adafruit / DHT-sensor-library

Arduino library for DHT11, DHT22, etc Temperature & Humidity Sensors
https://learn.adafruit.com/dht
MIT License
1.98k stars 1.42k forks source link

ESP8266 and DHT22: NAN errors using libraries >= 1.2.0 #94

Closed robcazzaro closed 5 years ago

robcazzaro commented 6 years ago

I'm using a few Wemos D1 and generic ESP8266-12 as temperature/humidity sensors feeding data to a service. All the ESP8266 devices are plain vanilla, and I use default settings when compiling.The DHT22 is connected to GPIO12, and I invoke the DHT library with

define DHTPIN 12

define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE, 15); //15 critical to stable readings

I have been using them for at least 2 years, using the original 1.0.0 DHT library, with no problems at all. I read the temperature/humidity every 10 seconds

I recently updated my devices with a newer version of my code, and I used Arduino 1.8.5 with newer libraries to ensure I have the latest and best. Same devices, same code. I immediately started getting a lot of NAN returned by the DHT library, and my devices skip roughly 15-20% of the reading cycles as a result.

After a long troubleshooting sessions, I narrowed the problem down to the DHT library version. With any version older than 1.2.0, everything works just fine. As soon as I use a newer library, I get the NAN errors. It looks as if the timing optimization in 9d7a9da8ae6cc5f6b6dd5be62d787f779e640a2a (the one that deprecated the parameter count, 15 in my case) doesn't work properly with the DHT22 and ESP8266 I'm using. There is a subtle timing error that at least in my case throws off some readings

I searched online for a similar issue, and found a lot of people with DHT22 and NAN issues, but none seemed to truly apply

It's hard to believe this issue was not discovered in ~2 years, but I have a solid repro in 4 devices at least, and I discovered it only because my code logs NAN results, while most people tend to write code that in case of a NAN repeats the DHT read right away, so might be masked

khjoen commented 6 years ago

it seems this is starting of death or end of life for this lib. Not much support for fundamental problems

Happy to help if anyone is ready to fork.

On 25 November 2017 at 22:00, robcazzaro notifications@github.com wrote:

I'm using a few Wemos D1 and generic ESP8266-12 as temperature/humidity sensors feeding data to a service. All the ESP8266 devices are plain vanilla, and I use default settings when compiling.The DHT22 is connected to GPIO12, and I invoke the DHT library with

define DHTPIN 12

define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE, 15); //15 critical to stable readings

I have been using them for at least 2 years, using the original 1.0.0 DHT library, with no problems at all. I read the temperature/humidity every 10 seconds

I recently updated my devices with a newer version of my code, and I used Arduino 1.8.5 with newer libraries to ensure I have the latest and best. Same devices, same code. I immediately started getting a lot of NAN returned by the DHT library, and my devices skip roughly 15-20% of the reading cycles as a result.

After a long troubleshooting sessions, I narrowed the problem down to the DHT library version. With any version older than 1.2.0, everything works just fine. As soon as I use a newer library, I get the NAN errors. It looks as if the timing optimization in 9d7a9da https://github.com/adafruit/DHT-sensor-library/commit/9d7a9da8ae6cc5f6b6dd5be62d787f779e640a2a (the one that deprecated the parameter count, 15 in my case) doesn't work properly with the DHT22 and ESP8266 I'm using. There is a subtle timing error that at least in my case throws off some readings

I searched online for a similar issue, and found a lot of people with DHT22 and NAN issues, but none seemed to truly apply

It's hard to believe this issue was not discovered in ~2 years, but I have a solid repro in 4 devices at least, and I discovered it only because my code logs NAN results, while most people tend to write code that in case of a NAN repeats the DHT read right away, so might be masked

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/adafruit/DHT-sensor-library/issues/94, or mute the thread https://github.com/notifications/unsubscribe-auth/ALSrTQ0REpdy4RqdwlPjPDRL6D7mbuJKks5s6NRjgaJpZM4Qqo1J .

robcazzaro commented 6 years ago

It turns out I did not discover something new: as I suspected, this is a well known and already reported issue (in many forums), one that has already been discussed and a solution is available. What is puzzling, is why this has not been addressed yet, at least for the ESP8266 platform. Even the frequency of the problem as previously reported matches mine

Here's the best link to explain the problem: https://github.com/adafruit/DHT-sensor-library/issues/48

And the solution is as simple as commenting out two lines (line 155 and 156 of the current library), and avoiding having the processor force the data line high on the DHT22:

