From 616d908b60580121933cefaf344eea025b8cbf1a Mon Sep 17 00:00:00 2001 From: khjoen Date: Fri, 6 Jan 2017 12:31:28 -0500 Subject: [PATCH 1/2] Start listening to the sensor right after releasing the start signal (close #48) --- DHT.cpp | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index 86ad91c..e33a9e6 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -135,11 +135,6 @@ boolean DHT::read(bool force) { // Send start signal. See DHT datasheet for full signal diagram: // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf - // Go into high impedence state to let pull-up raise data line level and - // start the reading process. - digitalWrite(_pin, HIGH); - delay(250); - // First set data line low for 20 milliseconds. pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); @@ -149,23 +144,42 @@ boolean DHT::read(bool force) { { // Turn off interrupts temporarily because the next sections are timing critical // and we don't want any interruptions. + // NOTE: From this point we cannot use function such as delay(), delayMicroseconds(), + // Those functions among others rely on interrupts. InterruptLock lock; - // End the start signal by setting data line high for 40 microseconds. - digitalWrite(_pin, HIGH); - delayMicroseconds(40); - + // End of the start signal. // Now start reading the data line to get the value from the DHT sensor. pinMode(_pin, INPUT_PULLUP); - delayMicroseconds(10); // Delay a bit to let sensor pull data line low. + // from this point we listen, it's sensor's turn to talk. + + + // The following step is a busy-wait loop to continue only + // when the data line has been pulled LOW by the sensor. + // + // To avoid infinite loops here, we use a counter as a timeout. + // 700 iterations is about 4 ms on a 16Mhz processor. The sensor should + // set the pin LOW within 20 to 40 microseconds. + // The (F_CPU / 16000000) is a ratio to keep the timeout to approximately + // the same period if processor used has different frequency. + unsigned long timesup = (F_CPU / 16000000) * 700; + unsigned long count = 0; + while (digitalRead(_pin) == HIGH && ++count < timesup) + ; + if (count == timesup) { + DEBUG_PRINTLN(F("Timeout waiting sensor to pull the data line LOW.")); + _lastresult = false; + return _lastresult; + } - // First expect a low signal for ~80 microseconds followed by a high signal - // for ~80 microseconds again. + // expect a low signal for ~80 microseconds. if (expectPulse(LOW) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); _lastresult = false; return _lastresult; } + + // followed by a high signal for ~80 microseconds. if (expectPulse(HIGH) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); _lastresult = false; @@ -184,7 +198,8 @@ boolean DHT::read(bool force) { cycles[i] = expectPulse(LOW); cycles[i+1] = expectPulse(HIGH); } - } // Timing critical code is now complete. + // Interrupts will turn back on when exiting this scope. + } // Timing critical code is now complete. // Inspect pulses and determine which ones are 0 (high state cycle count < low // state cycle count), or 1 (high state cycle count > low state cycle count). From ba8cd46debe1cb855fd2b46e8a9b6cf671673abc Mon Sep 17 00:00:00 2001 From: khjoen Date: Wed, 25 Jul 2018 16:10:21 -0400 Subject: [PATCH 2/2] Ensured float division for start signal response timeout and changed start signal time depending on sensor type --- DHT.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index e33a9e6..3641eac 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -134,11 +134,20 @@ boolean DHT::read(bool force) { // Send start signal. See DHT datasheet for full signal diagram: // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf - - // First set data line low for 20 milliseconds. + // First set data line low to send start signal. pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); - delay(20); + // set wait time according to sensor type. + switch (_type) { + case DHT22: + case DHT21: + delayMicroseconds(1100); //data sheet says at least 1ms, 1.1ms should be ok + break; + case DHT11: + default: + delay(20); //data sheet says at least 18ms, 20ms just to be safe + break; + } uint32_t cycles[80]; { @@ -154,15 +163,15 @@ boolean DHT::read(bool force) { // from this point we listen, it's sensor's turn to talk. - // The following step is a busy-wait loop to continue only + // The following step is a busy-wait loop to resume processing only // when the data line has been pulled LOW by the sensor. // // To avoid infinite loops here, we use a counter as a timeout. // 700 iterations is about 4 ms on a 16Mhz processor. The sensor should // set the pin LOW within 20 to 40 microseconds. - // The (F_CPU / 16000000) is a ratio to keep the timeout to approximately - // the same period if processor used has different frequency. - unsigned long timesup = (F_CPU / 16000000) * 700; + // The (F_CPU / 16000000.0) is a ratio to keep the timeout to approximately + // the same period if processor used runs at a different frequency. + unsigned long timesup = (F_CPU / 16000000.0) * 700; unsigned long count = 0; while (digitalRead(_pin) == HIGH && ++count < timesup) ;