Multiple DHT-22 sensor problem



  • Hi All,
    I'm building my first sensor project and now have hit a wall. My project is a multi temp and humidity sensor for egg incubators. I want to have 5 DHTs, 4 for incubators and 1 for room temp and humidity.

    I'm using an Arduino Nano for the sensors, Pi Ethernet gateway both using NRF24 radios. I have Home Assistant up and running as the controller.
    I started with the one DHT and have everything working, so the Arduino is fine, gateway is good, radios good and I can read them in HA. I then added two more DHTs, made my best guess at the code, this is my first attempt at EE, but it seemed to work! I watched HA for days checking the status of the three sensors, they were updating and reading fine. Although very inaccurate.

    Then I updated HA to the latest, a major update, and now I only can read 1 DHT at a time. I don't think it has anything to do with the HA update, but maybe I did something wrong in the sketch, so I'm basically starting over. I have now learned to save the sketches with better names - especially if they work. I just started to see if the SENSOR_TEMP_OFFSET was actually working for the three DHTs, that's going to be important. I think it first showed up as node 1, as in HA it was ****_1_0, *****_1_1, 1_2, and so on, each child was listed and was updating. Now it shows up as node 2, and in the debug it shows 2-2-000 etc.
    BTW, each DHT does work, I can comment out each data_ping, using the child nodes and they work. Just now it will only send the last pin.

    There might be something in the debug file that explains the problem, I do not know what all of it means. Maybe my sketch is totally wrong, but here is what I created-

    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached 
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    //#define MY_RS485
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 3
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET -5
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 4
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 10
    
    #define CHILD_ID_HUM 2
    #define CHILD_ID_TEMP 3
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 5
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 10
    
    #define CHILD_ID_HUM 4
    #define CHILD_ID_TEMP 5
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 30000;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 2;
    
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    DHT dht;
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      sendSketchInfo("IncubatorTempnHum", "1.1");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
    
      metric = getControllerConfig().isMetric;
    }
    
    
    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // 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(dht.getMinimumSamplingPeriod());
    }
    
    
    void loop()      
    {  
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
    
      // Get temperature from DHT library
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature != lastTemp || nNoUpdatesTemp == 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
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        // Reset no updates counter
        nNoUpdatesTemp = 0;
        temperature += SENSOR_TEMP_OFFSET;
        send(msgTemp.set(temperature, 1));
    
        #ifdef MY_DEBUG
        Serial.print("T: ");
        Serial.println(temperature);
        #endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp++;
      }
    
      // Get humidity from DHT library
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum || nNoUpdatesHum == 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
        lastHum = humidity;
        // Reset no updates counter
        nNoUpdatesHum = 0;
        send(msgHum.set(humidity, 1));
    
        #ifdef MY_DEBUG
        Serial.print("H: ");
        Serial.println(humidity);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum++;
      }
    
      // Sleep for a while to save energy
      sleep(UPDATE_INTERVAL); 
    }
    

    Here is the debug - I did see each DHT and child show in the monitor, before it broke. thanks for any help!
    0 MCO:BGN:INIT NODE,CP=RNNNA--,VER=2.1.1
    3 TSM:INIT
    4 TSF:WUR:MS=0
    11 TSM:INIT:TSP OK
    13 TSF:SID:OK,ID=2
    14 TSM:FPAR
    51 TSF:MSG:SEND,2-2-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    2058 !TSM:FPAR:NO REPLY
    2060 TSM:FPAR
    2096 TSF:MSG:SEND,2-2-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    2370 TSF:MSG:READ,0-0-2,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    2375 TSF:MSG:FPAR OK,ID=0,D=1
    4104 TSM:FPAR:OK
    4105 TSM:ID
    4106 TSM:ID:OK
    4108 TSM:UPL
    4111 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    4117 TSF:MSG:READ,0-0-2,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    4122 TSF:MSG:PONG RECV,HP=1
    4124 TSM:UPL:OK
    4126 TSM:READY:ID=2,PAR=0,DIS=1
    4130 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    4137 TSF:MSG:READ,0-0-2,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    4145 TSF:MSG:SEND,2-2-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.1.1
    4154 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    4202 TSF:MSG:READ,0-0-2,s=255,c=3,t=6,pt=0,l=1,sg=0:I
    4209 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=11,pt=0,l=17,sg=0,ft=0,st=OK:IncubatorTempnHum
    4218 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.1
    4227 TSF:MSG:SEND,2-2-0-0,s=4,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    4235 TSF:MSG:SEND,2-2-0-0,s=5,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    4240 MCO:REG:REQ
    4244 TSF:MSG:SEND,2-2-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    4250 TSF:MSG:READ,0-0-2,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    4255 MCO:PIM:NODE REG=1
    4257 MCO:BGN:STP
    4263 MCO:SLP:MS=2000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4269 MCO:SLP:TPD
    4271 MCO:SLP:WUP=-1
    4273 MCO:BGN:INIT OK,TSP=1
    4282 TSF:MSG:SEND,2-2-0-0,s=5,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:78.4
    T: 78.36
    4291 TSF:MSG:SEND,2-2-0-0,s=4,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:99.9
    H: 99.90
    4297 MCO:SLP:MS=30000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4302 MCO:SLP:TPD
    4304 MCO:SLP:WUP=-1
    4312 MCO:SLP:MS=30000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4317 MCO:SLP:TPD
    4318 MCO:SLP:WUP=-1
    4325 MCO:SLP:MS=30000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4330 MCO:SLP:TPD
    4332 MCO:SLP:WUP=-1
    4341 TSF:MSG:SEND,2-2-0-0,s=5,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:78.4
    T: 78.36
    4349 TSF:MSG:SEND,2-2-0-0,s=4,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:99.9
    H: 99.90
    4357 MCO:SLP:MS=30000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4362 MCO:SLP:TPD



  • Hi again,

    Well, I guess I found the solution, of course after my first post looking bad :-)
    I found another post by turborick which helped a lot. I do not know how the first sketch was working, but modified my sketch, defining each DHT and used the sensor offset that might be working. I'll have to do more tests. I left in all the sleep and other commands from the original, just added one for each DHT, again, it seems to work. But I'm crazy, who knows.
    Here is a working sketch for my three DHTs, I'll update if the offsets work. The incubators have to be 99.5 exactly, each sensor needs to be accurate for the alarms. Also the humidity needs to be good or it's useless.
    Here is the working sketch:

    #define MY_DEBUG
    #define MY_RADIO_NRF24
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    
    #define CHILD_ID_HUM1 1
    #define CHILD_ID_TEMP1 2
    #define DHT1_DATA_PIN 3
    
    #define SENSOR_TEMP1_OFFSET -2.5
    
    #define CHILD_ID_HUM2 3
    #define CHILD_ID_TEMP2 4
    #define DHT2_DATA_PIN 4
    
    #define SENSOR_TEMP2_OFFSET -12.5
    
    #define CHILD_ID_HUM3 5
    #define CHILD_ID_TEMP3 6
    #define DHT3_DATA_PIN 5
    
    #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;
    bool metric = true;
    
    MyMessage msgHum1(CHILD_ID_HUM1, V_HUM);
    MyMessage msgTemp1(CHILD_ID_TEMP1, V_TEMP);
    MyMessage msgHum2(CHILD_ID_HUM2, V_HUM);
    MyMessage msgTemp2(CHILD_ID_TEMP2, V_TEMP);
    MyMessage msgHum3(CHILD_ID_HUM3, V_HUM);
    MyMessage msgTemp3(CHILD_ID_TEMP3, V_TEMP);
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      sendSketchInfo("IncubatorTempAndHum", "1.1");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM1, S_HUM);
      present(CHILD_ID_TEMP1, S_TEMP);
      present(CHILD_ID_HUM2, S_HUM);
      present(CHILD_ID_TEMP2, S_TEMP);
      present(CHILD_ID_HUM3, S_HUM);
      present(CHILD_ID_TEMP3, S_TEMP);
    
      metric = getControllerConfig().isMetric;
    }
    
    
    void setup()
    {
      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 temperature from DHT library
      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
        nNoUpdatesTemp1++;
      }
    
      // 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); 
    }```


  • You have probably seen that the DHT-22 sensor promises an accuracy of +-0.5°C for temperature and +-2% for humidity. So, if are building almost a sort of life-support-system, you may want to think about redundancy, e.g. by joining 2-3 sensors per unit and taking their average value or calculating their relative deviation to avoid surprises and notify you about sensors going awry.



  • This post is deleted!


  • @exxamalte Hi,
    That is a good idea, at least having two DHT-22s for each incubator. I've been thinking how to program the average for each, then present that number to the gateway. Could have alarms in case one goes down and stuff. Sounds like fun.
    Now that my code is working and I'm getting real numbers from the three DHTs, they are accurate. Only .1 - .2 difference between them. So I'm happy with that.
    Thanks!



  • @Slimz Speaking of reliability (life support), I was searching for similar posts to what I am experiencing (again) and came across this one.

    I don't see this in the DHT-11s I've tested (dozens), but this is frequent in the DHT-22s (no doubt just my luck)... they dies, and then rise from the dead... Check this out from last night:

    alt text

    All yesterday, no output from the DHT-22. I tried different pins, and almost tried another library (using SimpleDHT now). I had a 10k resistor between pins 1&2 (Vcc & Data), all to no avail. Also, I couldn't remember if having Vcc on the data pin was normal or not-but it was there...

    I went to bed, a beaten man. Then, the Sensor Fairy (C)2017 came to visit at around 4:00am, and now I have 2 problems:

    1. Why it didn't work, and...
    2. Why it works now.

    Just sharing because this kind of behavior has been common with me and the DHT-22s, and in your situation may not be noticeable. Hopefully you have alerts for env values out of range. If it really matters, I use a trusty BME280.

    good luck!


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.