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
This commit is contained in:
amunra68 2021-06-27 08:45:57 +02:00 committed by GitHub
parent 80f18a53e1
commit 5c329713fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -47,18 +47,21 @@ struct DHTSTRUCT {
float h = NAN; float h = NAN;
} Dht[DHT_MAX_SENSORS]; } 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 timeout = micros() + 100;
unsigned long startms = micros();
while (digitalRead(Dht[sensor].pin) != level) { while (digitalRead(Dht[sensor].pin) != level) {
if (TimeReachedUsec(timeout)) { if (TimeReachedUsec(timeout)) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE),
(level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW);
return false; return 0; // return 0 (==false for compatibility) if timeout reached
} }
delayMicroseconds(1); delayMicroseconds(1);
} }
return true; return micros()-startms;
} }
bool DhtRead(uint32_t sensor) bool DhtRead(uint32_t sensor)
@ -78,7 +81,8 @@ bool DhtRead(uint32_t sensor)
break; break;
case GPIO_DHT22: // DHT21, DHT22, AM2301, AM2302, AM2321 case GPIO_DHT22: // DHT21, DHT22, AM2301, AM2302, AM2321
// delay(2); // minimum 1ms // 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; break;
case GPIO_SI7021: // iTead SI7021 case GPIO_SI7021: // iTead SI7021
delayMicroseconds(500); delayMicroseconds(500);
@ -133,14 +137,12 @@ bool DhtRead(uint32_t sensor)
uint32_t i = 0; uint32_t i = 0;
noInterrupts(); 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++) { for (i = 0; i < 40; i++) {
if (!DhtWaitState(sensor, 1)) { break; } if (!DhtWaitState(sensor, 1)) { break; }
delayMicroseconds(32); // Was 30 int wt = DhtWaitState(sensor,0); // determine time to change state
if (digitalRead(Dht[sensor].pin)) { if(wt==0) break;
dht_data[i / 8] |= (1 << (7 - i % 8)); if(wt>50) dht_data[i / 8] |= (1 << (7 - i % 8)); // if longer than 50 usec then 1, else 0
}
if (!DhtWaitState(sensor, 0)) { break; }
} }
} }
interrupts(); interrupts();