diff --git a/DHT.cpp b/DHT.cpp index d32c83f..d979ebe 100644 --- a/DHT.cpp +++ b/DHT.cpp @@ -32,7 +32,6 @@ void DHT::setup(uint8_t pin, DHT_MODEL_t model) { DHT::pin = pin; DHT::model = model; - DHT::resetTimer(); // Make sure we do read the sensor in the next readSensor() if ( model == AUTO_DETECT) { DHT::model = DHT22; @@ -45,23 +44,6 @@ void DHT::setup(uint8_t pin, DHT_MODEL_t model) } } -void DHT::resetTimer() -{ - DHT::lastReadTime = millis() - 3000; -} - -float DHT::getHumidity() -{ - readSensor(); - return humidity; -} - -float DHT::getTemperature() -{ - readSensor(); - return temperature; -} - #ifndef OPTIMIZE_SRAM_SIZE const char* DHT::getStatusString() @@ -110,15 +92,6 @@ const char *DHT::getStatusString() { void DHT::readSensor() { - // Make sure we don't poll the sensor too often - // - Max sample rate DHT11 is 1 Hz (duty cicle 1000 ms) - // - Max sample rate DHT22 is 0.5 Hz (duty cicle 2000 ms) - unsigned long startTime = millis(); - if ( (unsigned long)(startTime - lastReadTime) < (model == DHT11 ? 999L : 1999L) ) { - return; - } - lastReadTime = startTime; - temperature = NAN; humidity = NAN; @@ -134,51 +107,54 @@ void DHT::readSensor() delayMicroseconds(800); } - pinMode(pin, INPUT); - digitalWrite(pin, HIGH); // Switch bus to receive data + pinMode(pin, INPUT_PULLUP); // Switch bus to receive data - // We're going to read 83 edges: - // - First a FALLING, RISING, and FALLING edge for the start bit - // - Then 40 bits: RISING and then a FALLING edge per bit - // To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long + // We're going to read 41 pulses, which each consist of a transition to HIGH + // and then back to LOW again. The first pulse is the start bit and goes for + // ~80us. Then after that, a 26-28us pulse is a 0, and a 70us pulse is a 1. + // + // It's helpful to disable interrupts for the whole duration of capture, since + // at 8 MHz a timer interrupt takes ~10us, long enough to cause a short "0" + // pulse to be missed. However, this will cause millis() and micros() to give + // an inaccurate result. + + noInterrupts(); word rawHumidity; word rawTemperature; word data; - for ( int8_t i = -3 ; i < 2 * 40; i++ ) { - byte age; - startTime = micros(); + unsigned calibration = 0; - do { - age = (unsigned long)(micros() - startTime); - if ( age > 90 ) { - error = ERROR_TIMEOUT; - return; - } - } - while ( digitalRead(pin) == (i & 1) ? HIGH : LOW ); + for ( int8_t i = -1 ; i < 40; i++ ) { + byte width = (byte)pulseIn(pin, HIGH, 150); + + if (width == 0) { + error = ERROR_TIMEOUT; + interrupts(); + return; + } - if ( i >= 0 && (i & 1) ) { + if ( i >= 0 ) { // Now we are being fed our 40 bits data <<= 1; - // A zero max 30 usecs, a one at least 68 usecs. - if ( age > 30 ) { + if ( width > 45 ) { data |= 1; // we got a one } - } - switch ( i ) { - case 31: - rawHumidity = data; - break; - case 63: - rawTemperature = data; - data = 0; - break; + switch ( i ) { + case 15: + rawHumidity = data; + break; + case 31: + rawTemperature = data; + data = 0; + break; + } } } + interrupts(); // Verify checksum diff --git a/DHT.h b/DHT.h index 9e24518..75ff691 100644 --- a/DHT.h +++ b/DHT.h @@ -24,6 +24,13 @@ 2013-06-10: Initial version 2013-06-12: Refactored code 2013-07-01: Add a resetTimer method + 2015-04-25: Remove resetTimer(). Require readSensor() to be called before + getTemperature()/getHumidity() and remove the sampling rate + check, so that we don't need to rely on millis() being accurate. + This means that we can support sleep mode. Improve reliability + on 8MHz devices by disabling interrupts and using pulseIn() + instead of our own busy loop. + ******************************************************************/ #ifndef dht_h @@ -56,10 +63,16 @@ class DHT DHT_ERROR_t; void setup(uint8_t pin, DHT_MODEL_t model=AUTO_DETECT); - void resetTimer(); - float getTemperature(); - float getHumidity(); + void readSensor(); + + float getTemperature() { + return temperature; + } + + float getHumidity() { + return humidity; + } DHT_ERROR_t getStatus() { return error; }; const char* getStatusString(); @@ -80,8 +93,6 @@ class DHT static float toCelsius(float fromFahrenheit) { return (fromFahrenheit - 32.0) / 1.8; }; protected: - void readSensor(); - float temperature; float humidity; @@ -90,7 +101,6 @@ class DHT private: DHT_MODEL_t model; DHT_ERROR_t error; - unsigned long lastReadTime; }; #endif /*dht_h*/ diff --git a/README.md b/README.md index 812f044..a69adb6 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ void loop() { delay(dht.getMinimumSamplingPeriod()); + dht.readSensor(); Serial.print(dht.getHumidity()); Serial.print("\t"); Serial.print(dht.getTemperature());