Navigation

    • Register
    • Login
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. AterMentis
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    AterMentis

    @AterMentis

    0
    Reputation
    3
    Posts
    67
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    AterMentis Follow

    Best posts made by AterMentis

    This user hasn't posted anything yet.

    Latest posts made by AterMentis

    • Advanced combination script (OneWire+DHT+Relays) over serial usb to Pi runnung domoticz - HELP with timing and group ID

      Hi All,

      I would like to share my script i am using as an expansion shield for my domoticz home automation system. On this module i connect up to 10 DS18B20 (hardwired over the whole house on a star configuration using the Onewire protocol) as well as 3 DHT11 modules (2 bathrooms and a indoor garden) as well as 4 Finder brand relay modules to control 4 lights (2 for each bathroom). The choice of finde relays was done so that in a bathroom all the lights are interupted on 2 poles, hence the special relays from finder that switch a 5V PSU by using 4 2N2222A NGate transistors.

      This sketch is basically a combo from various other posts and scripts made by other users so all credit goes to them. The DS18B20 script qlso stores all chip IDs in the eeprom because i got sick and tired of how they would interchange inside of domoticz and thus jump from one sensor to the other.

      NOW my problem i am facing and also my cry for help:
      1)Is there anyone that can help me on the timing part of this script as i want to minimize delays caused by the data transfer of all the sensors. currently already miliseconds but still...
      2) MY biggest problem is the famous groupID issue within domoticz that i have found numerous posts about but cant seem to figure out or get working... All my DS18B20 show up seperatly now but all are grouped together even with the DHT sensors making them all show up as temp/humidity sensor (NOT OK). Also the DHT sensors are grouped wrong so the temperature and humidity are coupled wrong. In previous version of the script i got i working correctly but i lost it due to PC crash and am pretty stuck right now. I have tried stuff i found in other posts like spacing them apart in presentation (0-16 is for DS18B20 and 50-55 is for DHT with relays in between in 40 range) as well as making everything V_HUM but nothing seems to work....Any help or explaination on how to fix this would be greatly appreciated.

      Thx in advance

      /**
         The MySensors Arduino library handles the wireless radio link and protocol
         between your home built sensors/actuators and HA controller of choice.
         The sensors forms a self healing radio network with optional repeaters. Each
         repeater and gateway builds a routing tables in EEPROM which keeps track of the
         network topology allowing messages to be routed to nodes.
         Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
         Copyright (C) 2013-2015 Sensnology AB
         Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
         Documentation: http://www.mysensors.org
         Support Forum: http://forum.mysensors.org
         This program is free software; you can redistribute it and/or
         modify it under the terms of the GNU General Public License
         version 2 as published by the Free Software Foundation.
       *******************************
         DESCRIPTION
         Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
         http://www.mysensors.org/build/temp
         Enhanced Version to keep SensorID icluding a lot of ideas from leodesigner and hauswart (forum.fhem.de)
         Improvements:
         - it will remember a sensor index in EEPROM (2 bytes per sensor)
            in case if you need to replace or add new sensor to the 1Wire bus - all other sensors will keep own sensor index#
        Last modifications:
        - Revert back to standard Mysensor EEPROM storage (in line with leodesigner code base)
        - First ID for DS has to be defined
        - Bug fixed with not changed "spot_used" value
        - Present Dallas-Hardware-ID as comment (still not working!!!)
        - Improve reading of code by opting for some more subroutines
      */
      // Enable debug prints to serial monitor
      #define MY_DEBUG 
      // Enable and select radio type attached
      //#define MY_RADIO_NRF24
      //#define MY_RF24_PA_LEVEL RF24_PA_MIN              // This sets a low-power mode for the radio. Useful if you use the version with the bigger antenna, but don' want to power that from a separate source. It can also fix problems with fake Chinese versions of the radio.
      //#define MY_RADIO_RFM69
      // Enable serial gateway
      #define MY_GATEWAY_SERIAL
      #include <SPI.h>
      #include <MySensors.h>
      #include <DallasTemperature.h>
      #include <OneWire.h>
      #include <DHT.h>   
      
      /////////////////*CODE FOR DS18B20*/////////////////////////////
      #define COMPARE_TEMP 1 // Send temperature only if changed?
      #define ERASE_HASH // Clear EEPROM, if no 1w-device is present?
      #define SEND_ID // Send also Dallas-Addresses?
      #define ONE_WIRE_BUS 11 // Pin where dallase sensor is connected 
      #define MAX_ATTACHED_DS18B20 16
      #define EEPROM_DEVICE_ADDR_START  64     // start byte in eeprom for remembering our sensors
      #define EEPROM_DEVICE_ADDR_END    EEPROM_DEVICE_ADDR_START+MAX_ATTACHED_DS18B20*2
      
      uint8_t DS_First_Child_ID = 0; //First Child-ID to be used by Dallas Bus; set this to be higher than other Child-ID's who need EEPROM storage to avoid conflicts
      uint16_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
      OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
      DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
      float lastTemperature[MAX_ATTACHED_DS18B20];
      uint8_t numSensors = 0;
      DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address
      int  resolution = 12;
      int  conversionTime = 0;
      char* charAddr = "Check for faults";
      uint8_t ts_spot[MAX_ATTACHED_DS18B20]; // array for matching bus-id to EEPROM-index
      bool spot_used[MAX_ATTACHED_DS18B20]; // used spot array
      // Initialize temperature message
      MyMessage msgTemp(0, V_TEMP);
      #ifdef SEND_ID
      MyMessage msgId(0, V_ID);
      #endif
      boolean receivedConfig = false;
      boolean metric = true;
      
      /////////////////*CODE FOR DHT*/////////////////////////////
      #define CHILD_ID_HUM1 51
      #define CHILD_ID_TEMP1 50
      #define DHT1_DATA_PIN 12
      
      #define SENSOR_TEMP1_OFFSET 0
      
      #define CHILD_ID_HUM2 53
      #define CHILD_ID_TEMP2 52
      #define DHT2_DATA_PIN 5
      
      #define SENSOR_TEMP2_OFFSET 0
      
      #define CHILD_ID_HUM3 55
      #define CHILD_ID_TEMP3 54
      #define DHT3_DATA_PIN 6
      
      #define SENSOR_TEMP3_OFFSET 0
      
      // Force sending an update of the temperature after n sensor reads, so a controller showing the
      static const uint8_t FORCE_UPDATE_N_READS = 2;
      
      // Must be >1000ms for DHT22 and >2000ms for DHT11
      static const uint64_t UPDATE_INTERVAL = 30000;
      
      DHT dht1;
      DHT dht2;
      DHT dht3;
      
      float lastTemp1;
      float lastHum1;
      float lastTemp2;
      float lastHum2;
      float lastTemp3;
      float lastHum3;
      uint8_t nNoUpdatesTemp1;
      uint8_t nNoUpdatesHum1;
      uint8_t nNoUpdatesTemp2;
      uint8_t nNoUpdatesHum2;
      uint8_t nNoUpdatesTemp3;
      uint8_t nNoUpdatesHum3;
      
      MyMessage msgTemp1(CHILD_ID_TEMP1, V_TEMP);
      MyMessage msgHum1(CHILD_ID_HUM1, V_HUM);
      MyMessage msgTemp2(CHILD_ID_TEMP2, V_TEMP);
      MyMessage msgHum2(CHILD_ID_HUM2, V_HUM);
      MyMessage msgTemp3(CHILD_ID_TEMP3, V_TEMP);
      MyMessage msgHum3(CHILD_ID_HUM3, V_HUM);
      
      
      /////////////////*CODE FOR FINDER RELAYS*/////////////////////////////
      #define RELAY_PIN 7  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
      #define NUMBER_OF_RELAYS 4 // Total number of attached relays
      #define RELAY_ON 1  // GPIO value to write to turn on attached relay
      #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
      
      
      
      void before() {
        conversionTime = 750 / (1 << (12 - resolution));
        // Startup up the OneWire library
        sensors.begin();
        // requestTemperatures() will not block current thread
        sensors.setWaitForConversion(false);
        // Fetch the number of attached temperature sensors
        numSensors = sensors.getDeviceCount();
        // use the 1.1 V internal reference
        initialiseIdArray();
        for (int sensor=41, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS+40; sensor++, pin++) {
              // Then set relay pins in output mode
              pinMode(pin, OUTPUT);
              // Set relay to last known state (using eeprom storage)
              digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
          }
      }
      
      void presentation() {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("1WIRE SHIELD", "V2");
        // Present all sensors to controller
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          sensors.getAddress(tempDeviceAddress, i);
          Serial.print("Hardware presented: ");
          charAddr = addrToChar(tempDeviceAddress);
          Serial.println(charAddr);
          present(ts_spot[i], S_TEMP, charAddr);
          sensors.setResolution(tempDeviceAddress, resolution);
        }
        // Register all sensors to gw (they will be created as child devices)
        present(CHILD_ID_TEMP1, S_TEMP);
        present(CHILD_ID_HUM1, S_HUM);
        present(CHILD_ID_TEMP2, S_TEMP);
        present(CHILD_ID_HUM2, S_HUM);
        present(CHILD_ID_TEMP3, S_TEMP);
        present(CHILD_ID_HUM3, S_HUM);
      
        metric = getControllerConfig().isMetric;
      
          for (int sensor=41, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS+40; sensor++, pin++) {
              // Register all sensors to gw (they will be created as child devices)
              present(sensor, S_BINARY);
          }
      }
      
      void setup() {
      #ifdef SEND_ID
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          sensors.getAddress(tempDeviceAddress, i);
          //charAddr = addrToChar(tempDeviceAddress);
          //8 sorgt dafür, dass alle 16 Stellen übermittelt werden
          send(msgId.setSensor(ts_spot[i]).set(tempDeviceAddress, 8));
        }
      #endif
      
       dht1.setup(DHT1_DATA_PIN);
       dht2.setup(DHT2_DATA_PIN);
       dht3.setup(DHT3_DATA_PIN);
      
        // Sleep for the time of the minimum sampling period to give the sensor time to power up
        // (otherwise, timeout errors might occure for the first reading)
        sleep(dht1.getMinimumSamplingPeriod());
        sleep(dht2.getMinimumSamplingPeriod());
        sleep(dht3.getMinimumSamplingPeriod());
      
      }
      
      void loop() {
      
          // Force reading sensor, so it works also after sleep()
        dht1.readSensor(true);
        dht2.readSensor(true);
        dht3.readSensor(true);
        //Get Temp DHT1
        float temperature1 = dht1.getTemperature();
        if (isnan(temperature1)) {
          Serial.println("Failed reading temperature from DHT1!");
        } else if (temperature1 != lastTemp1 || nNoUpdatesTemp1 == FORCE_UPDATE_N_READS) {
          // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
          lastTemp1 = temperature1;
          if (!metric) {
            temperature1 = dht1.toFahrenheit(temperature1);
          }
          // Reset no updates counter
          nNoUpdatesTemp1 = 0;
          temperature1 += SENSOR_TEMP1_OFFSET;
          send(msgTemp1.set(temperature1, 1));
      
          #ifdef MY_DEBUG
          Serial.print("T: ");
          Serial.println(temperature1);
          #endif
        } else {
          // Increase no update counter if the temperature stayed the same
          nNoUpdatesTemp2++;
        }
        // Get humidity from DHT library
        float humidity1 = dht1.getHumidity();
        if (isnan(humidity1)) {
          Serial.println("Failed reading humidity from DHT1");
        } else if (humidity1 != lastHum1 || nNoUpdatesHum1 == FORCE_UPDATE_N_READS) {
          // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
          lastHum1 = humidity1;
          // Reset no updates counter
          nNoUpdatesHum1 = 0;
          send(msgHum1.set(humidity1, 1));
      
          #ifdef MY_DEBUG
          Serial.print("H: ");
          Serial.println(humidity1);
          #endif
        } else {
          // Increase no update counter if the humidity stayed the same
          nNoUpdatesHum1++;
        }
        float temperature2 = dht2.getTemperature();
        if (isnan(temperature2)) {
          Serial.println("Failed reading temperature from DHT2!");
        } else if (temperature2 != lastTemp2 || nNoUpdatesTemp2 == FORCE_UPDATE_N_READS) {
          // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
          lastTemp2 = temperature2;
          if (!metric) {
            temperature2 = dht2.toFahrenheit(temperature2);
          }
          // Reset no updates counter
          nNoUpdatesTemp2 = 0;
          temperature2 += SENSOR_TEMP2_OFFSET;
          send(msgTemp2.set(temperature2, 1));
      
          #ifdef MY_DEBUG
          Serial.print("T: ");
          Serial.println(temperature2);
          #endif
        } else {
          // Increase no update counter if the temperature stayed the same
          nNoUpdatesTemp2++;
        }
      
        // Get humidity from DHT library
        float humidity2 = dht2.getHumidity();
        if (isnan(humidity2)) {
          Serial.println("Failed reading humidity from DHT2");
        } else if (humidity2 != lastHum2 || nNoUpdatesHum2 == FORCE_UPDATE_N_READS) {
          // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
          lastHum2 = humidity2;
          // Reset no updates counter
          nNoUpdatesHum2 = 0;
          send(msgHum2.set(humidity2, 1));
      
          #ifdef MY_DEBUG
          Serial.print("H: ");
          Serial.println(humidity2);
          #endif
        } else {
          // Increase no update counter if the humidity stayed the same
          nNoUpdatesHum2++;
        }
        float temperature3 = dht3.getTemperature();
        if (isnan(temperature3)) {
          Serial.println("Failed reading temperature from DHT3!");
        } else if (temperature3 != lastTemp3 || nNoUpdatesTemp3 == FORCE_UPDATE_N_READS) {
          // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
          lastTemp3 = temperature3;
          if (!metric) {
            temperature3 = dht3.toFahrenheit(temperature3);
          }
          // Reset no updates counter
          nNoUpdatesTemp3 = 0;
          temperature3 += SENSOR_TEMP3_OFFSET;
          send(msgTemp3.set(temperature3, 1));
      
          #ifdef MY_DEBUG
          Serial.print("T: ");
          Serial.println(temperature3);
          #endif
        } else {
          // Increase no update counter if the temperature stayed the same
          nNoUpdatesTemp3++;
        }
      
        // Get humidity from DHT library
        float humidity3 = dht3.getHumidity();
        if (isnan(humidity3)) {
          Serial.println("Failed reading humidity from DHT3");
        } else if (humidity3 != lastHum3 || nNoUpdatesHum3 == FORCE_UPDATE_N_READS) {
          // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
          lastHum3 = humidity3;
          // Reset no updates counter
          nNoUpdatesHum3 = 0;
          send(msgHum3.set(humidity3, 1));
      
          #ifdef MY_DEBUG
          Serial.print("H: ");
          Serial.println(humidity3);
          #endif
        } else {
          // Increase no update counter if the humidity stayed the same
          nNoUpdatesHum3++;
        }
        
        // Sleep for a while to save energy
        sleep(UPDATE_INTERVAL); 
      
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
        // query conversion time and sleep until conversion completed
        // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
        wait(conversionTime);
        // Read temperatures and send them to controller
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          // Fetch and round temperature to one decimal
          float temperature = static_cast<float>(static_cast<int>((metric ? sensors.getTempCByIndex(i) : sensors.getTempFByIndex(i)) * 10.)) / 10.;
          // Only send data if temperature has changed and no error
      #if COMPARE_TEMP == 1
          if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
      #else
          if (temperature != -127.00 && temperature != 85.00) {
      #endif
            // Send in the new temperature
            send(msgTemp.setSensor(ts_spot[i]).set(temperature, 1));
            // Save new temperatures for next compare
            lastTemperature[i] = temperature;
          }
        }
        wait(SLEEP_TIME);
      }
      
      
        
      // Subroutines
      //##########################################################
      //
      void initialiseIdArray() {
        uint8_t knownSensors = 0;
      #ifdef ERASE_HASH
        if (numSensors < 1) {
          for (uint8_t i = EEPROM_DEVICE_ADDR_START; i < EEPROM_DEVICE_ADDR_END + 1; i++) {
            saveState(i, 0xFF); //0xFF seems to be better in line with mysensors standards, was 0x00
          }
          Serial.println("EEPROM cleared...");
        }
      #endif
        //initialise spot_used array to default false
        for (uint8_t i = 0; i < MAX_ATTACHED_DS18B20; i++) {
          spot_used[i] = false;
        }
        // first loop: filling Address-Array with IDs already stored, and clear used spot array
        for (uint8_t i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          sensors.getAddress(tempDeviceAddress, i);
          // check if we know this sensor
          int8_t sidx = getSensorIndex(tempDeviceAddress);
          if (sidx < 0) {
            ts_spot[i] = 0;
          }
          else {
            // we know this sensor
            ts_spot[i] = sidx + DS_First_Child_ID;
            spot_used[sidx] = true;
            knownSensors++;
          }
        }
      #ifdef MY_DEBUG
        Serial.println();
        Serial.print(F("# Stored Devices: "));
        Serial.println(knownSensors);
      #endif
        // second loop for filling Address-Array with IDs not stored yet
        for (uint8_t i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          sensors.getAddress(tempDeviceAddress, i);
          // check if we do not know this sensor yet
          if (ts_spot[i] == 0) {
            uint8_t k = getUnusedSpot();
            ts_spot[i] = k + DS_First_Child_ID;
            spot_used[k] = true;
            storeSensorAddr(tempDeviceAddress, k);
          }
        }
      #ifdef MY_DEBUG
        for (int i = 0; i < numSensors && i < MAX_ATTACHED_DS18B20; i++) {
          sensors.getAddress(tempDeviceAddress, i);
          Serial.println();
          Serial.print(i);
          Serial.print(F(" index: "));
          Serial.print(ts_spot[i]);
          Serial.print(F(" address: "));
          charAddr = addrToChar(tempDeviceAddress);
          Serial.println(charAddr);
      #endif
        }
      }
      
      // a simple hash function for 1wire address to reduce id to two bytes
      uint16_t simpleAddrHash(DeviceAddress a) {
        return ((a[1] ^ a[2] ^ a[3] ^ a[4] ^ a[5] ^ a[6]) << 8) + a[7];
      }
      
      // search for device address hash in eeprom
      // return -1 if not found
      int8_t getSensorIndex(DeviceAddress a) {
        uint16_t hash = simpleAddrHash(a);
        int8_t idx = -1;
        uint8_t aidx = 0;
        uint8_t ptr = EEPROM_DEVICE_ADDR_START;
        while (ptr < EEPROM_DEVICE_ADDR_END && idx == -1) {
          uint8_t hash1 = loadState(ptr);
          uint8_t hash2 = loadState(ptr + 1);
          if ( hash1 == (uint8_t)(hash >> 8) && hash2 == (uint8_t)(hash & 0x00FF)) {
            // found device index
            idx = aidx;
          }
          aidx++;
          ptr += 2;
        }
        return idx;
      }
      
      // search for first unused spot in eeprom
      uint8_t getUnusedSpot() {
        int8_t j = 0;
        while (spot_used[j] == true) {
          j++;
        }
        return j;
      }
      
      // save address hash in EEPROM under index
      void storeSensorAddr(DeviceAddress a, uint8_t index) {
        uint16_t hash = simpleAddrHash(a);
        uint8_t ptr = EEPROM_DEVICE_ADDR_START + index * 2;
        if (ptr < EEPROM_DEVICE_ADDR_END) {
          saveState(ptr,   hash >> 8);
          saveState(ptr + 1, hash & 0x00FF);
        }
      #ifdef MY_DEBUG
        Serial.print(F("storeSensorAddr under index: "));
        Serial.println(index);
      #endif
      }
      
      char* addrToChar(uint8_t* data) {
        String strAddr = String(data[0], HEX); //Chip Version; should be higher than 16
        byte first ;
        int j = 0;
        for (uint8_t i = 1; i < 8; i++) {
          if (data[i] < 16) strAddr = strAddr + 0;
          strAddr = strAddr + String(data[i], HEX);
          strAddr.toUpperCase();
        }
        for (int j = 0; j < 16; j++) {
          charAddr[j] = strAddr[j];
        }
        return charAddr;
        }
      
      
      
      void receive(const MyMessage &message)
      {
          // We only expect one type of message from controller. But we better check anyway.
          if (message.type==V_STATUS) {
              // Change relay state
              digitalWrite(message.sensor-41+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
              // Store state in eeprom
              saveState(message.sensor, message.getBool());
              // Write some debug info
              Serial.print("Incoming change for sensor:");
              Serial.print(message.sensor);
              Serial.print(", New status: ");
              Serial.println(message.getBool());
          }
      }
          
      
      posted in Domoticz
      AterMentis
      AterMentis
    • RE: Ethernet Gateway delay issue

      Hi mfalkvidd!

      The sketch i am using is the following and is derived from the ethernet gateway and includes relays buttons and a one wire bus. I have tried excluding all different parts from the sketch so that only the relays where present to make sure that no delays or millis type of factors would cause any issues but it all remains the same and the delay i observe ocasionally is still present.

      /**
       * The MySensors Arduino library handles the wireless radio link and protocol
       * between your home built sensors/actuators and HA controller of choice.
       * The sensors forms a self healing radio network with optional repeaters. Each
       * repeater and gateway builds a routing tables in EEPROM which keeps track of the
       * network topology allowing messages to be routed to nodes.
       *
       * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
       * Copyright (C) 2013-2015 Sensnology AB
       * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
       *
       * Documentation: http://www.mysensors.org
       * Support Forum: http://forum.mysensors.org
       *
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       *******************************
       *
       * REVISION HISTORY
       * Version 1.0 - Henrik Ekblad
       * 
       * DESCRIPTION
       * Example sketch for a "light switch" where you can control light or something 
       * else from both HA controller and a local physical button 
       * (connected between digital pin 3 and GND).
       * This node also works as a repeader for other nodes
       * http://www.mysensors.org/build/relay
       */ 
      
      
      // Enable debug prints to serial monitor
      #define MY_DEBUG
      
      // Enable and select radio type attached
      //#define MY_RADIO_NRF24
      //#define MY_RADIO_NRF5_ESB
      //#define MY_RADIO_RFM69
      //#define MY_RADIO_RFM95
      
      // Enable gateway ethernet module type
      #define MY_GATEWAY_W5100
      
      // W5100 Ethernet module SPI enable (optional if using a shield/module that manages SPI_EN signal)
      //#define MY_W5100_SPI_EN 4
      
      // Enable Soft SPI for NRF radio (note different radio wiring is required)
      // The W5100 ethernet module seems to have a hard time co-operate with
      // radio on the same spi bus.
      //#if !defined(MY_W5100_SPI_EN) && !defined(ARDUINO_ARCH_SAMD)
      //#define MY_SOFTSPI
      //#define MY_SOFT_SPI_SCK_PIN 14
      //#define MY_SOFT_SPI_MISO_PIN 16
      //#define MY_SOFT_SPI_MOSI_PIN 15
      //#endif
      
      // Enable UDP communication
      //#define MY_USE_UDP  // If using UDP you need to set MY_CONTROLLER_IP_ADDRESS below
      
      // Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
      #define MY_IP_ADDRESS 192,168,0,165
      
      // If using static ip you can define Gateway and Subnet address as well
      //#define MY_IP_GATEWAY_ADDRESS 192,168,0,1
      //#define MY_IP_SUBNET_ADDRESS 255,255,255,0
      
      // Renewal period if using DHCP
      //#define MY_IP_RENEWAL_INTERVAL 60000
      
      // The port to keep open on node server mode / or port to contact in client mode
      #define MY_PORT 5003
      
      // Controller ip address. Enables client mode (default is "server" mode).
      // Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere.
      //#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254
      
      // The MAC address can be anything you want but should be unique on your network.
      // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use.
      // Note that most of the Arduino examples use  "DEAD BEEF FEED" for the MAC address.
      #define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
      
      // Enable inclusion mode
      #define MY_INCLUSION_MODE_FEATURE
      // Enable Inclusion mode button on gateway
      //#define MY_INCLUSION_BUTTON_FEATURE
      // Set inclusion mode duration (in seconds)
      #define MY_INCLUSION_MODE_DURATION 60
      // Digital pin used for inclusion mode button
      //#define MY_INCLUSION_MODE_BUTTON_PIN  3
      
      // Set blinking period
      //#define MY_DEFAULT_LED_BLINK_PERIOD 300
      
      // Flash leds on rx/tx/err
      // Uncomment to override default HW configurations
      //#define MY_DEFAULT_ERR_LED_PIN 7  // Error led pin
      //#define MY_DEFAULT_RX_LED_PIN  8  // Receive led pin
      //#define MY_DEFAULT_TX_LED_PIN  9  // Transmit led pin
      
      #if defined(MY_USE_UDP)
      #include <EthernetUdp.h>
      #endif
      #include <Ethernet.h>
      #include <MySensors.h>
      #include <DallasTemperature.h>
      #include <OneWire.h>
      #include <Bounce2.h>
      
      /*DEFINITION OF TEMPSENS*/
      #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
      #define ONE_WIRE_BUS 2 // Pin where dallase sensor is connected 
      #define MAX_ATTACHED_DS18B20 16
      /*STUFF FOR TEMP */
      unsigned long MEASUREMENT_INTERVAL = 30000;       // Time to wait between reads (in milliseconds).
      OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
      DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
      float lastTemperature[MAX_ATTACHED_DS18B20];
      int numSensors=0;
      bool receivedConfig = false;
      bool metric = true;
      boolean CURRENTLY_MEASURING = true;               // Used to indicate when the time is right for a new measurement to be made.
      boolean CURRENTLY_CALCULATING = false;            // Used to bridge the time that is needed to calculate the temperature values by the Dallas library.
      unsigned long CURRENT_MILLIS = 0;                 // The millisecond clock in the main loop.
      unsigned long PREVIOUS_MEASUREMENT_MILLIS = 0;    // Used to remember the time of the last temperature measurement.
      int16_t CONVERSION_TIME = 0;                      // Used to store the time needed to calculate the temperature from measurements.
      // Initialize temperature message
      MyMessage msgTEMP(0,V_TEMP);
      
      
      /*RELAY CODE*/
      #define RELAY_PIN 3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
      #define NUMBER_OF_RELAYS 7 // Total number of attached relays
      #define RELAY_ON 0  // GPIO value to write to turn on attached relay
      #define RELAY_OFF 1 // GPIO value to write to turn off attached relay
      
      //BUTTON CODE
      #define CHILD_ID_B1 10
      #define BUTTON_PIN1  14  // Arduino Digital I/O pin for button/reed switch
      #define CHILD_ID_B2 11
      #define BUTTON_PIN2  15  // Arduino Digital I/O pin for button/reed switch
      #define CHILD_ID_B3 12
      #define BUTTON_PIN3  16  // Arduino Digital I/O pin for button/reed switch
      
      Bounce debouncerB1 = Bounce(); 
      Bounce debouncerB2 = Bounce(); 
      Bounce debouncerB3 = Bounce(); 
      int oldValueB1=-1;
      int oldValueB2=-1;
      int oldValueB3=-1;
      // Change to V_LIGHT if you use S_LIGHT in presentation below
      MyMessage msgBUTTON1(CHILD_ID_B1,V_LIGHT);
      MyMessage msgBUTTON2(CHILD_ID_B2,V_LIGHT);
      MyMessage msgBUTTON3(CHILD_ID_B3,V_LIGHT);
      
      void before()
      {
          for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
              // Then set relay pins in output mode
              pinMode(pin, OUTPUT);
              // Set relay to last known state (using eeprom storage)
              digitalWrite(pin, loadState(sensor+20)?RELAY_ON:RELAY_OFF);
          }
          // Startup up the OneWire library
        sensors.begin();
      }
      
      
      void setup()
      {
        for(int i=0;i<MAX_ATTACHED_DS18B20;i++){lastTemperature[i] = 0;} //Pre-filling array with 0's.
        sensors.setWaitForConversion(false);  // requestTemperatures() will not block current thread
        
       // Setup the button
        pinMode(BUTTON_PIN1,INPUT);
        pinMode(BUTTON_PIN2,INPUT);
        pinMode(BUTTON_PIN3,INPUT);
        // Activate internal pull-up
        digitalWrite(BUTTON_PIN1,HIGH);
        digitalWrite(BUTTON_PIN2,HIGH);
        digitalWrite(BUTTON_PIN3,HIGH);
      
        // After setting up the button, setup debouncer
        debouncerB1.attach(BUTTON_PIN1);
        debouncerB2.attach(BUTTON_PIN2);
        debouncerB3.attach(BUTTON_PIN3);
        debouncerB1.interval(5);
        debouncerB2.interval(5);
        debouncerB3.interval(5);
      }
      
      void presentation()
      {
          // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Mysensors Garage", "1");
         
         // Fetch the number of attached temperature sensors  
        numSensors = sensors.getDeviceCount();
      
        // Present all sensors to controller
        for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
           present(i, S_TEMP);
        }
      
      for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
              // Register all sensors to gw (they will be created as child devices)
              present(sensor+20, S_BINARY);
          }
      
          // Register binary input sensor to gw (they will be created as child devices)
        // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. 
        // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
        present(CHILD_ID_B1, S_LIGHT);  
        present(CHILD_ID_B2, S_LIGHT);
        present(CHILD_ID_B3, S_LIGHT);
      }
      
      void loop()
      {
       debouncerB1.update();
        // Get the update value
        int valueB1 = debouncerB1.read();
      
        if (valueB1 != oldValueB1) {
           // Send in the new value
           send(msgBUTTON1.set(valueB1==HIGH ? 1 : 0));
           oldValueB1 = valueB1;
        }
        debouncerB2.update();
        // Get the update value
        int valueB2 = debouncerB2.read();
      
        if (valueB2 != oldValueB2) {
           // Send in the new value
           send(msgBUTTON2.set(valueB2==HIGH ? 1 : 0));
           oldValueB2 = valueB2;
        }
        debouncerB3.update();
        // Get the update value
        int valueB3 = debouncerB3.read();
      
        if (valueB3 != oldValueB3) {
           // Send in the new value
           send(msgBUTTON3.set(valueB3==HIGH ? 1 : 0));
           oldValueB3 = valueB3;
      }
      
      CURRENT_MILLIS = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater.
      
      // Let's measure the temperature
        if(CURRENTLY_MEASURING == true && CURRENT_MILLIS - PREVIOUS_MEASUREMENT_MILLIS >= MEASUREMENT_INTERVAL){ // If we'e not calculating, and enough time has passed, we'll start again.
          CURRENTLY_MEASURING == false; // We're measuring, so let's take it off our to-do list.
          Serial.print("Starting new measurement(s)\n");
          PREVIOUS_MEASUREMENT_MILLIS = CURRENT_MILLIS; // Mark the time of the initialiation of this measurement.
          
        // Fetch temperatures from Dallas sensors
        sensors.requestTemperatures();
      
         // query conversion time. Apparently it takes a while to calculate?
          CONVERSION_TIME = sensors.millisToWaitForConversion(sensors.getResolution());
      
          CURRENTLY_CALCULATING = true; //Next step is to re-calculate the temperature again.
        }
      
      
        // Let's calculate and send the temperature
        if(CURRENTLY_CALCULATING == true && CURRENT_MILLIS > PREVIOUS_MEASUREMENT_MILLIS + CONVERSION_TIME ){
          CURRENTLY_CALCULATING = false; // check calculating off the to-do list too.
          for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {    // Loop through all the attached temperatur sensors.
          
            float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;   // Fetch and round temperature to one decimal
            
            Serial.print("Sensor #");
            Serial.print(i);
            Serial.print(" says it is ");
            Serial.print(temperature);
            Serial.print(" degrees\n");
            
            if(temperature != -127.00 && temperature != 85.00){ // avoid working with measurement errors.
              if (COMPARE_TEMP == 1 && lastTemperature[i] == temperature){
                Serial.print("Not sending it though, because it's the same temperature as before.\n");
              }
              else
              {
                Serial.print("Sending the temperature to the gateway.\n");
                send(msgTEMP.setSensor(i).set(temperature,1));
                lastTemperature[i] = temperature; // Save new temperatures to be able to compare in the next round.
              }
            }  
          }
          CURRENTLY_MEASURING = true; // Both tasks are done. Now we'll just wait for the measurement interval to be over.
        }
      }
      void receive(const MyMessage &message)
      {
          // We only expect one type of message from controller. But we better check anyway.
          if (message.type==V_STATUS) {
              // Change relay state
              digitalWrite(message.sensor-21+RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
              // Store state in eeprom
              saveState(message.sensor, message.getBool());
              // Write some debug info
              Serial.print("Incoming change for sensor:");
              Serial.print(message.sensor);
              Serial.print(", New status: ");
              Serial.println(message.getBool());
          }
      }
      

      All the relays are wired directly to the arduino uno which also has the ethernet shield installed on top of it. Both arduino, ethernet board and relay board are powered through an external DIN rail power supply providing 5V at 0.88A. I also have another ethernet gateway showing the same issues that is powered by a 12V psu feeding into a buck boost converter that supplies everything with 5V at 3A. Would you recommend setting this up differently?

      Both gateways are interfaced over ethernet where one has a 3m long cable and the other around 20m of cables. So cable length didn't seem like the issue to me.

      The issue only occurs on the ethernet gateways and not on the usb... i have had the gateway connected to the pc to view the changes coming in live from the serial monitor and there i also see nothing coming in when domotics displays the error and after a few seconds to minutes when the relay does switch i see the command arrive. So i don't think the gateway itself or the code is doing something wrong but for some reason between the command being sent from domoticz to it arriving at the gateway it gets lost?? and when domoticz repeats the command then sometimes it does come through???

      Ethernet lines are connected through a gigabit ethernet switch...

      Thank you already for all the help!

      posted in Domoticz
      AterMentis
      AterMentis
    • Ethernet Gateway delay issue

      Hi All,

      I currently have a full home automation system running on pi with domoticz and use arduino based mysensor nodes as expansions.
      Some of these go through USB communication but i also have several wired up as an ethernet gateway using a big W5100 ethernet shield.
      I used the example sketch from the mysensors site and just added devices and all is working well except for one issue...

      Sometimes when i switch a relay device from domoticz its instantaneous... but other times i get the following error messages:
      2019-09-20 20:54:42.414 Status: User: Admin initiated a switch command (854/Heating Zone3/On)
      2019-09-20 20:54:43.616 Error: MySensors: Repeating previous command (2/2)
      2019-09-20 20:54:44.817 Error: MySensors: Command not received by Node !! (node_id: 0, child_id: 3)

      If you wait a few seconds to a minute it will eventually send the command succesfully and all will work but this is quite an anoying delay that shouldn't be there in my opinion... I have been looking everywhere on forums and found input to other users about baudrate and how you should lower it from 115200 in the Myconfig.h file of the mysensors library and i have tried going to 9600 and 57600 but this did no change the situation for me...
      If anybody has any idea what else i could be doing wrong please feel free to share. Or if i can find it somewhere on this forum already written and i looked over it... my sincere apologies and thanks for pointing me in the right direction!

      Kind regards
      Jasper

      posted in Domoticz
      AterMentis
      AterMentis