blob: 74ff70e9b7dfd5aa6290f71defdc1cb6f83cc647 [file] [log] [blame]
Deokgyu Yang2c7e86b2020-04-28 10:56:11 +09001/*
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
25#include <sys/time.h>
26#include <stdio.h>
27//#include <stdlib.h>
28//#include <unistd.h>
29
30#include <wiringPi.h>
31
32#include "maxdetect.h"
33
34#ifndef TRUE
35# define TRUE (1==1)
36# define FALSE (1==2)
37#endif
38
39
40/*
41 * maxDetectLowHighWait:
42 * Wait for a transition from low to high on the bus
43 *********************************************************************************
44 */
45
46static int maxDetectLowHighWait (const int pin)
47{
48 struct timeval now, timeOut, timeUp ;
49
50// If already high then wait for pin to go low
51
52 gettimeofday (&now, NULL) ;
53 timerclear (&timeOut) ;
54 timeOut.tv_usec = 1000 ;
55 timeradd (&now, &timeOut, &timeUp) ;
56
57 while (digitalRead (pin) == HIGH)
58 {
59 gettimeofday (&now, NULL) ;
60 if (timercmp (&now, &timeUp, >))
61 return FALSE ;
62 }
63
64// Wait for it to go HIGH
65
66 gettimeofday (&now, NULL) ;
67 timerclear (&timeOut) ;
68 timeOut.tv_usec = 1000 ;
69 timeradd (&now, &timeOut, &timeUp) ;
70
71 while (digitalRead (pin) == LOW)
72 {
73 gettimeofday (&now, NULL) ;
74 if (timercmp (&now, &timeUp, >))
75 return FALSE ;
76 }
77
78 return TRUE ;
79}
80
81
82/*
83 * maxDetectClockByte:
84 * Read in a single byte from the MaxDetect bus
85 *********************************************************************************
86 */
87
88static unsigned int maxDetectClockByte (const int pin)
89{
90 unsigned int byte = 0 ;
91 int bit ;
92
93 for (bit = 0 ; bit < 8 ; ++bit)
94 {
95 if (!maxDetectLowHighWait (pin))
96 return 0 ;
97
98// bit starting now - we need to time it.
99
100 delayMicroseconds (30) ;
101 byte <<= 1 ;
102 if (digitalRead (pin) == HIGH) // It's a 1
103 byte |= 1 ;
104 }
105
106 return byte ;
107}
108
109
110/*
111 * maxDetectRead:
112 * Read in and return the 4 data bytes from the MaxDetect sensor.
113 * Return TRUE/FALSE depending on the checksum validity
114 *********************************************************************************
115 */
116
117int maxDetectRead (const int pin, unsigned char buffer [4])
118{
119 int i ;
120 unsigned int checksum ;
121 unsigned char localBuf [5] ;
122 struct timeval now, then, took ;
123
124// See how long we took
125
126 gettimeofday (&then, NULL) ;
127
128// Wake up the RHT03 by pulling the data line low, then high
129// Low for 10mS, high for 40uS.
130
131 pinMode (pin, OUTPUT) ;
132 digitalWrite (pin, 0) ; delay (10) ;
133 digitalWrite (pin, 1) ; delayMicroseconds (40) ;
134 pinMode (pin, INPUT) ;
135
136// Now wait for sensor to pull pin low
137
138 if (!maxDetectLowHighWait (pin))
139 return FALSE ;
140
141// and read in 5 bytes (40 bits)
142
143 for (i = 0 ; i < 5 ; ++i)
144 localBuf [i] = maxDetectClockByte (pin) ;
145
146 checksum = 0 ;
147 for (i = 0 ; i < 4 ; ++i)
148 {
149 buffer [i] = localBuf [i] ;
150 checksum += localBuf [i] ;
151 }
152 checksum &= 0xFF ;
153
154// See how long we took
155
156 gettimeofday (&now, NULL) ;
157 timersub (&now, &then, &took) ;
158
159// Total time to do this should be:
160// 10mS + 40µS - reset
161// + 80µS + 80µS - sensor doing its low -> high thing
162// + 40 * (50µS + 27µS (0) or 70µS (1) )
163// = 15010µS
164// so if we take more than that, we've had a scheduling interruption and the
165// reading is probably bogus.
166
167 if ((took.tv_sec != 0) || (took.tv_usec > 16000))
168 return FALSE ;
169
170 return checksum == localBuf [4] ;
171}
172
173
174/*
175 * readRHT03:
176 * Read the Temperature & Humidity from an RHT03 sensor
177 * Values returned are *10, so 123 is 12.3.
178 *********************************************************************************
179 */
180
181int readRHT03 (const int pin, int *temp, int *rh)
182{
183 static struct timeval then ; // will initialise to zero
184 static int lastTemp = 0 ;
185 static int lastRh = 0 ;
186
187 int result ;
188 struct timeval now, timeOut ;
189 unsigned char buffer [4] ;
190
191// The data sheets say to not read more than once every 2 seconds, so you
192// get the last good reading
193
194 gettimeofday (&now, NULL) ;
195 if (timercmp (&now, &then, <))
196 {
197 *rh = lastRh ;
198 *temp = lastTemp ;
199 return TRUE ;
200 }
201
202// Set timeout for next read
203
204 gettimeofday (&now, NULL) ;
205 timerclear (&timeOut) ;
206 timeOut.tv_sec = 2 ;
207 timeradd (&now, &timeOut, &then) ;
208
209// Read ...
210
211 result = maxDetectRead (pin, buffer) ;
212
213 if (!result) // Try again, but just once
214 result = maxDetectRead (pin, buffer) ;
215
216 if (!result)
217 return FALSE ;
218
219 *rh = (buffer [0] * 256 + buffer [1]) ;
220 *temp = (buffer [2] * 256 + buffer [3]) ;
221
222 if ((*temp & 0x8000) != 0) // Negative
223 {
224 *temp &= 0x7FFF ;
225 *temp = -*temp ;
226 }
227
228// Discard obviously bogus readings - the checksum can't detect a 2-bit error
229// (which does seem to happen - no realtime here)
230
231 if ((*rh > 999) || (*temp > 800) || (*temp < -400))
232 return FALSE ;
233
234 lastRh = *rh ;
235 lastTemp = *temp ;
236
237 return TRUE ;
238}