GY-63_MS5611/libraries/DHTNEW/dhtnew.cpp

428 lines
9.3 KiB
C++
Raw Normal View History

//
// FILE: dhtnew.cpp
// AUTHOR: Rob.Tillaart@gmail.com
2023-01-09 10:55:27 -05:00
// VERSION: 0.4.18
2020-05-22 03:20:39 -04:00
// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
// URL: https://github.com/RobTillaart/DHTNEW
//
2022-10-15 13:50:48 -04:00
// HISTORY: see changelog.md
2021-12-16 11:24:05 -05:00
#include "dhtnew.h"
2021-01-29 06:31:58 -05:00
#include <stdint.h>
2022-10-15 13:50:48 -04:00
// these defines are not for user to adjust (microseconds)
#define DHTLIB_DHT11_WAKEUP (18 * 1100UL)
#define DHTLIB_DHT_WAKEUP (1 * 1100UL)
// experimental 0.4.14
#define DHTLIB_SI7021_WAKEUP (500)
2020-05-22 03:20:39 -04:00
2021-01-29 06:31:58 -05:00
2022-10-16 09:10:29 -04:00
// READ_DELAY for blocking read
// datasheet: DHT11 = 1000 and DHT22 = 2000
// use setReadDelay() to overrule (at own risk)
// as individual sensors can be read faster.
// see example DHTnew_setReadDelay.ino
2020-11-27 05:10:47 -05:00
#define DHTLIB_DHT11_READ_DELAY 1000
#define DHTLIB_DHT22_READ_DELAY 2000
2020-05-22 03:20:39 -04:00
2021-01-29 06:31:58 -05:00
/////////////////////////////////////////////////////
//
2022-10-15 13:50:48 -04:00
// PUBLIC
//
2020-11-27 05:10:47 -05:00
DHTNEW::DHTNEW(uint8_t pin)
{
_dataPin = pin;
2021-01-29 06:31:58 -05:00
reset();
};
void DHTNEW::reset()
{
2022-10-16 09:10:29 -04:00
// Data-bus's free status is high voltage level.
2020-11-27 05:10:47 -05:00
pinMode(_dataPin, OUTPUT);
digitalWrite(_dataPin, HIGH);
2021-01-29 06:31:58 -05:00
_wakeupDelay = 0;
_type = 0;
2022-11-05 14:57:52 -04:00
_humOffset = (float)0.0;
_tempOffset = (float)0.0;
_humidity = (float)0.0;
_temperature = (float)0.0;
2021-01-29 06:31:58 -05:00
_lastRead = 0;
_disableIRQ = true;
_waitForRead = false;
_suppressError = false;
_readDelay = 0;
#if defined(__AVR__)
2021-11-18 03:48:40 -05:00
_disableIRQ = false;
2021-01-29 06:31:58 -05:00
#endif
2023-01-09 10:55:27 -05:00
// #if defined(ARDUINO_SAMD_MKRWIFI1010) // fix for issue #67
2021-11-18 03:48:40 -05:00
// _disableIRQ = false;
// #endif
2021-01-29 06:31:58 -05:00
}
2020-11-27 05:10:47 -05:00
uint8_t DHTNEW::getType()
{
if (_type == 0) read();
return _type;
}
2021-01-29 06:31:58 -05:00
2020-11-27 05:10:47 -05:00
void DHTNEW::setType(uint8_t type)
{
if ((type == 0) || (type == 11))
{
_type = type;
_wakeupDelay = DHTLIB_DHT11_WAKEUP;
}
2023-01-09 10:55:27 -05:00
if ((type == 22) || (type == 23))
2020-11-27 05:10:47 -05:00
{
_type = type;
_wakeupDelay = DHTLIB_DHT_WAKEUP;
}
2022-10-15 13:50:48 -04:00
// experimental 0.4.14
if (type == 70)
{
_type = type;
_wakeupDelay = DHTLIB_SI7021_WAKEUP;
}
2020-11-27 05:10:47 -05:00
}
2021-01-29 06:31:58 -05:00
2022-10-16 09:10:29 -04:00
// return values:
// DHTLIB_OK
// DHTLIB_WAITING_FOR_READ
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_BIT_SHIFT
// DHTLIB_ERROR_SENSOR_NOT_READY
// DHTLIB_ERROR_TIMEOUT_A
// DHTLIB_ERROR_TIMEOUT_B
// DHTLIB_ERROR_TIMEOUT_C
// DHTLIB_ERROR_TIMEOUT_D
int DHTNEW::read()
{
2020-11-27 05:10:47 -05:00
if (_readDelay == 0)
{
_readDelay = DHTLIB_DHT22_READ_DELAY;
if (_type == 11) _readDelay = DHTLIB_DHT11_READ_DELAY;
}
2020-05-22 03:20:39 -04:00
if (_type != 0)
{
2020-11-27 05:10:47 -05:00
while (millis() - _lastRead < _readDelay)
{
if (!_waitForRead) return DHTLIB_WAITING_FOR_READ;
yield();
}
2020-05-22 03:20:39 -04:00
return _read();
}
2022-10-15 13:50:48 -04:00
// AUTODETECT
2022-10-16 09:10:29 -04:00
// make sure sensor had time to wake up.
while (millis() < 1000);
2022-10-15 13:50:48 -04:00
2023-01-09 10:55:27 -05:00
// NOTE: cannot differentiate between type 23 and 22
_type = 22;
_wakeupDelay = DHTLIB_DHT_WAKEUP;
int rv = _read();
if (rv == DHTLIB_OK) return rv;
_type = 11;
_wakeupDelay = DHTLIB_DHT11_WAKEUP;
rv = _read();
if (rv == DHTLIB_OK) return rv;
2022-10-15 13:50:48 -04:00
// experimental 0.4.14
_type = 70;
_wakeupDelay = DHTLIB_SI7021_WAKEUP;
rv = _read();
if (rv == DHTLIB_OK) return rv;
_type = 0; // retry next time
return rv;
}
2021-01-29 06:31:58 -05:00
2022-10-16 09:10:29 -04:00
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_BIT_SHIFT
// DHTLIB_ERROR_SENSOR_NOT_READY
// DHTLIB_ERROR_TIMEOUT_A
// DHTLIB_ERROR_TIMEOUT_B
// DHTLIB_ERROR_TIMEOUT_C
// DHTLIB_ERROR_TIMEOUT_D
int DHTNEW::_read()
{
2022-10-16 09:10:29 -04:00
// READ VALUES
int rv = _readSensor();
2020-11-27 05:10:47 -05:00
2022-10-16 09:10:29 -04:00
// enable interrupts again
2022-07-07 06:14:35 -04:00
#if defined(ESP32)
portENABLE_INTERRUPTS();
#else
interrupts();
#endif
2022-10-16 09:10:29 -04:00
// Data-bus's free status is high voltage level.
2020-11-27 05:10:47 -05:00
pinMode(_dataPin, OUTPUT);
digitalWrite(_dataPin, HIGH);
_lastRead = millis();
if (rv != DHTLIB_OK)
{
2020-11-27 05:10:47 -05:00
if (_suppressError == false)
{
_humidity = DHTLIB_INVALID_VALUE;
_temperature = DHTLIB_INVALID_VALUE;
}
2022-10-16 09:10:29 -04:00
return rv; // propagate error value
}
2022-10-22 04:59:47 -04:00
if (_type == 11) // DHT11, DH12, compatible
{
_humidity = _bits[0] + _bits[1] * 0.1;
_temperature = _bits[2] + _bits[3] * 0.1;
}
else // DHT22, DHT33, DHT44, compatible + Si7021
{
2021-04-25 13:56:44 -04:00
_humidity = (_bits[0] * 256 + _bits[1]) * 0.1;
int16_t t = ((_bits[2] & 0x7F) * 256 + _bits[3]);
if (t == 0)
{
2022-11-05 14:57:52 -04:00
_temperature = (float)0.0; // prevent -0.0;
2021-04-25 13:56:44 -04:00
}
2021-03-01 04:11:54 -05:00
else
2021-04-25 13:56:44 -04:00
{
_temperature = t * 0.1;
if((_bits[2] & 0x80) == 0x80 )
{
_temperature = -_temperature;
}
}
}
2022-10-22 04:59:47 -04:00
2021-01-29 06:31:58 -05:00
// HEXDUMP DEBUG
/*
Serial.println();
// CHECKSUM
if (_bits[4] < 0x10) Serial.print(0);
Serial.print(_bits[4], HEX);
Serial.print(" ");
// TEMPERATURE
if (_bits[2] < 0x10) Serial.print(0);
Serial.print(_bits[2], HEX);
if (_bits[3] < 0x10) Serial.print(0);
Serial.print(_bits[3], HEX);
Serial.print(" ");
Serial.print(_temperature, 1);
Serial.print(" ");
// HUMIDITY
if (_bits[0] < 0x10) Serial.print(0);
Serial.print(_bits[0], HEX);
if (_bits[1] < 0x10) Serial.print(0);
Serial.print(_bits[1], HEX);
Serial.print(" ");
Serial.print(_humidity, 1);
*/
2022-10-16 09:10:29 -04:00
// TEST OUT OF RANGE
2021-06-13 06:56:40 -04:00
#ifdef DHTLIB_VALUE_OUT_OF_RANGE
if (_humidity > 100)
{
return DHTLIB_HUMIDITY_OUT_OF_RANGE;
}
if ((_temperature < -40) || (_temperature > 80))
{
return DHTLIB_TEMPERATURE_OUT_OF_RANGE;
}
#endif
2022-11-05 14:57:52 -04:00
if (_humOffset != (float)0.0)
2021-11-18 03:48:40 -05:00
{
_humidity += _humOffset;
if (_humidity < 0) _humidity = 0;
if (_humidity > 100) _humidity = 100;
}
2022-11-05 14:57:52 -04:00
if (_tempOffset != (float)0.0)
2021-11-18 03:48:40 -05:00
{
_temperature += _tempOffset;
}
2022-10-16 09:10:29 -04:00
// TEST CHECKSUM
uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3];
if (_bits[4] != sum)
{
return DHTLIB_ERROR_CHECKSUM;
}
2021-06-13 06:56:40 -04:00
return DHTLIB_OK;
}
2021-01-29 06:31:58 -05:00
2020-11-27 05:10:47 -05:00
void DHTNEW::powerUp()
{
digitalWrite(_dataPin, HIGH);
2022-10-16 09:10:29 -04:00
// do a dummy read to sync the sensor
2020-11-27 05:10:47 -05:00
read();
};
2021-01-29 06:31:58 -05:00
2020-11-27 05:10:47 -05:00
void DHTNEW::powerDown()
{
digitalWrite(_dataPin, LOW);
}
/////////////////////////////////////////////////////
//
2022-10-16 09:10:29 -04:00
// PRIVATE
//
2022-10-16 09:10:29 -04:00
// return values:
// DHTLIB_OK
// DHTLIB_ERROR_CHECKSUM
// DHTLIB_ERROR_BIT_SHIFT
// DHTLIB_ERROR_SENSOR_NOT_READY
// DHTLIB_ERROR_TIMEOUT_A
// DHTLIB_ERROR_TIMEOUT_B
// DHTLIB_ERROR_TIMEOUT_C
// DHTLIB_ERROR_TIMEOUT_D
int DHTNEW::_readSensor()
{
2022-10-16 09:10:29 -04:00
// INIT BUFFERVAR TO RECEIVE DATA
2020-11-27 05:10:47 -05:00
uint8_t mask = 0x80;
uint8_t idx = 0;
2022-10-16 09:10:29 -04:00
// EMPTY BUFFER
for (uint8_t i = 0; i < 5; i++) _bits[i] = 0;
2022-10-16 09:10:29 -04:00
// REQUEST SAMPLE - SEND WAKEUP TO SENSOR
2020-11-27 05:10:47 -05:00
pinMode(_dataPin, OUTPUT);
digitalWrite(_dataPin, LOW);
2022-01-31 11:46:37 -05:00
2022-10-15 13:50:48 -04:00
// HANDLE SI7021 separately (see #79)
if (_type == 70)
2022-01-31 11:46:37 -05:00
{
2022-10-15 13:50:48 -04:00
delayMicroseconds(DHTLIB_SI7021_WAKEUP); // hardcoded for now
}
else
{
// WAKE UP - add 10% extra for timing inaccuracies in sensor.
uint32_t startWakeup = micros();
do
{
// HANDLE PENDING IRQ
yield();
// 180 gives good wakeup delay on UNO for DHT22 / DHT11 (issue #72)
delayMicroseconds(180UL);
}
while((micros() - startWakeup) < _wakeupDelay);
2022-01-31 11:46:37 -05:00
}
2022-10-16 09:10:29 -04:00
// HOST GIVES CONTROL TO SENSOR
2020-11-27 05:10:47 -05:00
digitalWrite(_dataPin, HIGH);
delayMicroseconds(2);
pinMode(_dataPin, INPUT_PULLUP);
2022-10-16 09:10:29 -04:00
// DISABLE INTERRUPTS when clock in the bits
2022-07-07 06:14:35 -04:00
if (_disableIRQ)
{
2022-10-15 13:50:48 -04:00
#if defined(ESP32)
2022-07-07 06:14:35 -04:00
portDISABLE_INTERRUPTS();
#else
noInterrupts();
#endif
}
2020-11-27 05:10:47 -05:00
2022-10-16 09:10:29 -04:00
// DHT22 (and others including Si7021)
// SENSOR PULLS LOW after 20-40 us => if stays HIGH ==> device not ready
// timeout is 20 us less due to delay() above
// DHT11
// SENSOR PULLS LOW after 6000-10000 us
2020-11-27 05:10:47 -05:00
uint32_t WAITFORSENSOR = 50;
if (_type == 11) WAITFORSENSOR = 15000UL;
if (_waitFor(LOW, WAITFORSENSOR)) return DHTLIB_ERROR_SENSOR_NOT_READY;
2022-10-16 09:10:29 -04:00
// SENSOR STAYS LOW for ~80 us => or TIMEOUT
2020-11-27 05:10:47 -05:00
if (_waitFor(HIGH, 90)) return DHTLIB_ERROR_TIMEOUT_A;
2022-10-16 09:10:29 -04:00
// SENSOR STAYS HIGH for ~80 us => or TIMEOUT
2020-11-27 05:10:47 -05:00
if (_waitFor(LOW, 90)) return DHTLIB_ERROR_TIMEOUT_B;
2022-10-16 09:10:29 -04:00
// SENSOR HAS NOW SEND ACKNOWLEDGE ON WAKEUP
// NOW IT SENDS THE BITS
2022-10-16 09:10:29 -04:00
// READ THE OUTPUT - 40 BITS => 5 BYTES
for (uint8_t i = 40; i != 0; i--)
{
2022-10-16 09:10:29 -04:00
// EACH BIT START WITH ~50 us LOW
2022-10-15 13:50:48 -04:00
if (_waitFor(HIGH, 90))
2021-11-18 03:48:40 -05:00
{
2022-10-16 09:10:29 -04:00
// Most critical timeout
// Serial.print("IC: ");
// Serial.println(i);
2021-11-18 03:48:40 -05:00
return DHTLIB_ERROR_TIMEOUT_C;
}
2022-10-16 09:10:29 -04:00
// DURATION OF HIGH DETERMINES 0 or 1
// 26-28 us ==> 0
// 70 us ==> 1
uint32_t t = micros();
2021-11-18 03:48:40 -05:00
if (_waitFor(LOW, 90))
{
2022-10-16 09:10:29 -04:00
// Serial.print("ID: ");
// Serial.println(i);
2021-11-18 03:48:40 -05:00
return DHTLIB_ERROR_TIMEOUT_D;
}
2020-11-27 05:10:47 -05:00
if ((micros() - t) > DHTLIB_BIT_THRESHOLD)
{
_bits[idx] |= mask;
}
2020-11-27 05:10:47 -05:00
2022-10-16 09:10:29 -04:00
// PREPARE FOR NEXT BIT
mask >>= 1;
if (mask == 0) // next byte?
{
2020-05-22 03:20:39 -04:00
mask = 0x80;
idx++;
}
}
2022-10-16 09:10:29 -04:00
// After 40 bits the sensor pulls the line LOW for 50 us
// No functional need to wait for this one
// if (_waitFor(HIGH, 60)) return DHTLIB_ERROR_TIMEOUT_E;
2020-11-27 05:10:47 -05:00
2022-10-16 09:10:29 -04:00
// CATCH RIGHTSHIFT BUG ESP (only 1 single bit shift)
// humidity is maximum 1000 = 0x03E8 for DHT22 and 0x6400 for DHT11
// so most significant bit may never be set.
2020-11-27 05:10:47 -05:00
if (_bits[0] & 0x80) return DHTLIB_ERROR_BIT_SHIFT;
return DHTLIB_OK;
}
2020-05-22 03:20:39 -04:00
2020-11-27 05:10:47 -05:00
2022-10-16 09:10:29 -04:00
// returns true if timeout has passed.
// returns false if timeout is not reached and state is seen.
2020-11-27 05:10:47 -05:00
bool DHTNEW::_waitFor(uint8_t state, uint32_t timeout)
{
uint32_t start = micros();
uint8_t count = 2;
while ((micros() - start) < timeout)
{
2022-10-16 09:10:29 -04:00
// d elayMicroseconds(1); // less # reads ==> minimizes # glitch reads
2020-11-27 05:10:47 -05:00
if (digitalRead(_dataPin) == state)
{
count--;
2022-10-16 09:10:29 -04:00
if (count == 0) return false; // requested state seen count times
2020-11-27 05:10:47 -05:00
}
}
return true;
}
2021-11-18 03:48:40 -05:00
2020-05-22 03:20:39 -04:00
// -- END OF FILE --
2021-11-18 03:48:40 -05:00