rht03.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * rht03.c:
  3. * Extend wiringPi with the rht03 Maxdetect 1-Wire sensor.
  4. * Copyright (c) 2016-2017 Gordon Henderson
  5. ***********************************************************************
  6. * This file is part of wiringPi:
  7. * https://projects.drogon.net/raspberry-pi/wiringpi/
  8. *
  9. * wiringPi is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * wiringPi is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with wiringPi.
  21. * If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************
  23. */
  24. #include <sys/time.h>
  25. #include <stdio.h>
  26. #include <stdio.h>
  27. #include <time.h>
  28. #include "wiringPi.h"
  29. #include "rht03.h"
  30. /*
  31. * maxDetectLowHighWait:
  32. * Wait for a transition from low to high on the bus
  33. *********************************************************************************
  34. */
  35. static int maxDetectLowHighWait (const int pin)
  36. {
  37. struct timeval now, timeOut, timeUp ;
  38. // If already high then wait for pin to go low
  39. gettimeofday (&now, NULL) ;
  40. timerclear (&timeOut) ;
  41. timeOut.tv_usec = 1000 ;
  42. timeradd (&now, &timeOut, &timeUp) ;
  43. while (digitalRead (pin) == HIGH)
  44. {
  45. gettimeofday (&now, NULL) ;
  46. if (timercmp (&now, &timeUp, >))
  47. return FALSE ;
  48. }
  49. // Wait for it to go HIGH
  50. gettimeofday (&now, NULL) ;
  51. timerclear (&timeOut) ;
  52. timeOut.tv_usec = 1000 ;
  53. timeradd (&now, &timeOut, &timeUp) ;
  54. while (digitalRead (pin) == LOW)
  55. {
  56. gettimeofday (&now, NULL) ;
  57. if (timercmp (&now, &timeUp, >))
  58. return FALSE ;
  59. }
  60. return TRUE ;
  61. }
  62. /*
  63. * maxDetectClockByte:
  64. * Read in a single byte from the MaxDetect bus
  65. *********************************************************************************
  66. */
  67. static unsigned int maxDetectClockByte (const int pin)
  68. {
  69. unsigned int byte = 0 ;
  70. int bit ;
  71. for (bit = 0 ; bit < 8 ; ++bit)
  72. {
  73. if (!maxDetectLowHighWait (pin))
  74. return 0 ;
  75. // bit starting now - we need to time it.
  76. delayMicroseconds (30) ;
  77. byte <<= 1 ;
  78. if (digitalRead (pin) == HIGH) // It's a 1
  79. byte |= 1 ;
  80. }
  81. return byte ;
  82. }
  83. /*
  84. * maxDetectRead:
  85. * Read in and return the 4 data bytes from the MaxDetect sensor.
  86. * Return TRUE/FALSE depending on the checksum validity
  87. *********************************************************************************
  88. */
  89. static int maxDetectRead (const int pin, unsigned char buffer [4])
  90. {
  91. int i ;
  92. unsigned int checksum ;
  93. unsigned char localBuf [5] ;
  94. struct timeval now, then, took ;
  95. // See how long we took
  96. gettimeofday (&then, NULL) ;
  97. // Wake up the RHT03 by pulling the data line low, then high
  98. // Low for 10mS, high for 40uS.
  99. pinMode (pin, OUTPUT) ;
  100. digitalWrite (pin, 0) ; delay (10) ;
  101. digitalWrite (pin, 1) ; delayMicroseconds (40) ;
  102. pinMode (pin, INPUT) ;
  103. // Now wait for sensor to pull pin low
  104. if (!maxDetectLowHighWait (pin))
  105. return FALSE ;
  106. // and read in 5 bytes (40 bits)
  107. for (i = 0 ; i < 5 ; ++i)
  108. localBuf [i] = maxDetectClockByte (pin) ;
  109. checksum = 0 ;
  110. for (i = 0 ; i < 4 ; ++i)
  111. {
  112. buffer [i] = localBuf [i] ;
  113. checksum += localBuf [i] ;
  114. }
  115. checksum &= 0xFF ;
  116. // See how long we took
  117. gettimeofday (&now, NULL) ;
  118. timersub (&now, &then, &took) ;
  119. // Total time to do this should be:
  120. // 10mS + 40µS - reset
  121. // + 80µS + 80µS - sensor doing its low -> high thing
  122. // + 40 * (50µS + 27µS (0) or 70µS (1) )
  123. // = 15010µS
  124. // so if we take more than that, we've had a scheduling interruption and the
  125. // reading is probably bogus.
  126. if ((took.tv_sec != 0) || (took.tv_usec > 16000))
  127. return FALSE ;
  128. return checksum == localBuf [4] ;
  129. }
  130. /*
  131. * myReadRHT03:
  132. * Read the Temperature & Humidity from an RHT03 sensor
  133. * Values returned are *10, so 123 is 12.3.
  134. *********************************************************************************
  135. */
  136. static int myReadRHT03 (const int pin, int *temp, int *rh)
  137. {
  138. int result ;
  139. unsigned char buffer [4] ;
  140. // Read ...
  141. result = maxDetectRead (pin, buffer) ;
  142. if (!result)
  143. return FALSE ;
  144. *rh = (buffer [0] * 256 + buffer [1]) ;
  145. *temp = (buffer [2] * 256 + buffer [3]) ;
  146. if ((*temp & 0x8000) != 0) // Negative
  147. {
  148. *temp &= 0x7FFF ;
  149. *temp = -*temp ;
  150. }
  151. // Discard obviously bogus readings - the checksum can't detect a 2-bit error
  152. // (which does seem to happen - no realtime here)
  153. if ((*rh > 999) || (*temp > 800) || (*temp < -400))
  154. return FALSE ;
  155. return TRUE ;
  156. }
  157. /*
  158. * myAnalogRead:
  159. *********************************************************************************
  160. */
  161. static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
  162. {
  163. int piPin = node->fd ;
  164. int chan = pin - node->pinBase ;
  165. int temp = -9997 ;
  166. int rh = -9997 ;
  167. int try ;
  168. if (chan > 1)
  169. return -9999 ; // Bad parameters
  170. for (try = 0 ; try < 10 ; ++try)
  171. {
  172. if (myReadRHT03 (piPin, &temp, &rh))
  173. return chan == 0 ? temp : rh ;
  174. }
  175. return -9998 ;
  176. }
  177. /*
  178. * rht03Setup:
  179. * Create a new instance of an RHT03 temperature sensor.
  180. *********************************************************************************
  181. */
  182. int rht03Setup (const int pinBase, const int piPin)
  183. {
  184. struct wiringPiNodeStruct *node ;
  185. if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin
  186. return FALSE ;
  187. // 2 pins - temperature and humidity
  188. node = wiringPiNewNode (pinBase, 2) ;
  189. node->fd = piPin ;
  190. node->analogRead = myAnalogRead ;
  191. return TRUE ;
  192. }