#include "dht11.h"
/*!
* @brief Instantiates a new DHT class
* @param pin
* pin number that sensor is connected
*/
DHT11::DHT11(uint8_t pin)
{
_pin = pin;
pinMode(_pin, INPUT_PULLUP);
}
/*!
* @brief Reset the specific buffer
* @param buf
* buffer that you want to reset
* @param size
* how many bytes you want to reset
*/
void DHT11::resetBuffer(uint8_t *buf, uint8_t size)
{
for (int i=0; i<size; i++) {
buf[i] = 0;
}
}
/*!
* @brief Read value from sensor and update data array.
* @param usec
* Optionally pass pull-up time (in microseconds) before DHT reading
* starts. Default is 55 (see function declaration in dht.h).
* @return If read data successfully return DHTLIB_OK,
* if the data are not complete return DHTLIB_ERROR_CHECKSUM,
* if read timeout return DHTLIB_ERROR_TIMEOUT.
*/
uint8_t DHT11::read(uint8_t usec)
{
uint8_t bit = 7, index = 0;
uint32_t t1 = 0, t2 = 0, delta = 0;
// Reset data buffer
resetBuffer(data, sizeof(data)/sizeof(data[0]));
// MCU request sampling
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(BEGIN_TIME);
digitalWrite(_pin, HIGH);
delayMicroseconds(GO_TIME);
pinMode(_pin, INPUT);
// Waiting for DHT11 sensor reply
// ACKNOWLEDGE or TIMEOUT
unsigned int loopCnt = 10000;
while(digitalRead(_pin) == LOW)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
loopCnt = 10000;
while(digitalRead(_pin) == HIGH)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
// READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
for (int i=0; i<40; i++)
{
loopCnt = 10000;
while(digitalRead(_pin) == LOW)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
t1 = micros();
loopCnt = 10000;
while(digitalRead(_pin) == HIGH)
if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;
t2 = micros();
if(t2 < t1) delta = UINT32_MAX - t1 + t2;
else delta = t2 - t1;
if(delta > THINK_TIME) {
data[index] |= (1 << bit);
}
// Next byte or not
if (bit == 0) {
bit = 7;
index++;
}
else bit--;
}
if (data[4] != checksum()) {
return DHTLIB_ERROR_CHECKSUM;
}
return DHTLIB_OK;
}
/*!
* @brief Calculate checksum
* @return The last 8 bit of checksum value
*/
uint8_t DHT11::checksum()
{
uint16_t sum = 0;
for(int i=0; i<sizeof(data)/sizeof(data[0]); i++) {
sum += data[i];
}
return (uint8_t)sum;
}
/*!
* @brief Read Humidity
* @return float value - humidity in percent
*/
float DHT11::getHumidity()
{
float f = data[0] + data[1] * 0.1;
return f;
}
/*!
* @brief Get temperature
* @param isFahrenheit
* If or not scale in Fahrenheit (default in Celcius)
* @return Temperature value in selected scale
*/
float DHT11::getTemperature(bool isFahrenheit)
{
float f = data[2];
if (data[3] & 0x80) {
f = -1 - f;
}
f += (data[3] & 0x0f) * 0.1;
if (isFahrenheit) {
f = convertCtoF(f);
}
return f;
}
/*!
* @brief Converts Celcius to Fahrenheit
* @param c
* value in Celcius
* @return float value in Fahrenheit
*/
float DHT11::convertCtoF(float c)
{
return c * 1.8 + 32;
}
/*!
* @brief Converts Fahrenheit to Celcius
* @param f
* value in Fahrenheit
* @return float value in Celcius
*/
float DHT11::convertFtoC(float f)
{
return (f - 32) * 0.55555;
}
/*!
* @brief Converts Celcius to Kelvin
* @param c
* value in Celcius
* @return float value in Kelvin
*/
float DHT11::convertCtoK(float c)
{
return c + 273.15;
}
/*!
* @brief Calculate the dew point
* @param celsius
* temperature value in Celcius
* @param humidity
* humidity value in percent
*/
double DHT11::dewPoint(double celsius, double humidity)
{
double A0= 373.15/(273.15 + celsius);
double SUM = -7.90298 * (A0-1);
SUM += 5.02808 * log10(A0);
SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1);
SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1);
SUM += log10(1013.246);
double VP = pow(10, SUM-3) * humidity;
double T = log(VP/0.61078); // temp var
return (241.88 * T) / (17.558-T);
}
/*!
* @brief Calculate the dew point fast
* @param celsius
* temperature value in Celcius
* @param humidity
* humidity value in percent
*/
double DHT11::dewPointFast(double celsius, double humidity)
{
double a = 17.271;
double b = 237.7;
double temp = (a * celsius) / (b + celsius) + log(humidity/100);
double Td = (b * temp) / (a - temp);
return Td;
}
/*!
* @brief Compute Heat Index
* Using both Rothfusz and Steadman's equations
* (http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml)
* @param temperature
* temperature in selected scale
* @param percentHumidity
* humidity in percent
* @param isFahrenheit
* true if fahrenheit, false if celcius
* @return float heat index
*/
float DHT11::computeHeatIndex(float temperature, float percentHumidity,
bool isFahrenheit) {
float hi;
if (!isFahrenheit)
temperature = convertCtoF(temperature);
hi = 0.5 * (temperature + 61.0 + ((temperature - 68.0) * 1.2) +
(percentHumidity * 0.094));
if (hi > 79) {
hi = -42.379 + 2.04901523 * temperature + 10.14333127 * percentHumidity +
-0.22475541 * temperature * percentHumidity +
-0.00683783 * pow(temperature, 2) +
-0.05481717 * pow(percentHumidity, 2) +
0.00122874 * pow(temperature, 2) * percentHumidity +
0.00085282 * temperature * pow(percentHumidity, 2) +
-0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2);
if ((percentHumidity < 13) && (temperature >= 80.0) &&
(temperature <= 112.0))
hi -= ((13.0 - percentHumidity) * 0.25) *
sqrt((17.0 - abs(temperature - 95.0)) * 0.05882);
else if ((percentHumidity > 85.0) && (temperature >= 80.0) &&
(temperature <= 87.0))
hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2);
}
return isFahrenheit ? hi : convertFtoC(hi);
}