dhtnew.cpp (9865B)
1 // 2 // FILE: dhtnew.cpp 3 // AUTHOR: Rob.Tillaart@gmail.com 4 // VERSION: 0.4.5 5 // PURPOSE: DHT Temperature & Humidity Sensor library for Arduino 6 // URL: https://github.com/RobTillaart/DHTNEW 7 // 8 // HISTORY: 9 // 0.1.0 2017-07-24 initial version based upon DHTStable 10 // 0.1.1 2017-07-29 add begin() to determine type once and for all instead of every call + refactor 11 // 0.1.2 2018-01-08 improved begin() + refactor() 12 // 0.1.3 2018-01-08 removed begin() + moved detection to read() function 13 // 0.1.4 2018-04-03 add get-/setDisableIRQ(bool b) 14 // 0.1.5 2019-01-20 fix negative temperature DHT22 - issue #120 15 // 0.1.6 2020-04-09 #pragma once, readme.md, own repo 16 // 0.1.7 2020-05-01 prevent premature read; add waitForReading flag (Kudo's to Mr-HaleYa), 17 // 0.2.0 2020-05-02 made temperature and humidity private (Kudo's to Mr-HaleYa), 18 // 0.2.1 2020-05-27 Fix #11 - Adjust bit timing threshold 19 // 0.2.2 2020-06-08 added ERROR_SENSOR_NOT_READY and differentiate timeout errors 20 // 0.3.0 2020-06-12 added getReadDelay & setReadDelay to tune reading interval 21 // removed get/setDisableIRQ; adjusted wakeup timing; refactor 22 // 0.3.1 2020-07-08 added powerUp() powerDown(); 23 // 0.3.2 2020-07-17 fix #23 added get/setSuppressError(); overrulable DHTLIB_INVALID_VALUE 24 // 0.3.3 2020-08-18 fix #29, create explicit delay between pulling line HIGH and 25 // waiting for LOW in handshake to trigger the sensor. 26 // On fast ESP32 this fails because the capacity / voltage of the long wire 27 // cannot rise fast enough to be read back as HIGH. 28 // 0.3.4 2020-09-23 Added **waitFor(state, timeout)** to follow timing from datasheet. 29 // Restored disableIRQ flag as problems occured on AVR. The default of 30 // this flag on AVR is false so interrupts are allowed. 31 // This need some investigation 32 // Fix wake up timing for DHT11 as it does not behave according datasheet. 33 // fix wakeupDelay bug in setType(); 34 // 0.4.0 2020-11-10 added DHTLIB_WAITING_FOR_READ as return value of read (minor break of interface) 35 // 0.4.1 2020-11-11 getType() attempts to detect sensor type 36 // 2020-12-12 add arduino -CI + readme 37 // 0.4.2 2020-12-15 fix negative temperatures 38 // 0.4.3 2021-01-13 add reset(), add lastRead() 39 // 0.4.4 2021-02-01 fix negative temperatures DHT22 (again) 40 // 0.4.5 2021-02-14 fix -0°C encoding of DHT22 ( bit pattern 0x8000 ) 41 42 43 #include "dhtnew.h" 44 #include <stdint.h> 45 46 47 // these defines are not for user to adjust 48 #define DHTLIB_DHT11_WAKEUP 18 49 #define DHTLIB_DHT_WAKEUP 1 50 51 52 // READ_DELAY for blocking read 53 // datasheet: DHT11 = 1000 and DHT22 = 2000 54 // use setReadDelay() to overrule (at own risk) 55 // as individual sensors can be read faster. 56 // see example DHTnew_setReadDelay.ino 57 #define DHTLIB_DHT11_READ_DELAY 1000 58 #define DHTLIB_DHT22_READ_DELAY 2000 59 60 61 ///////////////////////////////////////////////////// 62 // 63 // PUBLIC 64 // 65 DHTNEW::DHTNEW(uint8_t pin) 66 { 67 _dataPin = pin; 68 reset(); 69 }; 70 71 72 void DHTNEW::reset() 73 { 74 // Data-bus's free status is high voltage level. 75 pinMode(_dataPin, OUTPUT); 76 digitalWrite(_dataPin, HIGH); 77 78 _wakeupDelay = 0; 79 _type = 0; 80 _humOffset = 0.0; 81 _tempOffset = 0.0; 82 _humidity = 0.0; 83 _temperature = 0.0; 84 _lastRead = 0; 85 _disableIRQ = true; 86 _waitForRead = false; 87 _suppressError = false; 88 _readDelay = 0; 89 #if defined(__AVR__) 90 _disableIRQ = false; 91 #endif 92 } 93 94 95 uint8_t DHTNEW::getType() 96 { 97 if (_type == 0) read(); 98 return _type; 99 } 100 101 102 void DHTNEW::setType(uint8_t type) 103 { 104 if ((type == 0) || (type == 11)) 105 { 106 _type = type; 107 _wakeupDelay = DHTLIB_DHT11_WAKEUP; 108 } 109 if (type == 22) 110 { 111 _type = type; 112 _wakeupDelay = DHTLIB_DHT_WAKEUP; 113 } 114 } 115 116 117 // return values: 118 // DHTLIB_OK 119 // DHTLIB_WAITING_FOR_READ 120 // DHTLIB_ERROR_CHECKSUM 121 // DHTLIB_ERROR_BIT_SHIFT 122 // DHTLIB_ERROR_SENSOR_NOT_READY 123 // DHTLIB_ERROR_TIMEOUT_A 124 // DHTLIB_ERROR_TIMEOUT_B 125 // DHTLIB_ERROR_TIMEOUT_C 126 // DHTLIB_ERROR_TIMEOUT_D 127 int DHTNEW::read() 128 { 129 if (_readDelay == 0) 130 { 131 _readDelay = DHTLIB_DHT22_READ_DELAY; 132 if (_type == 11) _readDelay = DHTLIB_DHT11_READ_DELAY; 133 } 134 if (_type != 0) 135 { 136 while (millis() - _lastRead < _readDelay) 137 { 138 if (!_waitForRead) return DHTLIB_WAITING_FOR_READ; 139 yield(); 140 } 141 return _read(); 142 } 143 144 _type = 22; 145 _wakeupDelay = DHTLIB_DHT_WAKEUP; 146 int rv = _read(); 147 if (rv == DHTLIB_OK) return rv; 148 149 _type = 11; 150 _wakeupDelay = DHTLIB_DHT11_WAKEUP; 151 rv = _read(); 152 if (rv == DHTLIB_OK) return rv; 153 154 _type = 0; // retry next time 155 return rv; 156 } 157 158 159 // return values: 160 // DHTLIB_OK 161 // DHTLIB_ERROR_CHECKSUM 162 // DHTLIB_ERROR_BIT_SHIFT 163 // DHTLIB_ERROR_SENSOR_NOT_READY 164 // DHTLIB_ERROR_TIMEOUT_A 165 // DHTLIB_ERROR_TIMEOUT_B 166 // DHTLIB_ERROR_TIMEOUT_C 167 // DHTLIB_ERROR_TIMEOUT_D 168 int DHTNEW::_read() 169 { 170 // READ VALUES 171 int rv = _readSensor(); 172 interrupts(); 173 174 // Data-bus's free status is high voltage level. 175 pinMode(_dataPin, OUTPUT); 176 digitalWrite(_dataPin, HIGH); 177 _lastRead = millis(); 178 179 if (rv != DHTLIB_OK) 180 { 181 if (_suppressError == false) 182 { 183 _humidity = DHTLIB_INVALID_VALUE; 184 _temperature = DHTLIB_INVALID_VALUE; 185 } 186 return rv; // propagate error value 187 } 188 189 if (_type == 22) // DHT22, DHT33, DHT44, compatible 190 { 191 _humidity = (_bits[0] * 256 + _bits[1]) * 0.1; 192 int16_t t = (_bits[2] * 256 + _bits[3]); 193 if(_bits[2] == 0x80) 194 _temperature = 0; 195 else 196 _temperature = t * 0.1; 197 } 198 else // if (_type == 11) // DHT11, DH12, compatible 199 { 200 _humidity = _bits[0] + _bits[1] * 0.1; 201 _temperature = _bits[2] + _bits[3] * 0.1; 202 } 203 204 // HEXDUMP DEBUG 205 /* 206 Serial.println(); 207 // CHECKSUM 208 if (_bits[4] < 0x10) Serial.print(0); 209 Serial.print(_bits[4], HEX); 210 Serial.print(" "); 211 // TEMPERATURE 212 if (_bits[2] < 0x10) Serial.print(0); 213 Serial.print(_bits[2], HEX); 214 if (_bits[3] < 0x10) Serial.print(0); 215 Serial.print(_bits[3], HEX); 216 Serial.print(" "); 217 Serial.print(_temperature, 1); 218 Serial.print(" "); 219 // HUMIDITY 220 if (_bits[0] < 0x10) Serial.print(0); 221 Serial.print(_bits[0], HEX); 222 if (_bits[1] < 0x10) Serial.print(0); 223 Serial.print(_bits[1], HEX); 224 Serial.print(" "); 225 Serial.print(_humidity, 1); 226 */ 227 228 _humidity = constrain(_humidity + _humOffset, 0, 100); 229 _temperature += _tempOffset; 230 231 // TEST CHECKSUM 232 uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3]; 233 if (_bits[4] != sum) 234 { 235 return DHTLIB_ERROR_CHECKSUM; 236 } 237 return DHTLIB_OK; 238 } 239 240 241 void DHTNEW::powerUp() 242 { 243 digitalWrite(_dataPin, HIGH); 244 // do a dummy read to sync the sensor 245 read(); 246 }; 247 248 249 void DHTNEW::powerDown() 250 { 251 digitalWrite(_dataPin, LOW); 252 } 253 254 255 ///////////////////////////////////////////////////// 256 // 257 // PRIVATE 258 // 259 260 // return values: 261 // DHTLIB_OK 262 // DHTLIB_ERROR_CHECKSUM 263 // DHTLIB_ERROR_BIT_SHIFT 264 // DHTLIB_ERROR_SENSOR_NOT_READY 265 // DHTLIB_ERROR_TIMEOUT_A 266 // DHTLIB_ERROR_TIMEOUT_B 267 // DHTLIB_ERROR_TIMEOUT_C 268 // DHTLIB_ERROR_TIMEOUT_D 269 int DHTNEW::_readSensor() 270 { 271 // INIT BUFFERVAR TO RECEIVE DATA 272 uint8_t mask = 0x80; 273 uint8_t idx = 0; 274 275 // EMPTY BUFFER 276 for (uint8_t i = 0; i < 5; i++) _bits[i] = 0; 277 278 // HANDLE PENDING IRQ 279 yield(); 280 281 // REQUEST SAMPLE - SEND WAKEUP TO SENSOR 282 pinMode(_dataPin, OUTPUT); 283 digitalWrite(_dataPin, LOW); 284 // add 10% extra for timing inaccuracies in sensor. 285 delayMicroseconds(_wakeupDelay * 1100UL); 286 287 // HOST GIVES CONTROL TO SENSOR 288 digitalWrite(_dataPin, HIGH); 289 delayMicroseconds(2); 290 pinMode(_dataPin, INPUT_PULLUP); 291 292 // DISABLE INTERRUPTS when clock in the bits 293 if (_disableIRQ) { noInterrupts(); } 294 295 // DHT22 296 // SENSOR PULLS LOW after 20-40 us => if stays HIGH ==> device not ready 297 // timeout is 20 us less due to delay() above 298 // DHT11 299 // SENSOR PULLS LOW after 6000-10000 us 300 uint32_t WAITFORSENSOR = 50; 301 if (_type == 11) WAITFORSENSOR = 15000UL; 302 if (_waitFor(LOW, WAITFORSENSOR)) return DHTLIB_ERROR_SENSOR_NOT_READY; 303 304 // SENSOR STAYS LOW for ~80 us => or TIMEOUT 305 if (_waitFor(HIGH, 90)) return DHTLIB_ERROR_TIMEOUT_A; 306 307 // SENSOR STAYS HIGH for ~80 us => or TIMEOUT 308 if (_waitFor(LOW, 90)) return DHTLIB_ERROR_TIMEOUT_B; 309 310 // SENSOR HAS NOW SEND ACKNOWLEDGE ON WAKEUP 311 // NOW IT SENDS THE BITS 312 313 // READ THE OUTPUT - 40 BITS => 5 BYTES 314 for (uint8_t i = 40; i != 0; i--) 315 { 316 // EACH BIT START WITH ~50 us LOW 317 if (_waitFor(HIGH, 70)) return DHTLIB_ERROR_TIMEOUT_C; 318 319 // DURATION OF HIGH DETERMINES 0 or 1 320 // 26-28 us ==> 0 321 // 70 us ==> 1 322 uint32_t t = micros(); 323 if (_waitFor(LOW, 90)) return DHTLIB_ERROR_TIMEOUT_D; 324 if ((micros() - t) > DHTLIB_BIT_THRESHOLD) 325 { 326 _bits[idx] |= mask; 327 } 328 329 // PREPARE FOR NEXT BIT 330 mask >>= 1; 331 if (mask == 0) // next byte? 332 { 333 mask = 0x80; 334 idx++; 335 } 336 } 337 // After 40 bits the sensor pulls the line LOW for 50 us 338 // No functional need to wait for this one 339 // if (_waitFor(HIGH, 60)) return DHTLIB_ERROR_TIMEOUT_E; 340 341 // CATCH RIGHTSHIFT BUG ESP (only 1 single bit shift) 342 // humidity is max 1000 = 0x03E8 for DHT22 and 0x6400 for DHT11 343 // so most significant bit may never be set. 344 if (_bits[0] & 0x80) return DHTLIB_ERROR_BIT_SHIFT; 345 346 return DHTLIB_OK; 347 } 348 349 350 // returns true if timeout has passed. 351 // returns false if timeout is not reached and state is seen. 352 bool DHTNEW::_waitFor(uint8_t state, uint32_t timeout) 353 { 354 uint32_t start = micros(); 355 uint8_t count = 2; 356 while ((micros() - start) < timeout) 357 { 358 // delayMicroseconds(1); // less # reads ==> minimizes # glitch reads 359 if (digitalRead(_dataPin) == state) 360 { 361 count--; 362 if (count == 0) return false; // requested state seen count times 363 } 364 } 365 return true; 366 } 367 368 // -- END OF FILE --