From 088b6bfaa5e6d0fef1ca3bf1d420395a177512e9 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sun, 24 Nov 2024 14:28:22 +0100 Subject: [PATCH] refactor --- CHANGELOG.md | 5 ++ README.md | 70 ++++++++++++---- dhtnew.cpp | 84 +++++++++++++------ dhtnew.h | 61 ++++++++------ .../dhtnew_adaptive_delay.ino | 16 ++-- examples/dhtnew_minimum/dhtnew_minimum.ino | 4 +- examples/dhtnew_test/dhtnew_test.ino | 16 ++-- keywords.txt | 5 ++ 8 files changed, 175 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 452a223..011e3e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.5.1] - 2024-11-24 - fix #102, add support for KY015 - add three examples, dhtnew_dht11.ino, dhtnew_dht22.ino, dhtnew_simple.ino +- optimize decimal part DHT11 (type == 11) +- minor fix setType(23), could be bug. +- minor fix temperature conversion (-0.0) +- add offset functions with full name version (readability), + - short ones will become obsolete in the future - update readme.md ## [0.5.0] - 2024-11-22 diff --git a/README.md b/README.md index 2c714a5..fcdb605 100644 --- a/README.md +++ b/README.md @@ -50,13 +50,27 @@ As the AM2321 and AM2322 are quite identical according to the datasheet, those a To use the library one should call **setType(22)** as the protocol is identical to the DHT22. If there are differences in operation type (23) will be elaborated. -The value 23 is now mapped upon 22 code. +The type 23 is now mapped upon type 22. Feedback (both positive and negative) about the AM232X sensors is welcome. **Note: check the datasheet how to connect!** +### KY-015 + +Since 0.5.1 there is **experimental** support for the KY-015, which is a DHT11 (sort of). +Not tested myself but the KY-015 is confirmed to work, see https://github.com/RobTillaart/DHTNew/issues/102 +Although it is a DHT11, the KY-015 was recognized as a DHT22 resulting in faulty conversions. + +The library sensor recognition code has been adapted so it should be recognized. +In the case this fails, one can use **setType(11)** to force the type. + +Feedback about the KY-015 sensors is welcome. + +**Note: check the datasheet how to connect!** + + ### 0.5.0 Negative temperature Apparently there are DHT22's which use another representation for negative temperatures. @@ -85,11 +99,13 @@ See also https://arduino.stackexchange.com/questions/86448/dht22-sensor-reading- | pin 3 | | Not Connected | | pin 4 | | GND | -**Note: check the datasheet how to connect!** +**Note: check the datasheet of the sensor how to connect!** as some have only 3 pins. ## Specification DHT22 +As most used model, for other sensors I refer to datasheet. + | Model | DHT22 | Notes | |:----------------------------|:-------------------------|:--------| | Power supply | 3.3 - 6.0 V DC | @@ -115,21 +131,22 @@ See also https://arduino.stackexchange.com/questions/86448/dht22-sensor-reading- ### Constructor - **DHTNEW(uint8_t pin)** defines the dataPin of the sensor. -- **void reset()** might help to reset a sensor behaving badly. It does reset the library settings to default, +- **void reset()** might help to reset a sensor behaving badly. +It resets the library internal settings to default, however it does not reset the sensor in a hardware way. - **uint8_t getType()** 0 = unknown, 11 or 22. In case of 0, **getType()** will try to determine type. Since 0.4.14 type 70 is added for **experimental** Sonoff Si7021 support. - **void setType(uint8_t type = 0)** allows to force the type of the sensor. -| Type | Sensors | Notes | -|:-------:|:---------------:|:--------| -| 0 | not defined | -| 11 | DHT11 | -| 22 | DHT22 a.o | most others -| 23 | DHT22 a.o | mapped to 22 for now -| 70 | Sonoff Si7021 | experimental -| other | sets to 0 | 0.4.20 +| Type | Sensors | Notes | +|:-------:|:-------------------------:|:--------| +| 0 | not defined | +| 11 | DHT11 DHT12, KY015 | KY015 needs setType(11) +| 22 | DHT22, DHT33, DHT44 a.o | most others +| 23 | DHT23 | mapped to 22 for now +| 70 | Sonoff Si7021 | experimental +| other | sets to 0 | 0.4.20 ### Base interface @@ -149,10 +166,19 @@ Note this error value can be suppressed by **setSuppressError(bool)**. Adding offsets works well in normal range however they might introduce under- or overflow at the ends of the sensor range. -Humidity is in % RH. -Humidity is constrained to 0.0 - 100.0 % in the code. -Temperature is in degrees Celsius. -For temperature such constrain would be type dependant, so it is not done. + +Humidity offset is in % RH and is constrained to 0.0 - 100.0 % in the code. + +Temperature offset is in degrees Celsius. +For temperature a constrain would be type dependant, so it is not done. +Furthermore by setting the offset to -273.15 one get the **Kelvin** scale. + +- **void setHumidityOffset(float offset)** typical < ±5% RH. +- **void setTemperatureOffset(float offset)** typical < ±2°C. +- **float getHumidityOffset()** idem. +- **float getTemperatureOffset()** idem. + +The "short-named" offset functions will become obsolete in the future (0.6.0). - **void setHumOffset(float offset)** typical < ±5% RH. - **void setTempOffset(float offset)** typical < ±2°C. @@ -311,7 +337,7 @@ updated readme.md - added badges and remarks after testing with MKR1010 Wifi. updated TIMEOUT_C from 70 -> 90 us to minimize its occurrence - See https://github.com/RobTillaart/DHTNew/issues/67. added ```while(!Serial);``` in examples to they work for MKR1010 Wifi. 27. (0.4.11) -update library.json, license, minor edits (cleanup), unit tests +update library.json, license, minor edits (clean up), unit tests 28. (0.4.12) Fix #72, delayMicroseconds() for wakeUp 29. (0.4.13) @@ -332,6 +358,10 @@ Update readme.md Update GitHub actions and readme.md 36. (0.4.21) Add dhtnew_pulse_diag_ext.ino +37. (0.5.0) +Fix negative values +38. (0.5.1) +Support KY015 and more. ## Future @@ -360,11 +390,17 @@ if (type == 11) temp = constrain(temp, 0, 100); if (type == 22) temp = constrain(temp, -40, 80); etc. ``` - +- type parameter in constructor, default 0 +- reimplement the recognition algorithm (separate class?) + - read as 22 => check the hum / temp data range to determine type + - read as 11 => check idem + - read as 70 => check idem + - split wakeup time from bit interpretation used. #### Wont - move all code from .h to .cpp +- derived classes for fixed type? ## Support diff --git a/dhtnew.cpp b/dhtnew.cpp index 60998f7..a8334b8 100644 --- a/dhtnew.cpp +++ b/dhtnew.cpp @@ -13,6 +13,7 @@ // these defines are not for user to adjust (microseconds) +// it adds 10% above the data sheet to allow a margin. #define DHTLIB_DHT11_WAKEUP (18 * 1100UL) #define DHTLIB_DHT_WAKEUP (1 * 1100UL) // experimental 0.4.14 @@ -45,19 +46,20 @@ void DHTNEW::reset() pinMode(_dataPin, OUTPUT); digitalWrite(_dataPin, HIGH); - _wakeupDelay = 0; - _type = 0; - _humOffset = 0.0; - _tempOffset = 0.0; - _humidity = 0.0; - _temperature = 0.0; - _lastRead = 0; - _disableIRQ = true; - _waitForRead = false; - _suppressError = false; - _readDelay = 0; + _wakeupDelay = 0; + _type = 0; + _humidityOffset = 0.0; + _temperatureOffset = 0.0; + _humidity = 0.0; + _temperature = 0.0; + _lastRead = 0; + _disableIRQ = true; + _waitForRead = false; + _suppressError = false; + _readDelay = 0; #if defined(__AVR__) - _disableIRQ = false; + // overrule + _disableIRQ = false; #endif // #if defined(ARDUINO_SAMD_MKRWIFI1010) // fix for issue #67 // _disableIRQ = false; @@ -80,7 +82,7 @@ void DHTNEW::setType(uint8_t type) if ((type == 22) || (type == 23)) { - _type = type; + _type = 22; // cannot differentiate type; _wakeupDelay = DHTLIB_DHT_WAKEUP; } else if (type == 11) @@ -125,27 +127,49 @@ int DHTNEW::read() } // AUTODETECT - // make sure sensor had time to wake up. + // make sure sensor had time to wake up after start of sketch. while (millis() < 1000); + // NOTE: we could add conversion H and T here and + // check if these are in the allowed range. + // humidity 0..100%, temperature 0..80C or -40..80C + // drawback: would increase footprint. + // NOTE: cannot differentiate between type 23 and 22 _type = 22; _wakeupDelay = DHTLIB_DHT_WAKEUP; int rv = _read(); - if (rv == DHTLIB_OK) return rv; + if (rv == DHTLIB_OK) + { + // test data bits to check for KY015 see issue #102 + // if it has DHT11 encoding. + // humidity cannot be over 100.0 % = 0x03E8 in DHT22 encoding + // test would incorrectly fail if there is a very low humidity + if (_bits[0] > 3) + { + _type = 11; + } + return rv; + } _type = 11; _wakeupDelay = DHTLIB_DHT11_WAKEUP; rv = _read(); - if (rv == DHTLIB_OK) return rv; + if (rv == DHTLIB_OK) + { + return rv; + } // experimental 0.4.14 _type = 70; _wakeupDelay = DHTLIB_SI7021_WAKEUP; rv = _read(); - if (rv == DHTLIB_OK) return rv; + if (rv == DHTLIB_OK) + { + return rv; + } - _type = 0; // retry next time + _type = 0; // retry next time return rv; } @@ -185,10 +209,12 @@ int DHTNEW::_read() return rv; // propagate error value } - if (_type == 11) // DHT11, DH12, compatible + if (_type == 11) // DHT11, DH12, KY015 compatible { - _humidity = _bits[0] + _bits[1] * 0.1; - _temperature = _bits[2] + _bits[3] * 0.1; + _humidity = _bits[0]; + if (_bits[1]) _humidity += _bits[1] * 0.1; + _temperature = _bits[2]; + if (_bits[3]) _temperature + _bits[3] * 0.1; } else // DHT22, DHT33, DHT44, compatible + Si7021 { @@ -200,9 +226,12 @@ int DHTNEW::_read() int16_t t = ((_bits[2] & 0x7F) * 256 + _bits[3]); if (t == 0) { - _temperature = 0.0; // prevent -0.0; + _temperature = 0.0; // prevents -0.0; + } + else + { + _temperature = t * 0.1; } - _temperature = t * 0.1; } else // negative temperature { @@ -257,15 +286,16 @@ int DHTNEW::_read() } #endif - if (_humOffset != 0.0) + if (_humidityOffset != 0.0) { - _humidity += _humOffset; + _humidity += _humidityOffset; + // constrain range if (_humidity > 100) _humidity = 100; else if (_humidity < 0) _humidity = 0; } - if (_tempOffset != 0.0) + if (_temperatureOffset != 0.0) { - _temperature += _tempOffset; + _temperature += _temperatureOffset; } // TEST CHECKSUM diff --git a/dhtnew.h b/dhtnew.h index 1f592c7..1a9c583 100644 --- a/dhtnew.h +++ b/dhtnew.h @@ -62,29 +62,42 @@ class DHTNEW // might help to reset a sensor behaving badly void reset(); - // 0 = unknown - // 11 = DHT11 and compatibles - // 22 = DHT22 and compatibles - // 23 = mapped to 22 for now (AM23xx) - // 70 = Sonoff Si7021 + // TYPE MEANING + // ---------------- + // 0 unknown, not set. + // 11 DHT11 and compatibles + // 22 DHT22 and compatibles + // 23 mapped to 22 for now (AM23xx) + // 70 Sonoff Si7021 uint8_t getType(); void setType(uint8_t type = 0); - int read(); + + // CORE FUNCTIONS + int read(); // lastRead is in MilliSeconds since start sketch uint32_t lastRead() { return _lastRead; }; - // preferred interface float getHumidity() { return _humidity; }; float getTemperature() { return _temperature; }; + + // OFFSET // adding offsets works well in normal range // might introduce under- or overflow at the ends of the sensor range - void setHumOffset(float offset) { _humOffset = offset; }; - void setTempOffset(float offset) { _tempOffset = offset; }; - float getHumOffset() { return _humOffset; }; - float getTempOffset() { return _tempOffset; }; - + // adding -273.15 offset to temperature gives Kelvin scale. + void setHumidityOffset(float offset) { _humidityOffset = offset; }; + void setTemperatureOffset(float offset) { _temperatureOffset = offset; }; + float getHumidityOffset() { return _humidityOffset; }; + float getTemperatureOffset() { return _temperatureOffset; }; + // future obsolete versions + void setHumOffset(float offset) { _humidityOffset = offset; }; + void setTempOffset(float offset) { _temperatureOffset = offset; }; + float getHumOffset() { return _humidityOffset; }; + float getTempOffset() { return _temperatureOffset; }; + + + // INTERRUPT DISABLE bool getDisableIRQ() { return _disableIRQ; }; void setDisableIRQ(bool b ) { _disableIRQ = b; }; @@ -106,18 +119,18 @@ class DHTNEW private: - uint8_t _dataPin = 0; - uint32_t _wakeupDelay = 0; - uint8_t _type = 0; - float _humOffset = 0.0; - float _tempOffset = 0.0; - float _humidity = 0.0; - float _temperature = 0.0; - uint32_t _lastRead = 0; - bool _disableIRQ = true; - bool _waitForRead = false; - bool _suppressError = false; - uint16_t _readDelay = 0; + uint8_t _dataPin = 0; + uint32_t _wakeupDelay = 0; + uint8_t _type = 0; + float _humidityOffset = 0.0; + float _temperatureOffset = 0.0; + float _humidity = 0.0; + float _temperature = 0.0; + uint32_t _lastRead = 0; + bool _disableIRQ = true; + bool _waitForRead = false; + bool _suppressError = false; + uint16_t _readDelay = 0; uint8_t _bits[5]; // buffer to receive data int _read(); diff --git a/examples/dhtnew_adaptive_delay/dhtnew_adaptive_delay.ino b/examples/dhtnew_adaptive_delay/dhtnew_adaptive_delay.ino index 0c38325..5486618 100644 --- a/examples/dhtnew_adaptive_delay/dhtnew_adaptive_delay.ino +++ b/examples/dhtnew_adaptive_delay/dhtnew_adaptive_delay.ino @@ -49,24 +49,24 @@ void setup() Serial.println("\n2. Humidity offset test"); Serial.println("STAT\tHUMI\tTEMP\tTIME\tTYPE"); - mySensor.setHumOffset(2.5); + mySensor.setHumidityOffset(2.5); test(); - mySensor.setHumOffset(5.5); + mySensor.setHumidityOffset(5.5); test(); - mySensor.setHumOffset(-5.5); + mySensor.setHumidityOffset(-5.5); test(); - mySensor.setHumOffset(0); + mySensor.setHumidityOffset(0); test(); Serial.println("\n3. Temperature offset test"); Serial.println("STAT\tHUMI\tTEMP\tTIME\tTYPE"); - mySensor.setTempOffset(2.5); + mySensor.setTemperatureOffset(2.5); test(); - mySensor.setTempOffset(5.5); + mySensor.setTemperatureOffset(5.5); test(); - mySensor.setTempOffset(-5.5); + mySensor.setTemperatureOffset(-5.5); test(); - mySensor.setTempOffset(0); + mySensor.setTemperatureOffset(0); test(); Serial.println("\n4. LastRead test"); diff --git a/examples/dhtnew_minimum/dhtnew_minimum.ino b/examples/dhtnew_minimum/dhtnew_minimum.ino index 6422198..859c4d2 100644 --- a/examples/dhtnew_minimum/dhtnew_minimum.ino +++ b/examples/dhtnew_minimum/dhtnew_minimum.ino @@ -36,8 +36,8 @@ void setup() Serial.print("\t"); Serial.println(mySensor.getTemperature(), 1); - mySensor.setHumOffset(10); - mySensor.setTempOffset(-3.5); + mySensor.setHumidityOffset(10); + mySensor.setTemperatureOffset(-3.5); Serial.println("AFTER OFFSET"); } diff --git a/examples/dhtnew_test/dhtnew_test.ino b/examples/dhtnew_test/dhtnew_test.ino index 36a8e1c..3bdc59b 100644 --- a/examples/dhtnew_test/dhtnew_test.ino +++ b/examples/dhtnew_test/dhtnew_test.ino @@ -40,24 +40,24 @@ void setup() Serial.println("\n2. Humidity offset test"); Serial.println("STAT\tHUMI\tTEMP\tTIME\tTYPE"); - mySensor.setHumOffset(2.5); + mySensor.setHumidityOffset(2.5); test(); - mySensor.setHumOffset(5.5); + mySensor.setHumidityOffset(5.5); test(); - mySensor.setHumOffset(-5.5); + mySensor.setHumidityOffset(-5.5); test(); - mySensor.setHumOffset(0); + mySensor.setHumidityOffset(0); test(); Serial.println("\n3. Temperature offset test"); Serial.println("STAT\tHUMI\tTEMP\tTIME\tTYPE"); - mySensor.setTempOffset(2.5); + mySensor.setTemperatureOffset(2.5); test(); - mySensor.setTempOffset(5.5); + mySensor.setTemperatureOffset(5.5); test(); - mySensor.setTempOffset(-5.5); + mySensor.setTemperatureOffset(-5.5); test(); - mySensor.setTempOffset(0); + mySensor.setTemperatureOffset(0); test(); Serial.println("\n4. LastRead test"); diff --git a/keywords.txt b/keywords.txt index b0e2e9c..39e9264 100644 --- a/keywords.txt +++ b/keywords.txt @@ -20,6 +20,11 @@ setTempOffset KEYWORD2 getHumOffset KEYWORD2 getTempOffset KEYWORD2 +setHumidityOffset KEYWORD2 +setTemperatureOffset KEYWORD2 +getHumidityOffset KEYWORD2 +getTemperatureOffset KEYWORD2 + getDisableIRQ KEYWORD2 setDisableIRQ KEYWORD2