// End the start signal by setting data line high for 40 microseconds.

 // digitalWrite(_pin, HIGH);
 // delayMicroseconds(40);

I have made that change in my local copy of the library, and so far have been reading hundreds of samples on 4 boards, not a single error. It's not what I would consider a solid proof yet, but with the un-modified 1.3.0 version I would never have been able to read this many samples without problems

I strongly recommend checking in the fix, if needed in a conditional block for the ESP8266 only (I cannot test on other processors, but I'm sure it's required for the ESP8266... and, based on the original description and the DHT22 datasheet, a required fix for all)

beicnet commented 6 years ago

@robcazzaro Yeah, same issue with me yesterday, but don't forget to change bellow that code:

pinMode(_pin, INPUT_PULLUP);
delayMicroseconds(10);

change delay to from 10 to 50

robcazzaro commented 6 years ago

In my case the change from 10 to 50 doesn't seem necessary, works both way, but I changed it anyway to 50. Thanks for the suggestion, @beicnet

At this point I have ~10k readings, not a single NAN... Pretty confident that this change is needed and much safer than the code currently in the library

I'm leaving this issue open (even if I have a fix now), for future consideration

beicnet commented 6 years ago

@robcazzaro I did the same thing by others proposition, so, I think it will not hurt anyway! Kappa

ronalLeiva commented 6 years ago

@robcazzaro Thanks I had the same problem

captainju commented 6 years ago

I had the same problem and I switched to another lib https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTstable

Salty-Doug commented 6 years ago

I am new to Arduino and microcontrollers. I had the nan problem with an ESP32 & DHT22 in Arduino IDE. I commented out the two lines above in DHT.cpp but when I downloaded the code I only saw "nan". Any ideas?

robcazzaro commented 6 years ago

Methinks that the timing of the much faster ESP32 does not work well with the DHT22 timing. I have really grown to dislike the DHT22, too sensitive to even small changes, and the protocol requires precise bitbanging

You could use the newer AM2320, which works with I2C protocols instead, and costs even less than a DHT22. I2C is much more reliable on all processors

Salty-Doug commented 6 years ago

Thanks captainju, I used the DHTstable library on my ESP32 and I am not seeing anymore "nan" readings.

VikIborra commented 6 years ago

I think that the problem is in the Chip. Last days I've received from China models of DHT22 with Chip ASAIR and is not 100% compatible. AOSONG is very good but ASAIR has problems.

robcazzaro commented 6 years ago

Try a different library, and you'll see it works. This library has a known bug and it's too timing dependent for modern IoT boards with different processors. It worked fine as long as everyone used the slow, original Arduino. You might also have a bad chip, but in my case (and many others) using a different library or patching the code bug solved the problem easily. It's not a chip problem

VikIborra commented 6 years ago

With Wemos D1 Mini (v2.0, 2.2, 2.3, 3.0) doesn't work. I've tried with diferent resistors, voltage (3.3/5), shield pro (dht22), ... only when I use AOSONG in same PCB Shield Pro received with ASAIR, works. I desolder ASAIR and I put AOSONG. I have tried all libraries in platformio. Same PCB with Arduino UNO, works but not in Wemos D1 Mini. 70% of ASAIR, fails by time out. I have changed "const int DHTLIB_TIMEOUT" in dht.h but nothing result. Thanks in advance.

robcazzaro commented 6 years ago

Have you tried commenting out the two lines 155-6 (and recompiling the library), as explained above in this thread? And possibly changing the delay from 10 to 50.

Without those changes, not even a DHT22 worked for me

In any case, the newer AM2320 is a much better choice these days :) or for overkill, a BME20, which also measures pressure

VikIborra commented 6 years ago

With PlatformIO and Libraries "DHT sensor library 1.3.0" and "Adafruit Unified Sensor 1.0.2".

Using example code : "DHT_Unified_Sensor" Change to: "DHT_Unified dht(DHTPIN, DHTTYPE, 50);" and 15 Comment lines in DHT.cpp: (155-156) // digitalWrite(_pin, HIGH); // delayMicroseconds(40);

I get good values 30% of times when I power off-on the wemos d1 mini, but never works when I use reset button or DEEP_SLEEP. It's very unstable. Any idea?

Thx in advance,

robcazzaro commented 6 years ago

In my case, the DHT22 sensors were very sensitive to RF noise from the ESP8266. With different ESP8266 modules, wiring and power supplies, I had all sort of weird problems, which also changed depending on which version of the Arduino ESP8266 core I used. DEEP_SLEEP also caused weird RF behavior which in turn caused problems.

