mysensors/temp_hum_sensor/lib/DHT/DHT.cpp

207 lines
4.6 KiB
C++

/******************************************************************
DHT Temperature & Humidity Sensor library for Arduino.
Features:
- Support for DHT11 and DHT22/AM2302/RHT03
- Auto detect sensor model
- Very low memory footprint
- Very small code
http://www.github.com/markruys/arduino-DHT
Written by Mark Ruys, mark@paracas.nl.
BSD license, check license.txt for more information.
All text above must be included in any redistribution.
Datasheets:
- http://www.micro4you.com/files/sensor/DHT11.pdf
- http://www.adafruit.com/datasheets/DHT22.pdf
- http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/RHT03.pdf
- http://meteobox.tk/files/AM2302.pdf
Changelog:
2013-06-10: Initial version
2013-06-12: Refactored code
2013-07-01: Add a resetTimer method
******************************************************************/
#include "DHT.h"
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;
readSensor();
if ( error == ERROR_TIMEOUT ) {
DHT::model = DHT11;
// Warning: in case we auto detect a DHT11, you should wait at least 1000 msec
// before your first read request. Otherwise you will get a time out error.
}
}
}
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()
{
switch ( error ) {
case DHT::ERROR_TIMEOUT:
return "TIMEOUT";
case DHT::ERROR_CHECKSUM:
return "CHECKSUM";
default:
return "OK";
}
}
#else
// At the expense of 26 bytes of extra PROGMEM, we save 11 bytes of
// SRAM by using the following method:
prog_char P_OK[] PROGMEM = "OK";
prog_char P_TIMEOUT[] PROGMEM = "TIMEOUT";
prog_char P_CHECKSUM[] PROGMEM = "CHECKSUM";
const char *DHT::getStatusString() {
prog_char *c;
switch ( error ) {
case DHT::ERROR_CHECKSUM:
c = P_CHECKSUM; break;
case DHT::ERROR_TIMEOUT:
c = P_TIMEOUT; break;
default:
c = P_OK; break;
}
static char buffer[9];
strcpy_P(buffer, c);
return buffer;
}
#endif
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;
// Request sample
digitalWrite(pin, LOW); // Send start signal
pinMode(pin, OUTPUT);
if ( model == DHT11 ) {
delay(18);
}
else {
// This will fail for a DHT11 - that's how we can detect such a device
delayMicroseconds(800);
}
pinMode(pin, INPUT);
digitalWrite(pin, HIGH); // 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
uint16_t rawHumidity = 0;
uint16_t rawTemperature = 0;
uint16_t data = 0;
for ( int8_t i = -3 ; i < 2 * 40; i++ ) {
byte age;
startTime = micros();
do {
age = (unsigned long)(micros() - startTime);
if ( age > 90 ) {
error = ERROR_TIMEOUT;
return;
}
}
while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );
if ( i >= 0 && (i & 1) ) {
// Now we are being fed our 40 bits
data <<= 1;
// A zero max 30 usecs, a one at least 68 usecs.
if ( age > 30 ) {
data |= 1; // we got a one
}
}
switch ( i ) {
case 31:
rawHumidity = data;
break;
case 63:
rawTemperature = data;
data = 0;
break;
}
}
// Verify checksum
if ( (byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data ) {
error = ERROR_CHECKSUM;
return;
}
// Store readings
if ( model == DHT11 ) {
humidity = rawHumidity >> 8;
temperature = rawTemperature >> 8;
}
else {
humidity = rawHumidity * 0.1;
if ( rawTemperature & 0x8000 ) {
rawTemperature = -(int16_t)(rawTemperature & 0x7FFF);
}
temperature = ((int16_t)rawTemperature) * 0.1;
}
error = ERROR_NONE;
}