1
- /* DHT library
1
+ /* DHT library
2
2
3
3
MIT license
4
4
written by Adafruit Industries
@@ -9,8 +9,9 @@ written by Adafruit Industries
9
9
DHT::DHT (uint8_t pin, uint8_t type, uint8_t count) {
10
10
_pin = pin;
11
11
_type = type;
12
- _count = count;
13
- firstreading = true ;
12
+ _firstreading = true ;
13
+ // Note that count is now ignored as the DHT reading algorithm adjusts itself
14
+ // basd on the speed of the processor.
14
15
}
15
16
16
17
void DHT::begin (void ) {
@@ -22,158 +23,198 @@ void DHT::begin(void) {
22
23
23
24
// boolean S == Scale. True == Farenheit; False == Celcius
24
25
float DHT::readTemperature (bool S) {
25
- float f;
26
+ float f = NAN ;
26
27
27
28
if (read ()) {
28
29
switch (_type) {
29
30
case DHT11:
30
31
f = data[2 ];
31
- if (S)
32
- f = convertCtoF (f);
33
-
34
- return f ;
32
+ if (S) {
33
+ f = convertCtoF (f);
34
+ }
35
+ break ;
35
36
case DHT22:
36
37
case DHT21:
37
38
f = data[2 ] & 0x7F ;
38
39
f *= 256 ;
39
40
f += data[3 ];
40
41
f /= 10 ;
41
- if (data[2 ] & 0x80 )
42
- f *= -1 ;
43
- if (S)
44
- f = convertCtoF (f);
45
-
46
- return f;
42
+ if (data[2 ] & 0x80 ) {
43
+ f *= -1 ;
44
+ }
45
+ if (S) {
46
+ f = convertCtoF (f);
47
+ }
48
+ break ;
47
49
}
48
50
}
49
- return NAN ;
51
+ return f ;
50
52
}
51
53
52
54
float DHT::convertCtoF (float c) {
53
- return c * 9 / 5 + 32 ;
55
+ return c * 9 / 5 + 32 ;
54
56
}
55
57
56
58
float DHT::convertFtoC (float f) {
57
- return (f - 32 ) * 5 / 9 ;
59
+ return (f - 32 ) * 5 / 9 ;
58
60
}
59
61
60
62
float DHT::readHumidity (void ) {
61
- float f;
63
+ float f = NAN ;
62
64
if (read ()) {
63
65
switch (_type) {
64
66
case DHT11:
65
67
f = data[0 ];
66
- return f ;
68
+ break ;
67
69
case DHT22:
68
70
case DHT21:
69
71
f = data[0 ];
70
72
f *= 256 ;
71
73
f += data[1 ];
72
74
f /= 10 ;
73
- return f ;
75
+ break ;
74
76
}
75
77
}
76
- return NAN ;
78
+ return f ;
77
79
}
78
80
79
81
float DHT::computeHeatIndex (float tempFahrenheit, float percentHumidity) {
80
82
// Adapted from equation at: https://github.com/adafruit/DHT-sensor-library/issues/9 and
81
83
// Wikipedia: http://en.wikipedia.org/wiki/Heat_index
82
- return -42.379 +
83
- 2.04901523 * tempFahrenheit +
84
+ return -42.379 +
85
+ 2.04901523 * tempFahrenheit +
84
86
10.14333127 * percentHumidity +
85
87
-0.22475541 * tempFahrenheit*percentHumidity +
86
88
-0.00683783 * pow (tempFahrenheit, 2 ) +
87
- -0.05481717 * pow (percentHumidity, 2 ) +
88
- 0.00122874 * pow (tempFahrenheit, 2 ) * percentHumidity +
89
+ -0.05481717 * pow (percentHumidity, 2 ) +
90
+ 0.00122874 * pow (tempFahrenheit, 2 ) * percentHumidity +
89
91
0.00085282 * tempFahrenheit*pow (percentHumidity, 2 ) +
90
92
-0.00000199 * pow (tempFahrenheit, 2 ) * pow (percentHumidity, 2 );
91
93
}
92
94
93
-
94
95
boolean DHT::read (void ) {
95
- uint8_t laststate = HIGH;
96
- uint8_t counter = 0 ;
97
- uint8_t j = 0 , i;
98
- unsigned long currenttime;
99
-
100
96
// Check if sensor was read less than two seconds ago and return early
101
97
// to use last reading.
102
- currenttime = millis ();
98
+ uint32_t currenttime = millis ();
103
99
if (currenttime < _lastreadtime) {
104
100
// ie there was a rollover
105
101
_lastreadtime = 0 ;
106
102
}
107
- if (!firstreading && ((currenttime - _lastreadtime) < 2000 )) {
108
- return true ; // return last correct measurement
109
- // delay(2000 - (currenttime - _lastreadtime));
103
+ if (!_firstreading && ((currenttime - _lastreadtime) < 2000 )) {
104
+ return _lastresult; // return last correct measurement
110
105
}
111
- firstreading = false ;
112
- /*
113
- Serial.print("Currtime: "); Serial.print(currenttime);
114
- Serial.print(" Lasttime: "); Serial.print(_lastreadtime);
115
- */
106
+ _firstreading = false ;
116
107
_lastreadtime = millis ();
117
108
109
+ // Reset 40 bits of received data to zero.
118
110
data[0 ] = data[1 ] = data[2 ] = data[3 ] = data[4 ] = 0 ;
119
-
120
- // pull the pin high and wait 250 milliseconds
111
+
112
+ // Send start signal. See DHT datasheet for full signal diagram:
113
+ // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
114
+
115
+ // Go into high impedence state to let pull-up raise data line level and
116
+ // start the reading process.
121
117
digitalWrite (_pin, HIGH);
122
118
delay (250 );
123
119
124
- // now pull it low for ~ 20 milliseconds
120
+ // First set data line low for 20 milliseconds.
125
121
pinMode (_pin, OUTPUT);
126
122
digitalWrite (_pin, LOW);
127
123
delay (20 );
124
+
125
+ // Turn off interrupts temporarily because the next sections are timing critical
126
+ // and we don't want any interruptions.
128
127
noInterrupts ();
128
+
129
+ // End the start signal by setting data line high for 40 microseconds.
129
130
digitalWrite (_pin, HIGH);
130
131
delayMicroseconds (40 );
132
+
133
+ // Now start reading the data line to get the value from the DHT sensor.
131
134
pinMode (_pin, INPUT);
135
+ delayMicroseconds (10 ); // Delay a bit to let sensor pull data line low.
136
+
137
+ // First expect a low signal for ~80 microseconds followed by a high signal
138
+ // for ~80 microseconds again.
139
+ if (expectPulse (LOW) == 0 ) {
140
+ DEBUG_PRINTLN (F (" Timeout waiting for start signal low pulse." ));
141
+ _lastresult = false ;
142
+ return _lastresult;
143
+ }
144
+ if (expectPulse (HIGH) == 0 ) {
145
+ DEBUG_PRINTLN (F (" Timeout waiting for start signal high pulse." ));
146
+ _lastresult = false ;
147
+ return _lastresult;
148
+ }
132
149
133
- // read in timings
134
- for ( i=0 ; i< MAXTIMINGS; i++) {
135
- counter = 0 ;
136
- while (digitalRead (_pin) == laststate) {
137
- counter++;
138
- delayMicroseconds (1 );
139
- if (counter == 255 ) {
140
- break ;
141
- }
150
+ // Now read the 40 bits sent by the sensor. Each bit is sent as a 50
151
+ // microsecond low pulse followed by a variable length high pulse. If the
152
+ // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds
153
+ // then it's a 1. We measure the cycle count of the initial 50us low pulse
154
+ // and use that to compare to the cycle count of the high pulse to determine
155
+ // if the bit is a 0 (high state cycle count < low state cycle count), or a
156
+ // 1 (high state cycle count > low state cycle count).
157
+ for (int i=0 ; i<40 ; ++i) {
158
+ uint32_t lowCycles = expectPulse (LOW);
159
+ if (lowCycles == 0 ) {
160
+ DEBUG_PRINTLN (F (" Timeout waiting for bit low pulse." ));
161
+ _lastresult = false ;
162
+ return _lastresult;
142
163
}
143
- laststate = digitalRead (_pin);
144
-
145
- if (counter == 255 ) break ;
146
-
147
- // ignore first 3 transitions
148
- if ((i >= 4 ) && (i%2 == 0 )) {
149
- // shove each bit into the storage bytes
150
- data[j/8 ] <<= 1 ;
151
- if (counter > _count)
152
- data[j/8 ] |= 1 ;
153
- j++;
164
+ uint32_t highCycles = expectPulse (HIGH);
165
+ if (highCycles == 0 ) {
166
+ DEBUG_PRINTLN (F (" Timeout waiting for bit high pulse." ));
167
+ _lastresult = false ;
168
+ return _lastresult;
154
169
}
155
-
170
+ data[i/8 ] <<= 1 ;
171
+ // Now compare the low and high cycle times to see if the bit is a 0 or 1.
172
+ if (highCycles > lowCycles) {
173
+ // High cycles are greater than 50us low cycle count, must be a 1.
174
+ data[i/8 ] |= 1 ;
175
+ }
176
+ // Else high cycles are less than (or equal to, a weird case) the 50us low
177
+ // cycle count so this must be a zero. Nothing needs to be changed in the
178
+ // stored data.
156
179
}
157
180
181
+ // Re-enable interrupts, timing critical code is complete.
158
182
interrupts ();
159
-
160
- /*
161
- Serial.println(j, DEC);
162
- Serial.print(data[0], HEX); Serial.print(", ");
163
- Serial.print(data[1], HEX); Serial.print(", ");
164
- Serial.print(data[2], HEX); Serial.print(", ");
165
- Serial.print(data[3], HEX); Serial.print(", ");
166
- Serial.print(data[4], HEX); Serial.print(" =? ");
167
- Serial.println(data[0] + data[1] + data[2] + data[3], HEX);
168
- */
169
-
170
- // check we read 40 bits and that the checksum matches
171
- if ((j >= 40 ) &&
172
- (data[4 ] == ((data[0 ] + data[1 ] + data[2 ] + data[3 ]) & 0xFF )) ) {
173
- return true ;
174
- }
175
-
176
183
177
- return false ;
184
+ DEBUG_PRINTLN (F (" Received:" ));
185
+ DEBUG_PRINT (data[0 ], HEX); DEBUG_PRINT (F (" , " ));
186
+ DEBUG_PRINT (data[1 ], HEX); DEBUG_PRINT (F (" , " ));
187
+ DEBUG_PRINT (data[2 ], HEX); DEBUG_PRINT (F (" , " ));
188
+ DEBUG_PRINT (data[3 ], HEX); DEBUG_PRINT (F (" , " ));
189
+ DEBUG_PRINT (data[4 ], HEX); DEBUG_PRINT (F (" =? " ));
190
+ DEBUG_PRINTLN (data[0 ] + data[1 ] + data[2 ] + data[3 ], HEX);
191
+
192
+ // Check we read 40 bits and that the checksum matches.
193
+ if (data[4 ] == ((data[0 ] + data[1 ] + data[2 ] + data[3 ]) & 0xFF )) {
194
+ _lastresult = true ;
195
+ return _lastresult;
196
+ }
197
+ else {
198
+ DEBUG_PRINTLN (F (" Checksum failure!" ));
199
+ _lastresult = false ;
200
+ return _lastresult;
201
+ }
202
+ }
178
203
204
+ // Expect the signal line to be at the specified level for a period of time and
205
+ // return a count of loop cycles spent at that level (this cycle count can be
206
+ // used to compare the relative time of two pulses). If more than a millisecond
207
+ // ellapses without the level changing then the call fails with a 0 response.
208
+ uint32_t DHT::expectPulse (bool level) {
209
+ uint32_t count = 0 ;
210
+ uint32_t end = micros () + 1000 ;
211
+ // Loop while counting cycles until the level changes.
212
+ while (digitalRead (_pin) == level) {
213
+ count++;
214
+ if (micros () >= end) {
215
+ // Exceeded timeout waiting for level to change, fail.
216
+ return 0 ;
217
+ }
218
+ }
219
+ return count;
179
220
}
0 commit comments