Statistics
| Branch: | Revision:

ddr4s / fw / wiringPi / wiringPi / rht03.c @ 32:cadb9025f1e0

History | View | Annotate | Download (5.79 KB)

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

    
25
#include <sys/time.h>
26
#include <stdio.h>
27
#include <stdio.h>
28
#include <time.h>
29

    
30
#include "wiringPi.h"
31
#include "rht03.h"
32

    
33
/*
34
 * maxDetectLowHighWait:
35
 *        Wait for a transition from low to high on the bus
36
 *********************************************************************************
37
 */
38

    
39
static int maxDetectLowHighWait (const int pin)
40
{
41
  struct timeval now, timeOut, timeUp ;
42

    
43
// If already high then wait for pin to go low
44

    
45
  gettimeofday (&now, NULL) ;
46
  timerclear   (&timeOut) ;
47
  timeOut.tv_usec = 1000 ;
48
  timeradd     (&now, &timeOut, &timeUp) ;
49

    
50
  while (digitalRead (pin) == HIGH)
51
  {
52
    gettimeofday (&now, NULL) ;
53
    if (timercmp (&now, &timeUp, >))
54
      return FALSE ;
55
  }
56

    
57
// Wait for it to go HIGH
58

    
59
  gettimeofday (&now, NULL) ;
60
  timerclear (&timeOut) ;
61
  timeOut.tv_usec = 1000 ;
62
  timeradd (&now, &timeOut, &timeUp) ;
63

    
64
  while (digitalRead (pin) == LOW)
65
  {
66
    gettimeofday (&now, NULL) ;
67
    if (timercmp (&now, &timeUp, >))
68
      return FALSE ;
69
  }
70

    
71
  return TRUE ;
72
}
73

    
74

    
75
/*
76
 * maxDetectClockByte:
77
 *        Read in a single byte from the MaxDetect bus
78
 *********************************************************************************
79
 */
80

    
81
static unsigned int maxDetectClockByte (const int pin)
82
{
83
  unsigned int byte = 0 ;
84
  int bit ;
85

    
86
  for (bit = 0 ; bit < 8 ; ++bit)
87
  {
88
    if (!maxDetectLowHighWait (pin))
89
      return 0 ;
90

    
91
// bit starting now - we need to time it.
92

    
93
    delayMicroseconds (30) ;
94
    byte <<= 1 ;
95
    if (digitalRead (pin) == HIGH)        // It's a 1
96
      byte |= 1 ;
97
  }
98

    
99
  return byte ;
100
}
101

    
102

    
103
/*
104
 * maxDetectRead:
105
 *        Read in and return the 4 data bytes from the MaxDetect sensor.
106
 *        Return TRUE/FALSE depending on the checksum validity
107
 *********************************************************************************
108
 */
109

    
110
static int maxDetectRead (const int pin, unsigned char buffer [4])
111
{
112
  int i ;
113
  unsigned int checksum ;
114
  unsigned char localBuf [5] ;
115
  struct timeval now, then, took ;
116

    
117
// See how long we took
118

    
119
  gettimeofday (&then, NULL) ;
120

    
121
// Wake up the RHT03 by pulling the data line low, then high
122
//        Low for 10mS, high for 40uS.
123

    
124
  pinMode      (pin, OUTPUT) ;
125
  digitalWrite (pin, 0) ; delay             (10) ;
126
  digitalWrite (pin, 1) ; delayMicroseconds (40) ;
127
  pinMode      (pin, INPUT) ;
128

    
129
// Now wait for sensor to pull pin low
130

    
131
  if (!maxDetectLowHighWait (pin))
132
    return FALSE ;
133

    
134
// and read in 5 bytes (40 bits)
135

    
136
  for (i = 0 ; i < 5 ; ++i)
137
    localBuf [i] = maxDetectClockByte (pin) ;
138

    
139
  checksum = 0 ;
140
  for (i = 0 ; i < 4 ; ++i)
141
  {
142
    buffer [i] = localBuf [i] ;
143
    checksum += localBuf [i] ;
144
  }
145
  checksum &= 0xFF ;
146

    
147
// See how long we took
148
  
149
  gettimeofday (&now, NULL) ;
150
  timersub (&now, &then, &took) ;
151

    
152
// Total time to do this should be:
153
//        10mS + 40µS - reset
154
//        + 80µS + 80µS - sensor doing its low -> high thing
155
//        + 40 * (50µS + 27µS (0) or 70µS (1) )
156
//        = 15010µS
157
// so if we take more than that, we've had a scheduling interruption and the
158
// reading is probably bogus.
159

    
160
  if ((took.tv_sec != 0) || (took.tv_usec > 16000))
161
    return FALSE ;
162

    
163
  return checksum == localBuf [4] ;
164
}
165

    
166

    
167
/*
168
 * myReadRHT03:
169
 *        Read the Temperature & Humidity from an RHT03 sensor
170
 *        Values returned are *10, so 123 is 12.3.
171
 *********************************************************************************
172
 */
173

    
174
static int myReadRHT03 (const int pin, int *temp, int *rh)
175
{
176
  int result ;
177
  unsigned char buffer [4] ;
178

    
179
// Read ...
180
  
181
  result = maxDetectRead (pin, buffer) ;
182

    
183
  if (!result)
184
    return FALSE ;
185

    
186
  *rh   = (buffer [0] * 256 + buffer [1]) ;
187
  *temp = (buffer [2] * 256 + buffer [3]) ;
188

    
189
  if ((*temp & 0x8000) != 0)        // Negative
190
  {
191
    *temp &= 0x7FFF ;
192
    *temp = -*temp ;
193
  }
194

    
195
// Discard obviously bogus readings - the checksum can't detect a 2-bit error
196
//        (which does seem to happen - no realtime here)
197

    
198
  if ((*rh > 999) || (*temp > 800) || (*temp < -400))
199
    return FALSE ;
200

    
201
  return TRUE ;
202
}
203

    
204

    
205
/*
206
 * myAnalogRead:
207
 *********************************************************************************
208
 */
209

    
210
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
211
{
212
  int piPin = node->fd ;
213
  int chan  = pin - node->pinBase ;
214
  int temp  = -9997 ;
215
  int rh    = -9997 ;
216
  int try ;
217

    
218
  if (chan > 1)
219
    return -9999 ;        // Bad parameters
220

    
221
  for (try = 0 ; try < 10 ; ++try)
222
  {
223
    if (myReadRHT03 (piPin, &temp, &rh))
224
      return chan == 0 ? temp : rh ;
225
  }
226

    
227
  return -9998 ;
228
}
229

    
230

    
231
/*
232
 * rht03Setup:
233
 *        Create a new instance of an RHT03 temperature sensor.
234
 *********************************************************************************
235
 */
236

    
237
int rht03Setup (const int pinBase, const int piPin)
238
{
239
  struct wiringPiNodeStruct *node ;
240

    
241
  if ((piPin & PI_GPIO_MASK) != 0)        // Must be an on-board pin
242
    return FALSE ;
243
  
244
// 2 pins - temperature and humidity
245

    
246
  node = wiringPiNewNode (pinBase, 2) ;
247

    
248
  node->fd         = piPin ;
249
  node->analogRead = myAnalogRead ;
250

    
251
  return TRUE ;
252
}