More than one DTH in one sketch - problem



  • Hi guys. Please help I struggle with this problem for a while. I searched the forum but I cannot find a solution that worked for me...
    I've created one sketch that contains motion sensors, reeds, DHT22 and relays. Serial connection via USB. My goal is to have more sensors (but always from this 4 categories). This is a part of my Smart Home solution, so each DHT will be wired and placed on each room (my goal is to have at least 6 DHT's for one Arduino Mega).

    Everything works fine - besides DHT22. I have 3 of them in the sketch. The first one works ok, but second and third don't fire.
    When I use the same "fire time", like below:

    unsigned long timeDHT1 = 30000; // 30 seconds
    unsigned long timeDHT2 = 30000; // 30 seconds
    unsigned long timeDHT3 = 30000; // 30 seconds

    The system (i use Home Assistant but this is not important) shows 3 DHT's, but they have the same Temperature and Humidity (so the data comes for one DHT and copied it to DHT2 and 3).

    When I change the times, for example

    unsigned long timeDHT1 = 30000; // 30 seconds
    unsigned long timeDHT2 = 31000; // 31 seconds
    unsigned long timeDHT3 = 32000; // 32 seconds

    The system update only the first DHT. 2nd and 3rd are visible, but they don't update. Please help. The sketch is below:

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    #define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // 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 
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <Bounce2.h>
    #include <DHT.h> // DHT11, DHT22 sensors
    
    // ------- PINS DEFINITION
    
    // RELAYS
    // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    // Relay for first floor - 10 pcs (Przelaczniki SSR - pierwsze pietro)
    #define RELAY_PIN_1 22
    
    // Buttons for Relays - to use normal wall switches (Przyciski / laczniki scienne - pierwsze pietro)
    #define BUTTON_PIN A0 
    
    #define NUMBER_OF_RELAYS 10 // 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
    
    // Arduino Digital I/O pin for button/reed switch
    // Reeds 
    #define REED_PIN_1 5
    
    
    // PIR  SENSORS
    uint32_t SLEEP_TIME = 1000; // 120000; // Sleep time between reports (in milliseconds)
    #define DIGITAL_INPUT_SENSOR1 22   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define DIGITAL_INPUT_SENSOR2 23
    #define SLEEP_NODE true
    
    // DHT22
    #define DHTPIN 4        // Broche sur laquelle est branché le DHT / what pin we're connected to
    #define DHTTYPE DHT22   // DHT 22  (AM2302), DHT11
    
    #define DHTPIN2 24        // Broche sur laquelle est branché le DHT / what pin we're connected to
    #define DHTTYPE2 DHT22   // DHT 22  (AM2302), DHT11
    
    #define DHTPIN3 25        // Broche sur laquelle est branché le DHT / what pin we're connected to
    #define DHTTYPE3 DHT22   // DHT 22  (AM2302), DHT11
    
    // ------- Data for Motion sensor
    
    int oldValueA = 0;
    int oldValueB = 0;
    
    bool stateA = false;
    bool stateB = false;
    
    unsigned long timeDHT1 = 30000; // 30 seconds
    unsigned long timeDHT2 = 31000; // 30 seconds
    unsigned long timeDHT3 = 32000; // 30 seconds
    
    unsigned long actualTime = 0;
    unsigned long recentTimeHum1 = 0;
    
    unsigned long actualTime2 = 0;
    unsigned long recentTimeHum2 = 0;
    
    unsigned long actualTime3 = 0;
    
    unsigned long recentTimeHum3 = 0;
    
    // Initialize DHT sensor
    float lastTemp;
    float lastTemp2;
    float lastTemp3;
    
    float lastHum;
    float lastHum2;
    float lastHum3;
    
    boolean metric = true;
    
    // for reed switch
    int oldValue=-1;
    
    bool state = false;
    
    // Relay for save state inside Arduino's EEPROM
    bool loadedState1 = false;
    
    bool initialValueSent = false;
    
    // ------- CHILD IDs 
    
    // REEDS
    #define CHILD_ID_REED1 0   // Id of the sensor child
    
    // Define CHILD_IDs
    #define CHILD_ID_TEMP1 1 // Id of the sensor child
    #define CHILD_ID_HUM1 2 // Id of the sensor child
    
    #define CHILD_ID_MOTION1 3   // Id of the sensor child
    #define CHILD_ID_MOTION2 4 // Id of the sensor child
    
    #define CHILD_ID_RELAY1 5 // Id of the sensor child
    
    #define CHILD_ID_TEMP2 6 // Id of the sensor child
    #define CHILD_ID_HUM2 7 // Id of the sensor child
    
    #define CHILD_ID_TEMP3 8 // Id of the sensor child
    #define CHILD_ID_HUM3 9 // Id of the sensor child
    
    // ------- 
    
    void before()
    {
      for (int sensor=1, pin=RELAY_PIN_1; 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)?RELAY_ON:RELAY_OFF);
      }
    }
    
    // Reed switches needs debouncers
    Bounce debouncer_reed1 = Bounce();
    
    //Relays switched - don't need debouncers
    Bounce debouncer_relay1 = Bounce();
    Bounce debouncer = Bounce();
    
    // Debouncer for Motion sensor
    Bounce debouncerA = Bounce();
    Bounce debouncerB = Bounce();
    
    // Initialize Relay
    MyMessage msg(CHILD_ID_RELAY1, V_STATUS);
    
    // Initialize reed switches
    MyMessage msgReed1(CHILD_ID_REED1, V_TRIPPED);
    
    
    // Initialize DHT22
    MyMessage msgTemp(CHILD_ID_TEMP1, V_TEMP);
    MyMessage msgHum(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);
    
    // Initialize motion message
    MyMessage msg_motion1(CHILD_ID_MOTION1, V_TRIPPED);
    MyMessage msg_motion2(CHILD_ID_MOTION2, V_TRIPPED);
    
    
    void setup() {
    
       // Setup locally attached sensors
      delay(100); 
    
       // Setup the button.
      pinMode(BUTTON_PIN, INPUT_PULLUP);
      // After setting up the button, setup debouncer.
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
      debouncer_relay1.attach(RELAY_PIN_1);
      debouncer_relay1.interval(5);
      // Setup the button
      pinMode(REED_PIN_1,INPUT_PULLUP);
      debouncer_reed1.attach(REED_PIN_1);
      debouncer_reed1.interval(10);
     
      // Make sure relays are off when starting up
      digitalWrite(RELAY_PIN_1, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN_1, OUTPUT);
    
      // Set relay to last known state (using eeprom storage) 
      loadedState1 = loadState(CHILD_ID_RELAY1);
    
      
      // setup debouncer for Reed switch
      debouncer_reed1.attach(REED_PIN_1);
      debouncer_reed1.interval(5);
    
      pinMode(REED_PIN_1,INPUT);
      digitalWrite(REED_PIN_1,HIGH);
    
      // Setup PIR Motion sensor "button"
      pinMode(DIGITAL_INPUT_SENSOR1, INPUT_PULLUP); // Setup the button Activate internal pull-up
      pinMode(DIGITAL_INPUT_SENSOR2, INPUT_PULLUP); //  sets the motion sensor digital pin as input / Setup the button Activate internal pull-up
      
        // setup debouncer for motion sensor
      debouncerA.attach(DIGITAL_INPUT_SENSOR1);
      debouncerA.interval(5);
    
      debouncerB.attach(DIGITAL_INPUT_SENSOR2);
      debouncerB.interval(5);
      
    }
    
    void presentation()  {
      sendSketchInfo("Arduino5", "1.0");
      
      // Register all sensors to gw (gateway - they will be created as child devices)
      present(CHILD_ID_RELAY1, S_BINARY);
      
      present(CHILD_ID_REED1, S_DOOR);  
    
      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);  
      
      present(CHILD_ID_MOTION1, S_MOTION);
      present(CHILD_ID_MOTION2, S_MOTION);
    
    }
    
    void loop() {
    
    actualTime = millis();
    
      // --- DHT22 SENSOR1 
      if (actualTime - recentTimeHum1 >= timeDHT1) {
    
        recentTimeHum1 = actualTime;
        // DHT sensor
        DHT dht(DHTPIN, DHTTYPE); // Creation of a dht object in the loop otherwise the values are not measured on awakening
        float temperature = dht.readTemperature();
        float humidity = dht.readHumidity();
        if (isnan(temperature)) {
          //Serial.println("Cannot read DHT temperature");
        } else {
          if (temperature != lastTemp) {
            lastTemp = temperature;
            if (!metric) {
              temperature = dht.readTemperature(true);
            }
    
            //Serial.print("T: ");
            //Serial.print(temperature);
            //Serial.print(" | H: ");
            //Serial.println(humidity);
            send(msgTemp.set(temperature, 1));
            send(msgHum.set(humidity, 1));
          } else {
            //Serial.println("Temperature doesn't change => don't update changes");
            //Serial.print("T: ");
            //Serial.print(temperature);
            //Serial.print(" | H: ");
            //Serial.println(humidity);
            send(msgTemp.set(temperature, 1));
            send(msgHum.set(humidity, 1));
          }
        }
    
      }    
      // --- DHT22 SENSOR END
    
      // --- DHT22 SENSOR2
      if (actualTime2 - recentTimeHum2 >= timeDHT2) {
    
        recentTimeHum2 = actualTime2;
        // DHT2 sensor
        DHT dht2(DHTPIN2, DHTTYPE2); // Creation of a dht object in the loop otherwise the values are not measured on awakening
        float temperature2 = dht2.readTemperature();
        float humidity2 = dht2.readHumidity();
        if (isnan(temperature2)) {
          //Serial.println("Cannot read DHT temperature");
        } else {
          if (temperature2 != lastTemp2) {
            lastTemp2 = temperature2;
            if (!metric) {
              temperature2 = dht2.readTemperature(true);
            }
    
            send(msgTemp2.set(temperature2, 1));
            send(msgHum2.set(humidity2, 1));
          } else {
            send(msgTemp2.set(temperature2, 1));
            send(msgHum2.set(humidity2, 1));
          }
        }
    
      }    
      // --- DHT22 SENSOR END
    
      // --- DHT22 SENSOR3
      if (actualTime3 - recentTimeHum3 >= timeDHT3) {
    
        recentTimeHum3 = actualTime3;
        // DHT3 sensor
        DHT dht3(DHTPIN3, DHTTYPE3); // Creation of a dht object in the loop otherwise the values are not measured on awakening
        float temperature3 = dht3.readTemperature();
        float humidity3 = dht3.readHumidity();
        if (isnan(temperature3)) {
          //Serial.println("Cannot read DHT temperature");
        } else {
          if (temperature3 != lastTemp3) {
            lastTemp3 = temperature3;
            if (!metric) {
              temperature3 = dht3.readTemperature(true);
            }
    
            send(msgTemp3.set(temperature3, 1));
            send(msgHum3.set(humidity3, 1));
          } else {
            send(msgTemp3.set(temperature3, 1));
            send(msgHum3.set(humidity3, 1));
          }
        }
    
      }    
      // --- DHT22 SENSOR END
    
      // ---- MOTION SENSOR START
    
      debouncerA.update();
      // Get the update value
      int valueA = debouncerA.read();
    
      if (valueA != oldValueA) {
        // Send in the new value
        send(msg_motion1.set(valueA == HIGH ? 1 : 0)); // Send tripped value to gw
        oldValueA = valueA;
        wait(5);
      }    
    
      debouncerB.update();
      // Get the update value
      int valueB = debouncerB.read();
    
      if (valueB != oldValueB) {
        // Send in the new value
        send(msg_motion2.set(valueB == HIGH ? 1 : 0)); // Send tripped value to gw
        oldValueB = valueB;
        wait(5);
      }  
    
     // --- MOTION SENSOR END
     
      if (!initialValueSent) {
        //Serial.println("Sending initial value");
        send(msg.set(loadedState1?RELAY_ON:RELAY_OFF));
        //Serial.println("Requesting initial value from controller");
    
      // Reed Switch
        int value1 = debouncer_reed1.read();
        send(msgReed1.set(value1==HIGH ? 1 : 0));
        wait(5);
    
        request(CHILD_ID_RELAY1, V_STATUS);
        request(CHILD_ID_REED1, V_TRIPPED);
        
        wait(2000, C_SET, V_STATUS);
    
      }
      // Send locally attached sensor data here 
      if (debouncer.update()) {
        // Get the update value.
        int value = debouncer.read();
        // Send in the new value.
        if(value != oldValue){
             saveState(CHILD_ID_RELAY1, !loadState(CHILD_ID_RELAY1));
             digitalWrite(RELAY_PIN_1, loadState(CHILD_ID_RELAY1)?RELAY_ON:RELAY_OFF);
             send(msg.set(loadState(CHILD_ID_RELAY1)));
     
            oldValue = value;
        }
      }
    
    
    
       // Send locally attached sensor data here  
       if (debouncer_reed1.update()) {
          // reed
         // Get the update value
        int value = debouncer_reed1.read();
          if (value != oldValue) {
             // Send in the new value
             send(msgReed1.set(value==HIGH ? 1 : 0));
             oldValue = value;
          }
       }
    
          
    }
    
    void receive(const MyMessage &message) {
      if (message.isAck()) {
         //Serial.println("This is an ack from gateway");
      }
    
      if (message.type == V_STATUS) {
        if (!initialValueSent) {
          //Serial.println("Receiving initial value from controller");
          initialValueSent = true;
        }
    
        switch (message.sensor) {
          case CHILD_ID_RELAY1:
            loadedState1 =  message.getBool();
            digitalWrite(RELAY_PIN_1, loadedState1 ? RELAY_ON : RELAY_OFF);
            saveState(CHILD_ID_RELAY1, loadedState1);
            send(msg.set(loadedState1?RELAY_ON:RELAY_OFF));
            break;
    
    /*
          case CHILD_ID_RELAY2:
            loadedState2 = message.getBool();
            digitalWrite(RELAY_PIN_2, loadedState2 ? RELAY_ON : RELAY_OFF);
            saveState(CHILD_RELAY2, loadedState2);
            send(msg2.set(loadedState2?RELAY_ON:RELAY_OFF));
            break;
            */
        }
     /* Remove debug - not needed in Home Assistant
        // Write some debug info
        Serial.print("Incoming change for sensor:");
        Serial.print(message.sensor);
        Serial.print(", New status: ");
        Serial.println(message.getBool());
    */
    
      }
    
    }
    
    

  • Mod

    @pl_rekin Creating the dht instances within the loop is unconventional. I would vouch to create them in global context only once.
    Also, I don't know which dht library you're using, but most of the time you need to call begin() on the dht instances before using them.



  • @Yveaux I tried to declare variable like
    DHT dht1;
    DHT dht2;
    DHT dht3;

    Then in void setup() setup DHT's but my DHT library throw errors 🙂 error: no matching function for call to 'DHT::DHT()').

    I use standard DHT library downloaded yesterday from Arduino INO library (I cannot check version right now)...



  • @pl_rekin Below are the bits you need to get this to work. Taken from my fridge/freezer sketch with all the confusing LCD and other stuff removed so you can see the basic set up of DHT and how to use.

    #include <DHT.h>
    
    #define CHILD_ID_FGEHUM 0
    #define CHILD_ID_FGETEMP 2
    #define CHILD_ID_FZRHUM 1
    #define CHILD_ID_FZRTEMP 3
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    
    unsigned long last_sent_time = 0;
    unsigned long sent_time = 5 * 60000;
    
    bool metric = true;
    
    DHT dht;    //Fridge
    DHT dht1;   //Freezer
    
    void setup() {
    
      dht.setup(7);  // Fridge data pin 7
      dht1.setup(6); // Freezer data pin 6
    
     //sensor fridge
      delay(dht.getMinimumSamplingPeriod());
      fgetemp = dht.getTemperature();
      
      //sensor freezer
      delay(dht1.getMinimumSamplingPeriod());
      fzrtemp = dht1.getTemperature();
      }
    
    void loop() {
    
      if (millis() - last_display_time >= display_time) {
        last_display_time = millis();
        //sensor fridge
        delay(dht.getMinimumSamplingPeriod());
        fgehum = dht.getHumidity();
        fgetemp = dht.getTemperature();
       
        //sensor freezer
        delay(dht1.getMinimumSamplingPeriod());
        fzrhum = dht1.getHumidity();
        fzrtemp = dht1.getTemperature();
       
    }
    

    It is important to fully read and comply with the instructions here.... https://www.mysensors.org/build/humidity
    Especially the bit about installing the modified library or you will still face issues.

    My build has been running > 5 years, so it is a tested method.



  • Thanx @skywatch I will try to apply this to my sketch and I come back 🙂

    BTW - this fridge / freezer looks interesting. Good idea. You put your DHT inside freezer wired with cable, or battery?



  • @pl_rekin Only put the sensors in the fridge or freezer. Everything else is on top of fridge/freezer inc AC-DC 5V power, all in plastic boxes. I also put an LCD display in the fridge door to see all the data at a glance.

    If I were to do this again I would try HTU21D sensors instead, I keep meaning to change the DHT's to HTU's , but never seem to get around to it. 😞


 

199
Online

8.7k
Users

9.5k
Topics

99.5k
Posts