My suggestions is to try different libraries like https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTstable and in the future stop using DHT22 and use the AM2320 instead (they cost more or less the same)

VikIborra commented 6 years ago

I have a workaround. Wemos DHT22 Shield uses D4 as data. D4 works fine with AOSONG Chip but fails with ASAIR. If you use D3, for example, AOSONG works and ASAIR works. https://abra-electronics.com/images/detailed/140/WEMOS-DHT22_3_.jpg

alexandruoliva commented 6 years ago

Ty @captainju you saved me.

davejel commented 6 years ago

Hi all I know this is an old thread but i'll put this solution here for anyone else having problems. i was also having the same problem with NAN errors using ESP8266-01 with DHT22, i tried pins: GPIO2, 3 Power cycling makes the sensor read normally !!!! ( i tried several different libs) After using a scope to watch the pins during upload both pins 2 & 3 have data at upload time which of course is not there if you power cycle My solution is to connect ground on DHT22 to GPIO0 which is held high at upload time. AND in setup before initializing DHT22 three lines:

digitalWrite(0, LOW); // sets output to gnd pinMode(0, OUTPUT); // switches power to DHT on delay(1000); // delay necessary after power up for DHT to stabilize

This works with all the libs i tried which were not working before. it appears that the data was scrambling the DHT's brain with the power on all of the time

cheers Dave

sergio-daniels commented 6 years ago

It turns out I did not discover something new: as I suspected, this is a well known and already reported issue (in many forums), one that has already been discussed and a solution is available. What is puzzling, is why this has not been addressed yet, at least for the ESP8266 platform. Even the frequency of the problem as previously reported matches mine

Here's the best link to explain the problem: #48

And the solution is as simple as commenting out two lines (line 155 and 156 of the current library), and avoiding having the processor force the data line high on the DHT22:

// End the start signal by setting data line high for 40 microseconds.

 // digitalWrite(_pin, HIGH);
 // delayMicroseconds(40);

I have made that change in my local copy of the library, and so far have been reading hundreds of samples on 4 boards, not a single error. It's not what I would consider a solid proof yet, but with the un-modified 1.3.0 version I would never have been able to read this many samples without problems

I strongly recommend checking in the fix, if needed in a conditional block for the ESP8266 only (I cannot test on other processors, but I'm sure it's required for the ESP8266... and, based on the original description and the DHT22 datasheet, a required fix for all)

Thanks, worked for me as well

ghost commented 5 years ago

I have a Wemos D1 R2 board and DHT22. None of the solutions given here are working for me.

robcazzaro commented 5 years ago

As I said before, I highly recommend to use better sensors than a DHT22, these days. The DHT22 is one of the most finicky thermo/humidity sensors out there

Having said that, though, the workaround I mention here works on just about any Wemos boards.

What do you mean "not working"? The original library works, just with too man NAN errors. If you don't get anything at all, the problem lies elsewhere, and I suggest you troubleshoot it one step at a time and possibly ask for help in another, more appropriate, forum (this is really not a support forum)

ghost commented 5 years ago

I have changed the sensor and I am using LM35 Temperature Sensor now. I have connected the 'Out' Pin of sensor to Pin A0 of Wemos D1 R2 for Analog reading. Before doing this I tested the A0 pin with following piece of code:

long int reading = 0;
float avg = 0.0;
void setup()
{
    Serial.begin(9600);
}
void loop() 
{
    for(int i = 0; i < 10; i++)
    {
        reading += analogRead(A0);
        delay(50);
    }
    avg = reading/10.0; 
    reading = 0; 
    Serial.print("Average Count: ");
    Serial.print(avg);
    delay(1000);
}

This code works quite well for potentiometer with full reading range from 0 to 1024 for a 0-3.3 V range. The same code does not give count at all for LM35 which is already tested OK with Arduino Uno. I know that LM35 is having operating voltage range of 4-30 V and that is why I connected it to the 5 V pin of Wemos D1 R2 because it would not harm the Wemos as the analog voltage transduced from nearly 26 degree Celsius at my place, would not exceed 3.3 V level of Wemos. The count remains in between 0 and 5 as per the code. I have also tested the same sensor on fresh Wemos D1 R2 board where I observed the same issue. So I am reporting this bug of LM35 error with Wemos. Kindly help.

Shaunak Agastya Vyas

robcazzaro commented 5 years ago

