dht.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. //
  2. // FILE: dht.cpp
  3. // AUTHOR: Rob Tillaart
  4. // VERSION: 0.1.14
  5. // PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
  6. // URL: http://arduino.cc/playground/Main/DHTLib
  7. //
  8. // HISTORY:
  9. // 0.1.14 replace digital read with faster (~3x) code => more robust low MHz machines.
  10. // 0.1.13 fix negative dht_temperature
  11. // 0.1.12 support DHT33 and DHT44 initial version
  12. // 0.1.11 renamed DHTLIB_TIMEOUT
  13. // 0.1.10 optimized faster WAKEUP + TIMEOUT
  14. // 0.1.09 optimize size: timeout check + use of mask
  15. // 0.1.08 added formula for timeout based upon clockspeed
  16. // 0.1.07 added support for DHT21
  17. // 0.1.06 minimize footprint (2012-12-27)
  18. // 0.1.05 fixed negative dht_temperature bug (thanks to Roseman)
  19. // 0.1.04 improved readability of code using DHTLIB_OK in code
  20. // 0.1.03 added error values for temp and dht_humidity when read failed
  21. // 0.1.02 added error codes
  22. // 0.1.01 added support for Arduino 1.0, fixed typos (31/12/2011)
  23. // 0.1.00 by Rob Tillaart (01/04/2011)
  24. //
  25. // inspired by DHT11 library
  26. //
  27. // Released to the public domain
  28. //
  29. // #define NODE_DEBUG
  30. #include "user_interface.h"
  31. #include "platform.h"
  32. #include <stdio.h>
  33. #include "dht.h"
  34. #ifndef LOW
  35. #define LOW 0
  36. #endif /* ifndef LOW */
  37. #ifndef HIGH
  38. #define HIGH 1
  39. #endif /* ifndef HIGH */
  40. #define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low) ((uint16_t)((byte_high) << 8) | (byte_low))
  41. static double dht_humidity;
  42. static double dht_temperature;
  43. static uint8_t dht_bytes[5]; // buffer to receive data
  44. static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay);
  45. /////////////////////////////////////////////////////
  46. //
  47. // PUBLIC
  48. //
  49. // return values:
  50. // Humidity
  51. double dht_getHumidity(void)
  52. {
  53. return dht_humidity;
  54. }
  55. // return values:
  56. // Temperature
  57. double dht_getTemperature(void)
  58. {
  59. return dht_temperature;
  60. }
  61. // return values:
  62. // DHTLIB_OK
  63. // DHTLIB_ERROR_CHECKSUM
  64. // DHTLIB_ERROR_TIMEOUT
  65. int dht_read(uint8_t pin, dht_type type)
  66. {
  67. // READ VALUES
  68. int rv = dht_readSensor(pin,
  69. type == DHT22 ? DHTLIB_DHT_WAKEUP :
  70. type == DHT11 ? DHTLIB_DHT11_WAKEUP :
  71. DHTLIB_DHT_UNI_WAKEUP
  72. );
  73. if (rv != DHTLIB_OK)
  74. {
  75. dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
  76. dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
  77. return rv; // propagate error value
  78. }
  79. NODE_DBG("DHT registers: %x\t%x\t%x\t%x\t%x == %x\n", dht_bytes[0], dht_bytes[1], dht_bytes[2], dht_bytes[3], dht_bytes[4], (uint8_t)(dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3]));
  80. // Assume it is special case of DHT11,
  81. // i.e. positive temperature and dht_bytes[3] == 0 ((dht_bytes[3] & 0x0f) * 0.1 to be added to temperature readout)
  82. // If it is DHT11, both temp and humidity's decimal
  83. dht_humidity = dht_bytes[0];
  84. dht_temperature = dht_bytes[2];
  85. if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
  86. {
  87. // It may DHT11
  88. // CONVERT AND STORE
  89. NODE_DBG("DHT11 method\n");
  90. // TEST CHECKSUM
  91. uint8_t sum = dht_bytes[0] + dht_bytes[2];
  92. if (dht_bytes[4] == sum)
  93. {
  94. return DHTLIB_OK;
  95. }
  96. }
  97. // Assume it is not DHT11 special case
  98. // CONVERT AND STORE
  99. NODE_DBG("DHTxx method\n");
  100. switch (type) {
  101. case DHT11:
  102. case DHT12:
  103. dht_humidity += dht_bytes[1] * 0.1;
  104. break;
  105. default:
  106. dht_humidity = COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
  107. break;
  108. }
  109. switch (type) {
  110. case DHT11:
  111. if (dht_bytes[3] & 0x80) {
  112. dht_temperature = -1 - dht_temperature;
  113. }
  114. dht_temperature += (dht_bytes[3] & 0x0f) * 0.1;
  115. break;
  116. case DHT12:
  117. dht_temperature += (dht_bytes[3] & 0x0f) * 0.1;
  118. if (dht_bytes[2] & 0x80) // negative dht_temperature
  119. {
  120. dht_temperature *= -1;
  121. }
  122. break;
  123. default: // DHT22, DHT_NON11
  124. dht_temperature = COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
  125. if (dht_bytes[2] & 0x80) // negative dht_temperature
  126. {
  127. dht_temperature *= -1;
  128. }
  129. break;
  130. }
  131. // TEST CHECKSUM
  132. uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
  133. if (dht_bytes[4] != sum)
  134. {
  135. return DHTLIB_ERROR_CHECKSUM;
  136. }
  137. return DHTLIB_OK;
  138. }
  139. /////////////////////////////////////////////////////
  140. //
  141. // PRIVATE
  142. //
  143. // return values:
  144. // DHTLIB_OK
  145. // DHTLIB_ERROR_TIMEOUT
  146. int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
  147. {
  148. // INIT BUFFERVAR TO RECEIVE DATA
  149. uint8_t mask = 128;
  150. uint8_t idx = 0;
  151. uint8_t i = 0;
  152. // replace digitalRead() with Direct Port Reads.
  153. // reduces footprint ~100 bytes => portability issue?
  154. // direct port read is about 3x faster
  155. // uint8_t bit = digitalPinToBitMask(pin);
  156. // uint8_t port = digitalPinToPort(pin);
  157. // volatile uint8_t *PIR = portInputRegister(port);
  158. // EMPTY BUFFER
  159. memset(dht_bytes, 0, sizeof(uint8_t)*5);
  160. // REQUEST SAMPLE
  161. // pinMode(pin, OUTPUT);
  162. platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP);
  163. DIRECT_MODE_OUTPUT(pin);
  164. // digitalWrite(pin, LOW); // T-be
  165. DIRECT_WRITE_LOW(pin);
  166. // delay(wakeupDelay);
  167. for (i = 0; i < wakeupDelay; i++) os_delay_us(1000);
  168. // Disable interrupts
  169. ets_intr_lock();
  170. // digitalWrite(pin, HIGH); // T-go
  171. DIRECT_WRITE_HIGH(pin);
  172. os_delay_us(40);
  173. // pinMode(pin, INPUT);
  174. DIRECT_MODE_INPUT(pin);
  175. // GET ACKNOWLEDGE or TIMEOUT
  176. uint16_t loopCntLOW = DHTLIB_TIMEOUT;
  177. while (DIRECT_READ(pin) == LOW ) // T-rel
  178. {
  179. os_delay_us(1);
  180. if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
  181. }
  182. uint16_t loopCntHIGH = DHTLIB_TIMEOUT;
  183. while (DIRECT_READ(pin) != LOW ) // T-reh
  184. {
  185. os_delay_us(1);
  186. if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
  187. }
  188. // READ THE OUTPUT - 40 BITS => 5 BYTES
  189. for (i = 40; i != 0; i--)
  190. {
  191. loopCntLOW = DHTLIB_TIMEOUT;
  192. while (DIRECT_READ(pin) == LOW )
  193. {
  194. os_delay_us(1);
  195. if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
  196. }
  197. uint32_t t = system_get_time();
  198. loopCntHIGH = DHTLIB_TIMEOUT;
  199. while (DIRECT_READ(pin) != LOW )
  200. {
  201. os_delay_us(1);
  202. if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
  203. }
  204. if ((system_get_time() - t) > 40)
  205. {
  206. dht_bytes[idx] |= mask;
  207. }
  208. mask >>= 1;
  209. if (mask == 0) // next byte?
  210. {
  211. mask = 128;
  212. idx++;
  213. }
  214. }
  215. // Enable interrupts
  216. ets_intr_unlock();
  217. // pinMode(pin, OUTPUT);
  218. DIRECT_MODE_OUTPUT(pin);
  219. // digitalWrite(pin, HIGH);
  220. DIRECT_WRITE_HIGH(pin);
  221. return DHTLIB_OK;
  222. }
  223. //
  224. // END OF FILE
  225. //