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;
  }
}
Esempio n. 2
0
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);
    }
}