This is not a support forum, please ask your questions in the right forum (Wemos or ESP8266 Arduino

Closing this issue to avoid further unrelated questions

ghost commented 5 years ago

The issue is not resolved yet. DHT22 Sensor is not working with Wemos for me even after trying all the solutions given here. The way I have described the issue with LM35 speaks that I am not just an another beginner. Now, please solve both the issues of DHT22 and LM35. I am not a rebellion, so please do not block me on GitHub. I am just an idiot who is stuck up and needs help badly.

Shaunak Agastya Vyas

khjoen commented 5 years ago

@robcazzaro and @everybody. Can someone test this https://github.com/khjoen/DHT-sensor-library with your respective boards and comment on your results.

The code is a bit more complicated than the original adafruit lib, but I think it complies to the datasheet of the DHT like sensors. I do use pullup resistor and it works at least on arduino uno and mega.

I do not own other boards so comments regarding results on them are welcomed.

For those interested in performance timings, there is that framework I put together: https://github.com/khjoen/perf-tester that uses the DHT lib as an example.

Happy testing.

j-opificius commented 5 years ago

My solution is to connect ground on DHT22 to GPIO0 which is held high at upload time. AND in setup before initializing DHT22 three lines:

digitalWrite(0, LOW); // sets output to gnd pinMode(0, OUTPUT); // switches power to DHT on delay(1000); // delay necessary after power up for DHT to stabilize

This solution in conjunction with the two line fix to the library works for me so far, with a sample of one. My device is an ASAIR AM2302 hard wired onto a 3-pin adapter board with a 4k7 pull-up from data output to +ve and a cap across power. It came up with no coaxing after a software upload for each of 10 attempts, and also after several simple power cycles (no upload) using a micro-USB source. I'm going to build 8 units of this config, each powered from a 2 x AA 3V power source. I'll report if there are any issues.

yavimaya commented 5 years ago

@robcazzaro and @everybody. Can someone test this https://github.com/khjoen/DHT-sensor-library with your respective boards and comment on your results.

The code is a bit more complicated than the original adafruit lib, but I think it complies to the datasheet of the DHT like sensors. I do use pullup resistor and it works at least on arduino uno and mega.

I do not own other boards so comments regarding results on them are welcomed.

For those interested in performance timings, there is that framework I put together: https://github.com/khjoen/perf-tester that uses the DHT lib as an example.

Happy testing.

That worked flawlessly on a ESP32 and dht22. No errors at all. Thank you!!

teverth commented 5 years ago

In my case, I am using two DHT22 on an ESP32 and was getting lots of NAN readings like the others. I am using the currently published DHT22 library from the Adafruit website. I tracked the issue down to checksum errors. And in fact, what it was is that from time to time the highest bit on the checksum transmitted by the DHT22 was not set to "1" when it had to. All other bits coming from the DHT22 matched what the checksum needed to be. So now I am masking the checksum check with 0x7F instead of 0xFF and presto: Not a single NAN result anymore.

Before that change, I also followed the recommendations above to comment out the two lines below and change the value to 50 in the last line of this part:

//digitalWrite(_pin, HIGH); 
//delayMicroseconds(40);  

// Now start reading the data line to get the value from the DHT sensor.
pinMode(_pin, INPUT_PULLUP);
delayMicroseconds(50);  // Delay a bit to let sensor pull data line low.

But these changes alone did not fix the checksum issue and are possibly not related in my case to the solution. But masking for 0x7F did the trick, see below.

DEBUG_PRINTLN(F("Received:")); DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[4] & 0x7F, HEX); DEBUG_PRINT(F(" =? ")); DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0x7F, HEX);

// Check we read 40 bits and that the checksum matches. if ((data[4] & 0x7F) == ((data[0] + data[1] + data[2] + data[3]) & 0x7F)) { _lastresult = true; return _lastresult; } else { DEBUG_PRINTLN(F("Checksum failure!")); _lastresult = false; // set to true to ignore checksum err return _lastresult; }

I also so other people posting their NAN issues and saw that they had the very same mismatch of the checksums, i.e.: Calculated checksum byte = 0xCA but received checksum byte = 4A, the high bit missing. I think that perhaps the DHT22 signals something else with that top checksum bit that they don't tell us in the datasheet? But ignoring that bit does no harm. The values that I get from my DHT22 sensors are all good and matching with independently measured values. So this fix sorted it all for me.

DIYGuy01 commented 5 years ago

did not help me. Still nan ESP01 + AOSONG AM2302

But it works absolutely fine on Arduino Uno with the same lib

khjoen commented 5 years ago

Thanks @yavimaya and @DIYGuy01 for testing.
I have ordered ESP01 for testing.

