|
|
- // -----------------------------------------------------------------------------
- // DHT Sensor
- // -----------------------------------------------------------------------------
-
- #pragma once
-
- #include "Arduino.h"
- #include "BaseSensor.h"
-
- #define DHT_MAX_DATA 5
- #define DHT_MAX_ERRORS 5
- #define DHT_MIN_INTERVAL 2000
- #define DHT_OK 0
- #define DHT_CHECKSUM_ERROR -1
- #define DHT_TIMEOUT_ERROR -2
-
- #define DHT11 11
- #define DHT22 22
- #define DHT21 21
- #define AM2301 21
-
- class DHTSensor : public BaseSensor {
-
- public:
-
- DHTSensor(unsigned char gpio, unsigned char type): BaseSensor() {
- _gpio = gpio;
- _type = type;
- }
-
- // Pre-read hook (usually to populate registers with up-to-date data)
- void pre() {
-
- if ((_last_ok > 0) && (millis() - _last_ok < DHT_MIN_INTERVAL)) {
- _error = 0;
- return;
- }
-
- unsigned long low = 0;
- unsigned long high = 0;
-
- unsigned char dhtData[DHT_MAX_DATA] = {0};
- unsigned char byteInx = 0;
- unsigned char bitInx = 7;
-
- // Send start signal to DHT sensor
- if (++_errors > DHT_MAX_ERRORS) {
- _errors = 0;
- digitalWrite(_gpio, HIGH);
- delay(250);
- }
- pinMode(_gpio, OUTPUT);
- noInterrupts();
- digitalWrite(_gpio, LOW);
- delayMicroseconds(500);
- digitalWrite(_gpio, HIGH);
- delayMicroseconds(40);
- pinMode(_gpio, INPUT_PULLUP);
-
- // No errors, read the 40 data bits
- for( int k = 0; k < 41; k++ ) {
-
- // Starts new data transmission with >50us low signal
- low = _signal(56, LOW);
- if (low == 0) {
- _error = DHT_TIMEOUT_ERROR;
- return;
- }
-
- // Check to see if after >70us rx data is a 0 or a 1
- high = _signal(75, HIGH);
- if (high == 0) {
- _error = DHT_TIMEOUT_ERROR;
- return;
- }
-
- // Skip the first bit
- if (k == 0) continue;
-
- // add the current read to the output data
- // since all dhtData array where set to 0 at the start,
- // only look for "1" (>28us us)
- if (high > low) dhtData[byteInx] |= (1 << bitInx);
-
- // index to next byte
- if (bitInx == 0) {
- bitInx = 7;
- ++byteInx;
- } else {
- --bitInx;
- }
-
- }
-
- interrupts();
-
- // Verify checksum
- if (dhtData[4] != ((dhtData[0] + dhtData[1] + dhtData[2] + dhtData[3]) & 0xFF)) {
- _error = DHT_CHECKSUM_ERROR;
- return;
- }
-
- // Get humidity from Data[0] and Data[1]
- if (_type == DHT11) {
- _humidity = dhtData[0];
- } else {
- _humidity = dhtData[0] * 256 + dhtData[1];
- _humidity /= 10;
- }
-
- // Get temp from Data[2] and Data[3]
- if (_type == DHT11) {
- _temperature = dhtData[2];
- } else {
- _temperature = (dhtData[2] & 0x7F) * 256 + dhtData[3];
- _temperature /= 10;
- if (dhtData[2] & 0x80) _temperature *= -1;
- }
-
- _last_ok = millis();
- _errors = 0;
- _error = 0;
-
- }
-
- // Post-read hook (usually to reset things)
- void post() {
-
- }
-
- // Return sensor status (true for ready)
- bool status() {
- return (_last_ok > 0) & (_error == 0);
- }
-
- // Return sensor last internal error
- int error() {
- return _error;
- }
-
- // Number of available slots
- unsigned char count() {
- return 2;
- }
-
- // Descriptive name of the sensor
- String name() {
- char buffer[64];
- snprintf(buffer, sizeof(buffer), "DHT%d @ GPIO%d", _type, _gpio);
- return String(buffer);
- }
-
- // Descriptive name of the slot # index
- String slot(unsigned char index) {
- return name();
- }
-
- // Type for slot # index
- magnitude_t type(unsigned char index) {
- if (index == 0) return MAGNITUDE_TEMPERATURE;
- if (index == 1) return MAGNITUDE_HUMIDITY;
- return MAGNITUDE_NONE;
- }
-
- // Current value for slot # index
- double value(unsigned char index) {
- if (index == 0) return _temperature;
- if (index == 1) return _humidity;
- return 0;
- }
-
-
- private:
-
- unsigned long _signal(int usTimeOut, bool state) {
- unsigned long uSec = 1;
- while (digitalRead(_gpio) == state) {
- if (++uSec > usTimeOut) return 0;
- delayMicroseconds(1);
- }
- return uSec;
- }
-
- unsigned char _gpio;
- unsigned char _type;
- int _error;
-
- unsigned long _last_ok = 0;
- unsigned char _errors = 0;
-
- double _temperature;
- unsigned int _humidity;
-
- };
|