DHT.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* DHT library
  2. MIT license
  3. written by Adafruit Industries
  4. */
  5. #include "DHT.h"
  6. #define MIN_INTERVAL 2000
  7. #define TIMEOUT -1
  8. DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
  9. _pin = pin;
  10. _type = type;
  11. #ifdef __AVR
  12. _bit = digitalPinToBitMask(pin);
  13. _port = digitalPinToPort(pin);
  14. #endif
  15. _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for
  16. // reading pulses from DHT sensor.
  17. // Note that count is now ignored as the DHT reading algorithm adjusts itself
  18. // based on the speed of the processor.
  19. }
  20. void DHT::begin(void) {
  21. // set up the pins!
  22. pinMode(_pin, INPUT_PULLUP);
  23. // Using this value makes sure that millis() - lastreadtime will be
  24. // >= MIN_INTERVAL right away. Note that this assignment wraps around,
  25. // but so will the subtraction.
  26. _lastreadtime = millis() - MIN_INTERVAL;
  27. DEBUG_PRINT("DHT max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC);
  28. }
  29. //boolean S == Scale. True == Fahrenheit; False == Celcius
  30. float DHT::readTemperature(bool S, bool force) {
  31. float f = NAN;
  32. if (read(force)) {
  33. switch (_type) {
  34. case DHT11:
  35. case DHT12:
  36. f = data[2];
  37. f += (data[3] & 0x0f) * 0.1;
  38. if (data[2] & 0x80) {
  39. f *= -1;
  40. }
  41. if(S) {
  42. f = convertCtoF(f);
  43. }
  44. break;
  45. case DHT22:
  46. case DHT21:
  47. f = ((word)(data[2] & 0x7F)) << 8 | data[3];
  48. f *= 0.1;
  49. if (data[2] & 0x80) {
  50. f *= -1;
  51. }
  52. if(S) {
  53. f = convertCtoF(f);
  54. }
  55. break;
  56. }
  57. }
  58. return f;
  59. }
  60. float DHT::convertCtoF(float c) {
  61. return c * 1.8 + 32;
  62. }
  63. float DHT::convertFtoC(float f) {
  64. return (f - 32) * 0.55555;
  65. }
  66. float DHT::readHumidity(bool force) {
  67. float f = NAN;
  68. if (read(force)) {
  69. switch (_type) {
  70. case DHT11:
  71. case DHT12:
  72. f = data[0] + data[1] * 0.1;
  73. break;
  74. case DHT22:
  75. case DHT21:
  76. f = ((word)data[0]) << 8 | data[1];
  77. f *= 0.1;
  78. break;
  79. }
  80. }
  81. return f;
  82. }
  83. //boolean isFahrenheit: True == Fahrenheit; False == Celcius
  84. float DHT::computeHeatIndex(isFahrenheit) {
  85. float hi = self.computeHeatIndex(self.readTemperature(isFahrenheit), self.readHumidity(), isFahrenheit);
  86. return isFahrenheit ? hi : convertFtoC(hi);
  87. }
  88. //boolean isFahrenheit: True == Fahrenheit; False == Celcius
  89. float DHT::computeHeatIndex(float temperature, floast percentHumidity, bool isFahrenheit) {
  90. // Using both Rothfusz and Steadman's equations
  91. // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
  92. float hi;
  93. if (!isFahrenheit)
  94. temperature = convertCtoF(temperature);
  95. hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) + (percentHumidity * 0.094));
  96. if (hi > 79) {
  97. hi = -42.379 +
  98. 2.04901523 * temperature +
  99. 10.14333127 * percentHumidity +
  100. -0.22475541 * temperature*percentHumidity +
  101. -0.00683783 * pow(temperature, 2) +
  102. -0.05481717 * pow(percentHumidity, 2) +
  103. 0.00122874 * pow(temperature, 2) * percentHumidity +
  104. 0.00085282 * temperature*pow(percentHumidity, 2) +
  105. -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);
  106. if((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0))
  107. hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);
  108. else if((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0))
  109. hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
  110. }
  111. return isFahrenheit ? hi : convertFtoC(hi);
  112. }
  113. bool DHT::read(bool force) {
  114. // Check if sensor was read less than two seconds ago and return early
  115. // to use last reading.
  116. uint32_t currenttime = millis();
  117. if (!force && ((currenttime - _lastreadtime) < MIN_INTERVAL)) {
  118. return _lastresult; // return last correct measurement
  119. }
  120. _lastreadtime = currenttime;
  121. // Reset 40 bits of received data to zero.
  122. data[0] = data[1] = data[2] = data[3] = data[4] = 0;
  123. // Send start signal. See DHT datasheet for full signal diagram:
  124. // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
  125. // Go into high impedence state to let pull-up raise data line level and
  126. // start the reading process.
  127. digitalWrite(_pin, HIGH);
  128. delay(1);
  129. // First set data line low for 1 millisecond.
  130. pinMode(_pin, OUTPUT);
  131. digitalWrite(_pin, LOW);
  132. delay(1);
  133. uint32_t cycles[80];
  134. {
  135. // Turn off interrupts temporarily because the next sections are timing critical
  136. // and we don't want any interruptions.
  137. InterruptLock lock;
  138. // End the start signal by setting data line high for 40 microseconds.
  139. digitalWrite(_pin, HIGH);
  140. pinMode(_pin, INPUT_PULLUP);
  141. // Now start reading the data line to get the value from the DHT sensor.
  142. delayMicroseconds(60); // Delay a bit to let sensor pull data line low.
  143. // First expect a low signal for ~80 microseconds followed by a high signal
  144. // for ~80 microseconds again.
  145. if (expectPulse(LOW) == TIMEOUT) {
  146. DEBUG_PRINTLN(F("DHT timeout waiting for start signal low pulse."));
  147. _lastresult = false;
  148. return _lastresult;
  149. }
  150. if (expectPulse(HIGH) == TIMEOUT) {
  151. DEBUG_PRINTLN(F("DHT timeout waiting for start signal high pulse."));
  152. _lastresult = false;
  153. return _lastresult;
  154. }
  155. // Now read the 40 bits sent by the sensor. Each bit is sent as a 50
  156. // microsecond low pulse followed by a variable length high pulse. If the
  157. // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds
  158. // then it's a 1. We measure the cycle count of the initial 50us low pulse
  159. // and use that to compare to the cycle count of the high pulse to determine
  160. // if the bit is a 0 (high state cycle count < low state cycle count), or a
  161. // 1 (high state cycle count > low state cycle count). Note that for speed all
  162. // the pulses are read into a array and then examined in a later step.
  163. for (int i=0; i<80; i+=2) {
  164. cycles[i] = expectPulse(LOW);
  165. cycles[i+1] = expectPulse(HIGH);
  166. }
  167. } // Timing critical code is now complete.
  168. // Inspect pulses and determine which ones are 0 (high state cycle count < low
  169. // state cycle count), or 1 (high state cycle count > low state cycle count).
  170. for (int i=0; i<40; ++i) {
  171. uint32_t lowCycles = cycles[2*i];
  172. uint32_t highCycles = cycles[2*i+1];
  173. if ((lowCycles == TIMEOUT) || (highCycles == TIMEOUT)) {
  174. DEBUG_PRINTLN(F("DHT timeout waiting for pulse."));
  175. _lastresult = false;
  176. return _lastresult;
  177. }
  178. data[i/8] <<= 1;
  179. // Now compare the low and high cycle times to see if the bit is a 0 or 1.
  180. if (highCycles > lowCycles) {
  181. // High cycles are greater than 50us low cycle count, must be a 1.
  182. data[i/8] |= 1;
  183. }
  184. // Else high cycles are less than (or equal to, a weird case) the 50us low
  185. // cycle count so this must be a zero. Nothing needs to be changed in the
  186. // stored data.
  187. }
  188. DEBUG_PRINTLN(F("Received from DHT:"));
  189. DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", "));
  190. DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", "));
  191. DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", "));
  192. DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", "));
  193. DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? "));
  194. DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX);
  195. // Check we read 40 bits and that the checksum matches.
  196. if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
  197. _lastresult = true;
  198. return _lastresult;
  199. }
  200. else {
  201. DEBUG_PRINTLN(F("DHT checksum failure!"));
  202. _lastresult = false;
  203. return _lastresult;
  204. }
  205. }
  206. // Expect the signal line to be at the specified level for a period of time and
  207. // return a count of loop cycles spent at that level (this cycle count can be
  208. // used to compare the relative time of two pulses). If more than a millisecond
  209. // ellapses without the level changing then the call fails with a 0 response.
  210. // This is adapted from Arduino's pulseInLong function (which is only available
  211. // in the very latest IDE versions):
  212. // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c
  213. uint32_t DHT::expectPulse(bool level) {
  214. uint16_t count = 0;
  215. // On AVR platforms use direct GPIO port access as it's much faster and better
  216. // for catching pulses that are 10's of microseconds in length:
  217. #ifdef __AVR
  218. uint8_t portState = level ? _bit : 0;
  219. while ((*portInputRegister(_port) & _bit) == portState) {
  220. if (count++ >= _maxcycles) {
  221. return TIMEOUT; // Exceeded timeout, fail.
  222. }
  223. }
  224. // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266
  225. // right now, perhaps bugs in direct port access functions?).
  226. #else
  227. while (digitalRead(_pin) == level) {
  228. if (count++ >= _maxcycles) {
  229. return TIMEOUT; // Exceeded timeout, fail.
  230. }
  231. }
  232. #endif
  233. return count;
  234. }