dht.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. #include "user_interface.h"
  30. #include "platform.h"
  31. #include "c_stdio.h"
  32. #include "dht.h"
  33. #ifndef LOW
  34. #define LOW 0
  35. #endif /* ifndef LOW */
  36. #ifndef HIGH
  37. #define HIGH 1
  38. #endif /* ifndef HIGH */
  39. #define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low) (((byte_high) << 8) | (byte_low))
  40. static double dht_humidity;
  41. static double dht_temperature;
  42. static uint8_t dht_bytes[5]; // buffer to receive data
  43. static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay);
  44. /////////////////////////////////////////////////////
  45. //
  46. // PUBLIC
  47. //
  48. // return values:
  49. // Humidity
  50. double dht_getHumidity(void)
  51. {
  52. return dht_humidity;
  53. }
  54. // return values:
  55. // Temperature
  56. double dht_getTemperature(void)
  57. {
  58. return dht_temperature;
  59. }
  60. // return values:
  61. // DHTLIB_OK
  62. // DHTLIB_ERROR_CHECKSUM
  63. // DHTLIB_ERROR_TIMEOUT
  64. int dht_read_universal(uint8_t pin)
  65. {
  66. // READ VALUES
  67. int rv = dht_readSensor(pin, DHTLIB_DHT_UNI_WAKEUP);
  68. if (rv != DHTLIB_OK)
  69. {
  70. dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
  71. dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
  72. return rv; // propagate error value
  73. }
  74. #if defined(DHT_DEBUG_BYTES)
  75. int i;
  76. for (i = 0; i < 5; i++)
  77. {
  78. DHT_DEBUG("%02X\n", dht_bytes[i]);
  79. }
  80. #endif // defined(DHT_DEBUG_BYTES)
  81. // Assume it is DHT11
  82. // If it is DHT11, both bit[1] and bit[3] is 0
  83. if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
  84. {
  85. // It may DHT11
  86. // CONVERT AND STORE
  87. DHT_DEBUG("DHT11 method\n");
  88. dht_humidity = dht_bytes[0]; // dht_bytes[1] == 0;
  89. dht_temperature = dht_bytes[2]; // dht_bytes[3] == 0;
  90. // TEST CHECKSUM
  91. // dht_bytes[1] && dht_bytes[3] both 0
  92. uint8_t sum = dht_bytes[0] + dht_bytes[2];
  93. if (dht_bytes[4] != sum)
  94. {
  95. // It may not DHT11
  96. dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
  97. dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
  98. // Do nothing
  99. }
  100. else
  101. {
  102. return DHTLIB_OK;
  103. }
  104. }
  105. // Assume it is not DHT11
  106. // CONVERT AND STORE
  107. DHT_DEBUG("DHTxx method\n");
  108. dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
  109. dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
  110. if (dht_bytes[2] & 0x80) // negative dht_temperature
  111. {
  112. dht_temperature = -dht_temperature;
  113. }
  114. // TEST CHECKSUM
  115. uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
  116. if (dht_bytes[4] != sum)
  117. {
  118. return DHTLIB_ERROR_CHECKSUM;
  119. }
  120. return DHTLIB_OK;
  121. }
  122. // return values:
  123. // DHTLIB_OK
  124. // DHTLIB_ERROR_CHECKSUM
  125. // DHTLIB_ERROR_TIMEOUT
  126. int dht_read11(uint8_t pin)
  127. {
  128. // READ VALUES
  129. int rv = dht_readSensor(pin, DHTLIB_DHT11_WAKEUP);
  130. if (rv != DHTLIB_OK)
  131. {
  132. dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
  133. dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
  134. return rv;
  135. }
  136. // CONVERT AND STORE
  137. dht_humidity = dht_bytes[0]; // dht_bytes[1] == 0;
  138. dht_temperature = dht_bytes[2]; // dht_bytes[3] == 0;
  139. // TEST CHECKSUM
  140. // dht_bytes[1] && dht_bytes[3] both 0
  141. uint8_t sum = dht_bytes[0] + dht_bytes[2];
  142. if (dht_bytes[4] != sum) return DHTLIB_ERROR_CHECKSUM;
  143. return DHTLIB_OK;
  144. }
  145. // return values:
  146. // DHTLIB_OK
  147. // DHTLIB_ERROR_CHECKSUM
  148. // DHTLIB_ERROR_TIMEOUT
  149. int dht_read(uint8_t pin)
  150. {
  151. // READ VALUES
  152. int rv = dht_readSensor(pin, DHTLIB_DHT_WAKEUP);
  153. if (rv != DHTLIB_OK)
  154. {
  155. dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
  156. dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
  157. return rv; // propagate error value
  158. }
  159. // CONVERT AND STORE
  160. dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
  161. dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
  162. if (dht_bytes[2] & 0x80) // negative dht_temperature
  163. {
  164. dht_temperature = -dht_temperature;
  165. }
  166. // TEST CHECKSUM
  167. uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
  168. if (dht_bytes[4] != sum)
  169. {
  170. return DHTLIB_ERROR_CHECKSUM;
  171. }
  172. return DHTLIB_OK;
  173. }
  174. // return values:
  175. // DHTLIB_OK
  176. // DHTLIB_ERROR_CHECKSUM
  177. // DHTLIB_ERROR_TIMEOUT
  178. int dht_read21(uint8_t pin) __attribute__((alias("dht_read")));
  179. // return values:
  180. // DHTLIB_OK
  181. // DHTLIB_ERROR_CHECKSUM
  182. // DHTLIB_ERROR_TIMEOUT
  183. int dht_read22(uint8_t pin) __attribute__((alias("dht_read")));
  184. // return values:
  185. // DHTLIB_OK
  186. // DHTLIB_ERROR_CHECKSUM
  187. // DHTLIB_ERROR_TIMEOUT
  188. int dht_read33(uint8_t pin) __attribute__((alias("dht_read")));
  189. // return values:
  190. // DHTLIB_OK
  191. // DHTLIB_ERROR_CHECKSUM
  192. // DHTLIB_ERROR_TIMEOUT
  193. int dht_read44(uint8_t pin) __attribute__((alias("dht_read")));
  194. /////////////////////////////////////////////////////
  195. //
  196. // PRIVATE
  197. //
  198. // return values:
  199. // DHTLIB_OK
  200. // DHTLIB_ERROR_TIMEOUT
  201. int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
  202. {
  203. // INIT BUFFERVAR TO RECEIVE DATA
  204. uint8_t mask = 128;
  205. uint8_t idx = 0;
  206. uint8_t i = 0;
  207. // replace digitalRead() with Direct Port Reads.
  208. // reduces footprint ~100 bytes => portability issue?
  209. // direct port read is about 3x faster
  210. // uint8_t bit = digitalPinToBitMask(pin);
  211. // uint8_t port = digitalPinToPort(pin);
  212. // volatile uint8_t *PIR = portInputRegister(port);
  213. // EMPTY BUFFER
  214. for (i = 0; i < 5; i++) dht_bytes[i] = 0;
  215. // REQUEST SAMPLE
  216. // pinMode(pin, OUTPUT);
  217. platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP);
  218. DIRECT_MODE_OUTPUT(pin);
  219. // digitalWrite(pin, LOW); // T-be
  220. DIRECT_WRITE_LOW(pin);
  221. // delay(wakeupDelay);
  222. for (i = 0; i < wakeupDelay; i++) os_delay_us(1000);
  223. // Disable interrupts
  224. ets_intr_lock();
  225. // digitalWrite(pin, HIGH); // T-go
  226. DIRECT_WRITE_HIGH(pin);
  227. os_delay_us(40);
  228. // pinMode(pin, INPUT);
  229. DIRECT_MODE_INPUT(pin);
  230. // GET ACKNOWLEDGE or TIMEOUT
  231. uint16_t loopCntLOW = DHTLIB_TIMEOUT;
  232. while (DIRECT_READ(pin) == LOW ) // T-rel
  233. {
  234. os_delay_us(1);
  235. if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
  236. }
  237. uint16_t loopCntHIGH = DHTLIB_TIMEOUT;
  238. while (DIRECT_READ(pin) != LOW ) // T-reh
  239. {
  240. os_delay_us(1);
  241. if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
  242. }
  243. // READ THE OUTPUT - 40 BITS => 5 BYTES
  244. for (i = 40; i != 0; i--)
  245. {
  246. loopCntLOW = DHTLIB_TIMEOUT;
  247. while (DIRECT_READ(pin) == LOW )
  248. {
  249. os_delay_us(1);
  250. if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
  251. }
  252. uint32_t t = system_get_time();
  253. loopCntHIGH = DHTLIB_TIMEOUT;
  254. while (DIRECT_READ(pin) != LOW )
  255. {
  256. os_delay_us(1);
  257. if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
  258. }
  259. if ((system_get_time() - t) > 40)
  260. {
  261. dht_bytes[idx] |= mask;
  262. }
  263. mask >>= 1;
  264. if (mask == 0) // next byte?
  265. {
  266. mask = 128;
  267. idx++;
  268. }
  269. }
  270. // Enable interrupts
  271. ets_intr_unlock();
  272. // pinMode(pin, OUTPUT);
  273. DIRECT_MODE_OUTPUT(pin);
  274. // digitalWrite(pin, HIGH);
  275. DIRECT_WRITE_HIGH(pin);
  276. return DHTLIB_OK;
  277. }
  278. //
  279. // END OF FILE
  280. //