boolean DHT::read(bool force) { // Check if sensor was read less than two seconds ago and return early // to use last reading. uint32_t currenttime = millis(); if (!force && ((currenttime - _lastreadtime) < 2000)) { return _lastresult; // return last correct measurement } _lastreadtime = currenttime; // Reset 40 bits of received data to zero. data[0] = data[1] = data[2] = data[3] = data[4] = 0; // Send start signal. See DHT datasheet for full signal diagram: // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf // Go into high impedence state to let pull-up raise data line level and // start the reading process. digitalWrite(_pin, HIGH); delay(250); // First set data line low for 20 milliseconds. pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); delay(20); uint32_t cycles[80]; { // Turn off interrupts temporarily because the next sections are timing critical // and we don't want any interruptions. InterruptLock lock; // End the start signal by setting data line high for 40 microseconds. digitalWrite(_pin, HIGH); delayMicroseconds(40); // Now start reading the data line to get the value from the DHT sensor. pinMode(_pin, INPUT_PULLUP); delayMicroseconds(10); // Delay a bit to let sensor pull data line low. // First expect a low signal for ~80 microseconds followed by a high signal // for ~80 microseconds again. if (expectPulse(LOW) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); _lastresult = false; return _lastresult; } if (expectPulse(HIGH) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); _lastresult = false; return _lastresult; } // Now read the 40 bits sent by the sensor. Each bit is sent as a 50 // microsecond low pulse followed by a variable length high pulse. If the // high pulse is ~28 microseconds then it's a 0 and if it's ~70 microseconds // then it's a 1. We measure the cycle count of the initial 50us low pulse // and use that to compare to the cycle count of the high pulse to determine // if the bit is a 0 (high state cycle count < low state cycle count), or a // 1 (high state cycle count > low state cycle count). Note that for speed all // the pulses are read into a array and then examined in a later step. for (int i=0; i<80; i+=2) { cycles[i] = expectPulse(LOW); cycles[i+1] = expectPulse(HIGH); } } // Timing critical code is now complete. // Inspect pulses and determine which ones are 0 (high state cycle count < low // state cycle count), or 1 (high state cycle count > low state cycle count). for (int i=0; i<40; ++i) { uint32_t lowCycles = cycles[2*i]; uint32_t highCycles = cycles[2*i+1]; if ((lowCycles == 0) || (highCycles == 0)) { DEBUG_PRINTLN(F("Timeout waiting for pulse.")); _lastresult = false; return _lastresult; } data[i/8] <<= 1; // Now compare the low and high cycle times to see if the bit is a 0 or 1. if (highCycles > lowCycles) { // High cycles are greater than 50us low cycle count, must be a 1. data[i/8] |= 1; } // Else high cycles are less than (or equal to, a weird case) the 50us low // cycle count so this must be a zero. Nothing needs to be changed in the // stored data. } DEBUG_PRINTLN(F("Received:")); DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); // Check we read 40 bits and that the checksum matches. if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { _lastresult = true; return _lastresult; } else { DEBUG_PRINTLN(F("Checksum failure!")); _lastresult = false; return _lastresult; } }
bool DHT::read(bool force) { /* * Check if the sensor was read less than a second ago and return early * to use the last reading taken. */ uint32_t currentTime = millis(); if (!force && ((currentTime - _lastReadTime) < DHT_MIN_INTERVAL)) { return _lastResult; } _lastReadTime = currentTime; /* Reset 40 bits of received data to zero */ data[0] = data[1] = data[2] = data[3] = data[4] = 0; /* * Go into high impedence state to let pull-up raise data line level and * start the reading process. */ digitalWrite(_pin, HIGH); delay(250); /* First set the data line low for 20 ms */ pinMode(_pin, OUTPUT); digitalWrite(_pin, LOW); delay(20); uint32_t cycles[80]; /* * * * * * * * * * * Timing-critical code * * * * * * * * * * */ { /* * Turn off interrupts temporarily because the next sections are * timing-critical and we do not want any interruptions. */ InterruptLock lock; /* End the start signal by setting the data line high for 40ms */ digitalWrite(_pin, HIGH); delayMicroseconds(40); /* * Now start reading the data line to get the value from the DHT * sensor. */ pinMode(_pin, INPUT_PULLUP); delayMicroseconds(10); // Delay a bit to let the sensor pull the data line low /* * First, expect a low signal for ~80 ms followed by a high signal for * ~80 ms. */ if (expectPulse(LOW) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal low pulse.")); _lastResult = false; return (_lastResult); } if (expectPulse(HIGH) == 0) { DEBUG_PRINTLN(F("Timeout waiting for start signal high pulse.")); _lastResult = false; return (_lastResult); } /* * Now read the 40 bits sent by the sensor. Each bit is sent as a * 50 ms low pulse followed by a variable length high pulse. If the * high pulse is ~28 ms then it is a 0 and if it is ~70 ms then it is * a 1. We measure the cycle count of the initial 50us low pulse and * use that to compare to the cycle count of the high pulse to * determine if the bit is a 0 (high state cycle count < low state * cycle count), or a 1 (high state cycle count > low state cycle * count). Note that for speed all the pulses are read into a array and * then examined in a later step. */ for (int i = 0; i < 80; i += 2) { cycles[i] = expectPulse(LOW); cycles[i + 1] = expectPulse(HIGH); } } /* * Inspect pulses and determine which ones are 0 (high state cycle count < * low state cycle count), or 1 (high state cycle count > low state cycle * count). */ for (int i = 0; i < 40; ++i) { uint32_t lowCycles = cycles[2 * i]; uint32_t highCycles = cycles[2 * i + 1]; if ((lowCycles == 0) || (highCycles == 0)) { DEBUG_PRINTLN(F("Timeout waiting for pulse.")); _lastResult = false; return (_lastResult); } data[i / 8] <<= 1; /* * Now compare the low and high cycle times to see if the bit is a 0 or * 1. */ if (highCycles > lowCycles) { /* High cycles are greater than 50us low cycle count, must be a 1. */ data[i / 8] |= 1; } /* * Else high cycles are less than (or equal to, a weird case) the 50us * low cycle count so this must be a zero. Nothing needs to be changed * in the stored data. */ } DEBUG_PRINTLN(F("Received:")); DEBUG_PRINT(data[0], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[1], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[2], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[3], HEX); DEBUG_PRINT(F(", ")); DEBUG_PRINT(data[4], HEX); DEBUG_PRINT(F(" =? ")); DEBUG_PRINTLN((data[0] + data[1] + data[2] + data[3]) & 0xFF, HEX); // Check we read 40 bits and that the checksum matches. if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { _lastResult = true; return (_lastResult); } else { DEBUG_PRINTLN(F("Checksum failure!")); _lastResult = false; return (_lastResult); } }