blob: 74ff70e9b7dfd5aa6290f71defdc1cb6f83cc647 [file] [log] [blame]
Gordon Hendersonda384432013-05-13 19:43:26 +01001/*
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
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000025#include <sys/time.h>
26#include <stdio.h>
Gordon Hendersonda384432013-05-13 19:43:26 +010027//#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:
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000042 * Wait for a transition from low to high on the bus
Gordon Hendersonda384432013-05-13 19:43:26 +010043 *********************************************************************************
44 */
45
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000046static int maxDetectLowHighWait (const int pin)
Gordon Hendersonda384432013-05-13 19:43:26 +010047{
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000048 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) ;
Gordon Hendersonda384432013-05-13 19:43:26 +010056
57 while (digitalRead (pin) == HIGH)
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000058 {
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) ;
Gordon Hendersonda384432013-05-13 19:43:26 +010070
71 while (digitalRead (pin) == LOW)
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000072 {
73 gettimeofday (&now, NULL) ;
74 if (timercmp (&now, &timeUp, >))
75 return FALSE ;
76 }
77
78 return TRUE ;
Gordon Hendersonda384432013-05-13 19:43:26 +010079}
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 {
Gordon Hendersonb0a60c32016-02-29 06:57:38 +000095 if (!maxDetectLowHighWait (pin))
96 return 0 ;
Gordon Hendersonda384432013-05-13 19:43:26 +010097
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] ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000122 struct timeval now, then, took ;
123
124// See how long we took
125
126 gettimeofday (&then, NULL) ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100127
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
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000138 if (!maxDetectLowHighWait (pin))
139 return FALSE ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100140
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
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000154// 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
Gordon Hendersonda384432013-05-13 19:43:26 +0100170 return checksum == localBuf [4] ;
171}
172
173
174/*
175 * readRHT03:
176 * Read the Temperature & Humidity from an RHT03 sensor
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000177 * Values returned are *10, so 123 is 12.3.
Gordon Hendersonda384432013-05-13 19:43:26 +0100178 *********************************************************************************
179 */
180
181int readRHT03 (const int pin, int *temp, int *rh)
182{
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000183 static struct timeval then ; // will initialise to zero
184 static int lastTemp = 0 ;
185 static int lastRh = 0 ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100186
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000187 int result ;
188 struct timeval now, timeOut ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100189 unsigned char buffer [4] ;
190
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000191// The data sheets say to not read more than once every 2 seconds, so you
192// get the last good reading
Gordon Hendersonda384432013-05-13 19:43:26 +0100193
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000194 gettimeofday (&now, NULL) ;
195 if (timercmp (&now, &then, <))
Gordon Hendersonda384432013-05-13 19:43:26 +0100196 {
Gordon Hendersonda384432013-05-13 19:43:26 +0100197 *rh = lastRh ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000198 *temp = lastTemp ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100199 return TRUE ;
200 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000201
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)
Gordon Hendersonda384432013-05-13 19:43:26 +0100217 return FALSE ;
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000218
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 ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100226 }
Gordon Hendersonb0a60c32016-02-29 06:57:38 +0000227
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 ;
Gordon Hendersonda384432013-05-13 19:43:26 +0100238}