Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
robcazzaro opened this issue Nov 26, 2017 · 41 comments
Closed

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

robcazzaro opened this issue Nov 26, 2017 · 41 comments

Comments

@robcazzaro
Copy link

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 (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
Copy link

khjoen commented Nov 26, 2017 via email

@robcazzaro
Copy link
Author

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)

@beicnet
Copy link

beicnet commented Nov 26, 2017

@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
Copy link
Author

robcazzaro commented Nov 26, 2017

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
Copy link

beicnet commented Nov 26, 2017

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

@ronalLeiva
Copy link

@robcazzaro Thanks I had the same problem

@captainju
Copy link

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

@Salty-Doug
Copy link

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
Copy link
Author

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
Copy link

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

@VikIborra
Copy link

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
Copy link
Author

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link
Author

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
Copy link

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
Copy link

Ty @captainju you saved me.

@davejel
Copy link

davejel commented Oct 1, 2018

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
Copy link

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
Copy link

ghost commented Nov 26, 2018

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

@robcazzaro
Copy link
Author

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
Copy link

ghost commented Nov 28, 2018

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
Copy link
Author

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
Copy link

ghost commented Nov 28, 2018

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
Copy link

khjoen commented Nov 30, 2018

@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
Copy link

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
Copy link

yavimaya commented Dec 7, 2018

@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
Copy link

teverth commented Dec 21, 2018

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
Copy link

DIYGuy01 commented Feb 8, 2019

did not help me. Still nan
ESP01 + AOSONG AM2302

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

@khjoen
Copy link

khjoen commented Feb 10, 2019

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

@DIYGuy01
Copy link

DIYGuy01 commented Feb 10, 2019

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
Copy link

netixx commented Feb 15, 2019

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
Copy link

// 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
Copy link
Author

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
Copy link

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
Copy link

Your code fixed this issue. Thank you !!!

@sheepsy90
Copy link

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

@fontanon
Copy link

fontanon commented Aug 1, 2020

@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
Copy link

boumanb commented Mar 6, 2021

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
Copy link

GreaseMonkey88 commented Apr 13, 2021

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);
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests