You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

239 regels
5.5 KiB

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