From 5c329713fe8f91595d2992fd8c772d38c10e51ff Mon Sep 17 00:00:00 2001 From: amunra68 <37980036+amunra68@users.noreply.github.com> Date: Sun, 27 Jun 2021 08:45:57 +0200 Subject: [PATCH] Update xsns_06_dht.ino the DHT22/AM2301 did not work on Sonoff S20 and NodeMCU (possibly microsecond delay not exact enough??) and gave only "null" values for temperature and humidity. So I changed the way to determine if a bit is "0" or "1" by measuring the time in microseconds until state changes. If time > 50 usec (in data sheet it should be 80 usec), it is recognized as "1", otherwise (a "0" should be 26-28 usec by specs from data sheet) it is treated as "0". Also, the old version omitted the first bit (by waiting the sequence 0 - 1 - 0, I have changed it to the only first "0" This change has been tested on Sonoff S20 (on GPIO 3) and on NodeMCU (GPIO 2) on Tasmota version 9.3.1.4 (on version 9.5. it should make no difference) with a DHT22 with included pull-up resistor --- tasmota/xsns_06_dht.ino | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index a022eb410..ff71417e3 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -47,18 +47,21 @@ struct DHTSTRUCT { float h = NAN; } Dht[DHT_MAX_SENSORS]; -bool DhtWaitState(uint32_t sensor, uint32_t level) +// changed from bool to unsigned long returning the time to wait until state changes +unsigned long DhtWaitState(uint32_t sensor, uint32_t level) { unsigned long timeout = micros() + 100; + unsigned long startms = micros(); + while (digitalRead(Dht[sensor].pin) != level) { if (TimeReachedUsec(timeout)) { AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); - return false; + return 0; // return 0 (==false for compatibility) if timeout reached } delayMicroseconds(1); } - return true; + return micros()-startms; } bool DhtRead(uint32_t sensor) @@ -78,7 +81,8 @@ bool DhtRead(uint32_t sensor) break; case GPIO_DHT22: // DHT21, DHT22, AM2301, AM2302, AM2321 // delay(2); // minimum 1ms - delayMicroseconds(2000); // See https://github.com/arendst/Tasmota/pull/7468#issuecomment-647067015 +// delayMicroseconds(2000); // See https://github.com/arendst/Tasmota/pull/7468#issuecomment-647067015 + delayMicroseconds(1100); // changed to Arduino DHT library value break; case GPIO_SI7021: // iTead SI7021 delayMicroseconds(500); @@ -133,14 +137,12 @@ bool DhtRead(uint32_t sensor) uint32_t i = 0; noInterrupts(); - if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + if (DhtWaitState(sensor, 0)) { // only wait for one state change to 0 for (i = 0; i < 40; i++) { if (!DhtWaitState(sensor, 1)) { break; } - delayMicroseconds(32); // Was 30 - if (digitalRead(Dht[sensor].pin)) { - dht_data[i / 8] |= (1 << (7 - i % 8)); - } - if (!DhtWaitState(sensor, 0)) { break; } + int wt = DhtWaitState(sensor,0); // determine time to change state + if(wt==0) break; + if(wt>50) dht_data[i / 8] |= (1 << (7 - i % 8)); // if longer than 50 usec then 1, else 0 } } interrupts();