Statistics
| Branch: | Revision:

ddr4s / fw / wiringPi / devLib / maxdetect.c @ 32:cadb9025f1e0

History | View | Annotate | Download (5.53 KB)

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

    
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

    
46
static 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

    
88
static 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

    
117
int 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

    
181
int 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
}