DIYGuy01 commented 5 years ago

I was trying 3 days to achieve working DHT22 AOSONG with ESP-01 without success, trying various libs, changes in them, power source, boards, sensors etc. 9 months ago I made sketch the same ESP-01 with ASAIR DHT22 and it was working fine until this moment when I recompiled and changed DHT22 sensor vendor (I think during this time libs also have changed). New setup is working fine with Arduino Uno and Wemos D1 mini, but not with ESP-01. With debug on was getting constantly "DHT timeout waiting for start signal high pulse." Until I tried one trick which I found here on Github (do not remember where) Simple:

Void setup() {  
// workaround for DHT22 due to NAN error
  digitalWrite(DHTPIN, LOW); // sets output to gnd
  pinMode(DHTPIN, OUTPUT); // switches power to DHT on
  delay(1000); // delay necessary after power up for DHT to stabilize
  dht.begin();
....

dhd.begin() should follow instantly. If you put it in pre setup section- won't work. It works 100% not missing any reading in my case also ESP-01 is used with deepsleep().

This workaround helped me. Not going to deep dive in libs, I've got working solution but I hope it will give you direction what is wrong with lib, timings or new generation of chinese sensors :)

netixx commented 5 years ago

I have the ASAIR AM2302 (with shield and pull-up) and Wemos D1 mini (v3.0.0) and I can confirm @VikIborra suggestion to use D3 instead of the pre-wired D4 in the shield I received with it. I am using the latest v1.3.3 which has been published with fixes yesterday. With D4 I wasn't able to read any data at all!

I am still getting a few NAN, every 15 measurement or so using the test sketch provided with the library.

fabiom91 commented 5 years ago

// digitalWrite(_pin, HIGH); // delayMicroseconds(40);

Hi @robcazzaro I cannot find the two lines you quoted:

 // digitalWrite(_pin, HIGH);
 // delayMicroseconds(40);

In which file are them? .-.

robcazzaro commented 5 years ago

This issue was opened on version 1.2.0 of the library, in 2017. The current version of the library has changed a lot, and according to the comments for release 1.3.2, the ESP8266 timing issues have been addressed. So probably nothing here applies anymore :)

korovinn commented 4 years ago

Work for me. Try to do these:

  1. Connect DHT22 "+" to D0 on esp8266 and NOT to 3,3v
  2. Connect DHT22 "out" to D3 on esp8266
  3. Use such code in void setup ()

void setup() { Serial.begin(115200); pinMode(DHTPin, INPUT); pinMode(D0, OUTPUT); digitalWrite(D0, HIGH); dht.begin(); timer.setInterval(5000L, getdata); }

pentiumduck commented 4 years ago

Your code fixed this issue. Thank you !!!

sheepsy90 commented 4 years ago

That helped! Old lib works! It's a start!

fontanon commented 4 years ago

@robcazzaro and @everybody. Can someone test this https://github.com/khjoen/DHT-sensor-library with your respective boards and comment on your results.

The code is a bit more complicated than the original adafruit lib, but I think it complies to the datasheet of the DHT like sensors. I do use pullup resistor and it works at least on arduino uno and mega.

I do not own other boards so comments regarding results on them are welcomed.

For those interested in performance timings, there is that framework I put together: https://github.com/khjoen/perf-tester that uses the DHT lib as an example.

Happy testing.

Worked like a charm to me with Heltec WiFi LoRa 32 + DHT22 (AM23D2). I came from this tutorial: https://github.com/enzof6/arduino-lmic-for_ESP32 and end up with the NaN reading errors. Thanks for sharing.

boumanb commented 3 years ago

Work for me. Try to do these:

1. Connect DHT22 "+" to D0 on esp8266 and NOT to 3,3v

2. Connect DHT22 "out" to D3 on esp8266

3. Use such code in void setup ()

void setup() { Serial.begin(115200); pinMode(DHTPin, INPUT); pinMode(D0, OUTPUT); digitalWrite(D0, HIGH); dht.begin(); timer.setInterval(5000L, getdata); }

Thank you. Any explanation?

GreaseMonkey88 commented 3 years ago

I had the same problem using a DHT22/ESP8266(WemosD1Mini) for outdoor measurements connected to the 3.3V pin. After 24h or sometimes just hours I got NaN readings. So I sent the MCU to sleep for just 45s around every hour - that seems to work so far:

if (millis() >= 3600e3) // DeepSleep to "reset" the DHT22 sensor. Connect pins D0 + RST
  {
    ESP.deepSleep(45e6);
  }