@@ -10,6 +10,10 @@ DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
10
10
_pin = pin;
11
11
_type = type;
12
12
_firstreading = true ;
13
+ _bit = digitalPinToBitMask (pin);
14
+ _port = digitalPinToPort (pin);
15
+ _maxcycles = microsecondsToClockCycles (1000 ); // 1 millisecond timeout for
16
+ // reading pulses from DHT sensor.
13
17
// Note that count is now ignored as the DHT reading algorithm adjusts itself
14
18
// basd on the speed of the processor.
15
19
}
@@ -19,6 +23,7 @@ void DHT::begin(void) {
19
23
pinMode (_pin, INPUT);
20
24
digitalWrite (_pin, HIGH);
21
25
_lastreadtime = 0 ;
26
+ DEBUG_PRINT (" Max clock cycles: " ); DEBUG_PRINTLN (_maxcycles, DEC);
22
27
}
23
28
24
29
// boolean S == Scale. True == Fahrenheit; False == Celcius
@@ -169,17 +174,24 @@ boolean DHT::read(void) {
169
174
// then it's a 1. We measure the cycle count of the initial 50us low pulse
170
175
// and use that to compare to the cycle count of the high pulse to determine
171
176
// if the bit is a 0 (high state cycle count < low state cycle count), or a
172
- // 1 (high state cycle count > low state cycle count).
177
+ // 1 (high state cycle count > low state cycle count). Note that for speed all
178
+ // the pulses are read into a array and then examined in a later step.
179
+ uint32_t cycles[80 ];
180
+ for (int i=0 ; i<80 ; i+=2 ) {
181
+ cycles[i] = expectPulse (LOW);
182
+ cycles[i+1 ] = expectPulse (HIGH);
183
+ }
184
+
185
+ // Re-enable interrupts, timing critical code is complete.
186
+ interrupts ();
187
+
188
+ // Inspect pulses and determine which ones are 0 (high state cycle count < low
189
+ // state cycle count), or 1 (high state cycle count > low state cycle count).
173
190
for (int i=0 ; i<40 ; ++i) {
174
- uint32_t lowCycles = expectPulse (LOW);
175
- if (lowCycles == 0 ) {
176
- DEBUG_PRINTLN (F (" Timeout waiting for bit low pulse." ));
177
- _lastresult = false ;
178
- return _lastresult;
179
- }
180
- uint32_t highCycles = expectPulse (HIGH);
181
- if (highCycles == 0 ) {
182
- DEBUG_PRINTLN (F (" Timeout waiting for bit high pulse." ));
191
+ uint32_t lowCycles = cycles[2 *i];
192
+ uint32_t highCycles = cycles[2 *i+1 ];
193
+ if ((lowCycles == 0 ) || (highCycles == 0 )) {
194
+ DEBUG_PRINTLN (F (" Timeout waiting for pulse." ));
183
195
_lastresult = false ;
184
196
return _lastresult;
185
197
}
@@ -194,16 +206,13 @@ boolean DHT::read(void) {
194
206
// stored data.
195
207
}
196
208
197
- // Re-enable interrupts, timing critical code is complete.
198
- interrupts ();
199
-
200
209
DEBUG_PRINTLN (F (" Received:" ));
201
210
DEBUG_PRINT (data[0 ], HEX); DEBUG_PRINT (F (" , " ));
202
211
DEBUG_PRINT (data[1 ], HEX); DEBUG_PRINT (F (" , " ));
203
212
DEBUG_PRINT (data[2 ], HEX); DEBUG_PRINT (F (" , " ));
204
213
DEBUG_PRINT (data[3 ], HEX); DEBUG_PRINT (F (" , " ));
205
214
DEBUG_PRINT (data[4 ], HEX); DEBUG_PRINT (F (" =? " ));
206
- DEBUG_PRINTLN (data[0 ] + data[1 ] + data[2 ] + data[3 ], HEX);
215
+ DEBUG_PRINTLN (( data[0 ] + data[1 ] + data[2 ] + data[3 ]) & 0xFF , HEX);
207
216
208
217
// Check we read 40 bits and that the checksum matches.
209
218
if (data[4 ] == ((data[0 ] + data[1 ] + data[2 ] + data[3 ]) & 0xFF )) {
@@ -221,16 +230,29 @@ boolean DHT::read(void) {
221
230
// return a count of loop cycles spent at that level (this cycle count can be
222
231
// used to compare the relative time of two pulses). If more than a millisecond
223
232
// ellapses without the level changing then the call fails with a 0 response.
233
+ // This is adapted from Arduino's pulseInLong function (which is only available
234
+ // in the very latest IDE versions):
235
+ // https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c
224
236
uint32_t DHT::expectPulse (bool level) {
225
237
uint32_t count = 0 ;
226
- uint32_t end = micros () + 1000 ;
227
- // Loop while counting cycles until the level changes.
228
- while (digitalRead (_pin) == level) {
229
- count++;
230
- if (micros () >= end) {
231
- // Exceeded timeout waiting for level to change, fail.
232
- return 0 ;
238
+ // On AVR platforms use direct GPIO port access as it's much faster and better
239
+ // for catching pulses that are 10's of microseconds in length:
240
+ #ifdef __AVR
241
+ uint8_t portState = level ? _bit : 0 ;
242
+ while ((*portInputRegister (_port) & _bit) == portState) {
243
+ if (count++ >= _maxcycles) {
244
+ return 0 ; // Exceeded timeout, fail.
245
+ }
233
246
}
234
- }
247
+ // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266
248
+ // right now, perhaps bugs in direct port access functions?).
249
+ #else
250
+ while (digitalRead (_pin) == level) {
251
+ if (count++ >= _maxcycles) {
252
+ return 0 ; // Exceeded timeout, fail.
253
+ }
254
+ }
255
+ #endif
256
+
235
257
return count;
236
258
}
0 commit comments