From 04905bc5cd829ad13e299240aa9b202ca96fae94 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 24 Jul 2015 17:37:24 +0200 Subject: [PATCH 1/6] Add force parameter to read methods This allows forcing a read, even if the previous read was less than 2 seconds ago. This is useful in cases where the millis() timer is not reliable, such as when sleeping. In this case, it is up to the caller to ensure that at least 2 seconds elapse between calls with force set to true. --- DHT.cpp | 10 +++++----- DHT.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index 79f6a40..659dd97 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -27,10 +27,10 @@ void DHT::begin(void) { } //boolean S == Scale. True == Fahrenheit; False == Celcius -float DHT::readTemperature(bool S) { +float DHT::readTemperature(bool S, bool force) { float f = NAN; - if (read()) { + if (read(force)) { switch (_type) { case DHT11: f = data[2]; @@ -64,7 +64,7 @@ float DHT::convertFtoC(float f) { return (f - 32) * 5 / 9; } -float DHT::readHumidity(void) { +float DHT::readHumidity(bool force) { float f = NAN; if (read()) { switch (_type) { @@ -113,7 +113,7 @@ float DHT::computeHeatIndex(float temperature, float percentHumidity, bool isFah } } -boolean DHT::read(void) { +boolean DHT::read(bool force) { // Check if sensor was read less than two seconds ago and return early // to use last reading. uint32_t currenttime = millis(); @@ -121,7 +121,7 @@ boolean DHT::read(void) { // ie there was a rollover _lastreadtime = 0; } - if (!_firstreading && ((currenttime - _lastreadtime) < 2000)) { + if (!force && !_firstreading && ((currenttime - _lastreadtime) < 2000)) { return _lastresult; // return last correct measurement } _firstreading = false; diff --git a/DHT.h b/DHT.h index dd4d1f5..5040fa3 100644 --- a/DHT.h +++ b/DHT.h @@ -39,12 +39,12 @@ class DHT { public: DHT(uint8_t pin, uint8_t type, uint8_t count=6); void begin(void); - float readTemperature(bool S=false); + float readTemperature(bool S=false, bool force=false); float convertCtoF(float); float convertFtoC(float); float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true); - float readHumidity(void); - boolean read(void); + float readHumidity(bool force=false); + boolean read(bool force=false); private: uint8_t data[6]; From f1b79028ea5f3c11a8ae0d2c06452de1d293b559 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 24 Jul 2015 17:40:38 +0200 Subject: [PATCH 2/6] Clean up two-second interval check There was some handling of millis() overflow that is not needed. Standard unsigned subtraction and wraparound already works as expected, so this extra check can be removed (it even hurts, since it introduces 2 seconds after a wraparound where no new data will be read, even if it could otherwise happen). Also, this prevents calling millis() a second time, since its value is already known. --- DHT.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index 659dd97..6bc87c9 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -117,15 +117,11 @@ boolean DHT::read(bool force) { // Check if sensor was read less than two seconds ago and return early // to use last reading. uint32_t currenttime = millis(); - if (currenttime < _lastreadtime) { - // ie there was a rollover - _lastreadtime = 0; - } if (!force && !_firstreading && ((currenttime - _lastreadtime) < 2000)) { return _lastresult; // return last correct measurement } _firstreading = false; - _lastreadtime = millis(); + _lastreadtime = currenttime; // Reset 40 bits of received data to zero. data[0] = data[1] = data[2] = data[3] = data[4] = 0; From 5973929e63e99a61662e7e1dd1026796d8631cdc Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 24 Jul 2015 21:17:16 +0200 Subject: [PATCH 3/6] Remove the firstreading variable By cleverly setting _lastreadtime in begin() to make sure that it looks like the last read was alrady 2000 ms ago, even on startup when millis() still returns 0, there is no longer a need to keep a separate firstreading variable, saving a byte of memory and a bit of code. --- DHT.cpp | 11 +++++++---- DHT.h | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index 6bc87c9..e75ccfe 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -6,10 +6,11 @@ written by Adafruit Industries #include "DHT.h" +#define MIN_INTERVAL 2000 + DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { _pin = pin; _type = type; - _firstreading = true; _bit = digitalPinToBitMask(pin); _port = digitalPinToPort(pin); _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for @@ -22,7 +23,10 @@ void DHT::begin(void) { // set up the pins! pinMode(_pin, INPUT); digitalWrite(_pin, HIGH); - _lastreadtime = 0; + // Using this value makes sure that millis() - lastreadtime will be + // >= MIN_INTERVAL right away. Note that this assignment wraps around, + // but so will the subtraction. + _lastreadtime = -MIN_INTERVAL; DEBUG_PRINT("Max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC); } @@ -117,10 +121,9 @@ boolean DHT::read(bool force) { // Check if sensor was read less than two seconds ago and return early // to use last reading. uint32_t currenttime = millis(); - if (!force && !_firstreading && ((currenttime - _lastreadtime) < 2000)) { + if (!force && ((currenttime - _lastreadtime) < 2000)) { return _lastresult; // return last correct measurement } - _firstreading = false; _lastreadtime = currenttime; // Reset 40 bits of received data to zero. diff --git a/DHT.h b/DHT.h index 5040fa3..bbce4f5 100644 --- a/DHT.h +++ b/DHT.h @@ -50,7 +50,6 @@ class DHT { uint8_t data[6]; uint8_t _pin, _type, _bit, _port; uint32_t _lastreadtime, _maxcycles; - bool _firstreading; bool _lastresult; uint32_t expectPulse(bool level); From 45a20da301c97a5d7256df5a76a77fb245173505 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 24 Jul 2015 18:08:47 +0200 Subject: [PATCH 4/6] Shrink DHT::data to 5 bytes There's only 5 bytes of data being transferred (2x2 bytes of data, 1 byte checksum), so no need to keep a useless byte. --- DHT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DHT.h b/DHT.h index bbce4f5..5d92f06 100644 --- a/DHT.h +++ b/DHT.h @@ -47,7 +47,7 @@ class DHT { boolean read(bool force=false); private: - uint8_t data[6]; + uint8_t data[5]; uint8_t _pin, _type, _bit, _port; uint32_t _lastreadtime, _maxcycles; bool _lastresult; From f9c3f323e3d2335164f0787bedaf2450fcaa9307 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 24 Jul 2015 18:18:01 +0200 Subject: [PATCH 5/6] Use INPUT_PULLUP Previously, the mode was configured to INPUT and then written HIGH, which works on AVR but isn't very portable. Instead, this uses the INPUT_PULLUP pin mode (available since Arduino 1.0.1) which is portable. --- DHT.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DHT.cpp b/DHT.cpp index e75ccfe..c2257d0 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -21,8 +21,7 @@ DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { void DHT::begin(void) { // set up the pins! - pinMode(_pin, INPUT); - digitalWrite(_pin, HIGH); + pinMode(_pin, INPUT_PULLUP); // Using this value makes sure that millis() - lastreadtime will be // >= MIN_INTERVAL right away. Note that this assignment wraps around, // but so will the subtraction. @@ -153,7 +152,7 @@ boolean DHT::read(bool force) { delayMicroseconds(40); // Now start reading the data line to get the value from the DHT sensor. - pinMode(_pin, INPUT); + pinMode(_pin, INPUT_PULLUP); delayMicroseconds(10); // Delay a bit to let sensor pull data line low. // First expect a low signal for ~80 microseconds followed by a high signal From 232ad0cd70826b852b447ba83d817233ee7194da Mon Sep 17 00:00:00 2001 From: Tony DiCola Date: Tue, 15 Sep 2015 12:26:38 -0700 Subject: [PATCH 6/6] Bump version to 1.2.0 after integrating optimizations from matthijskooijman. --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index d8bfdf1..49c992d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=DHT sensor library -version=1.1.1 +version=1.2.0 author=Adafruit maintainer=Adafruit sentence=Arduino library for DHT11, DHT22, etc Temp & Humidity Sensors