arduinoprojects

git clone https://git.tarina.org/arduinoprojects
Log | Files | Refs

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 --