diff --git a/arduino/HalMultiSensor/HalConfiguration.h b/arduino/HalMultiSensor/HalConfiguration.h index 4de98281..13f852dc 100755 --- a/arduino/HalMultiSensor/HalConfiguration.h +++ b/arduino/HalMultiSensor/HalConfiguration.h @@ -3,7 +3,7 @@ #define ENABLE_DEBUG // comment out to disable debug -#define TIMER_MILLISECOND 60*1000 // poling in minutes +#define TIMER_MILLISECOND 10*1000 // poling in minutes #define INDICATOR_PIN 13 // diod // POWER CONSUMPTION SENSOR @@ -14,7 +14,7 @@ // TEMPERATURE SENSOR #define TEMPERATURE_ENABLED // comment out to disable sensor -#define TEMPERATURE_SENSOR SensorDHT11(10) +#define TEMPERATURE_SENSOR SensorDHT(DHT22, 10) #define TEMPERATURE_PROTOCOL ProtocolOregon(11, 100) #define TEMPERATURE_TIMER_MULTIPLIER 1 diff --git a/arduino/HalMultiSensor/HalInclude.h b/arduino/HalMultiSensor/HalInclude.h index d1b7979f..bef0a17d 100755 --- a/arduino/HalMultiSensor/HalInclude.h +++ b/arduino/HalMultiSensor/HalInclude.h @@ -3,7 +3,7 @@ /////// SENSORS #include "SensorBH1750.h" -#include "SensorDHT11.h" +#include "SensorDHT.h" #include "SensorPhotocell.h" //////// PROTOCOLS diff --git a/arduino/HalMultiSensor/HalInterfaces.h b/arduino/HalMultiSensor/HalInterfaces.h index 03aa7ed9..a4966c72 100755 --- a/arduino/HalMultiSensor/HalInterfaces.h +++ b/arduino/HalMultiSensor/HalInterfaces.h @@ -69,7 +69,7 @@ public: struct TemperatureData { float temperature; - short humidity; + float humidity; }; class SensorTemperature : public Sensor { diff --git a/arduino/HalMultiSensor/SensorDHT.cpp b/arduino/HalMultiSensor/SensorDHT.cpp new file mode 100755 index 00000000..651a18a9 --- /dev/null +++ b/arduino/HalMultiSensor/SensorDHT.cpp @@ -0,0 +1,159 @@ +/* DHT library +MIT license +written by Adafruit Industries +*/ +// Modified by Ziver Koc +// + +#include "SensorDHT.h" + + +void SensorDHT::setup() +{ + // set up the pins! + pinMode(_pin, INPUT_PULLUP); + _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for + // reading pulses from DHT sensor. +} + + +// Expect the signal line to be at the specified level for a period of time and +// return a count of loop cycles spent at that level (this cycle count can be +// used to compare the relative time of two pulses). If more than a millisecond +// ellapses without the level changing then the call fails with a 0 response. +// This is adapted from Arduino's pulseInLong function (which is only available +// in the very latest IDE versions): +// https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_pulse.c +uint32_t SensorDHT::expectPulse(bool level) { + uint32_t count = 0; + // On AVR platforms use direct GPIO port access as it's much faster and better + // for catching pulses that are 10's of microseconds in length: + #ifdef __AVR + uint8_t portState = level ? _bit : 0; + while ((*portInputRegister(_port) & _bit) == portState) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + // Otherwise fall back to using digitalRead (this seems to be necessary on ESP8266 + // right now, perhaps bugs in direct port access functions?). + #else + while (digitalRead(_pin) == level) { + if (count++ >= _maxcycles) { + return 0; // Exceeded timeout, fail. + } + } + #endif + + return count; +} + + +void SensorDHT::read(TemperatureData& retData) +{ + // Reset 40 bits of received data to zero. + static uint8_t data[5]; + 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. + noInterrupts(); + + // 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("DHT:Timeout waiting for start signal low pulse."); + return; + } + if (expectPulse(HIGH) == 0) { + DEBUG("DHT:Timeout waiting for start signal high pulse."); + return; + } + + // 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); + } + + interrupts(); + } // 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("DHT:Timeout waiting for pulse."); + return; + } + 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. + } + + + // Check we read 40 bits and that the checksum matches. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { + switch (_type) { + case DHT11: + retData.temperature = data[2]; + retData.humidity = data[0]; + break; + case DHT22: + case DHT21: + retData.temperature = data[2] & 0x7F; + retData.temperature *= 256; + retData.temperature += data[3]; + retData.temperature *= 0.1; + if (data[2] & 0x80) { + retData.temperature *= -1; + } + retData.humidity = data[0]; + retData.humidity *= 256; + retData.humidity += data[1]; + retData.humidity *= 0.1; + break; + } + } + else { + DEBUG("DHT:Checksum failure!"); + } +} \ No newline at end of file diff --git a/arduino/HalMultiSensor/SensorDHT.h b/arduino/HalMultiSensor/SensorDHT.h new file mode 100755 index 00000000..04e2559a --- /dev/null +++ b/arduino/HalMultiSensor/SensorDHT.h @@ -0,0 +1,33 @@ +#ifndef SensorDHT_h +#define SensorDHT_h + +#include +#include "HalInterfaces.h" + + +// Define types of sensors. +#define DHT11 11 +#define DHT22 22 +#define DHT21 21 + + +class SensorDHT : public SensorTemperature +{ +public: + SensorDHT(uint8_t type, uint8_t pin) : _type(type), _pin(pin) {}; + + virtual void setup(); + virtual void read(TemperatureData& data); + +private: + uint8_t _type, _pin; + uint32_t _maxcycles; + #ifdef __AVR + // Use direct GPIO access on an 8-bit AVR so keep track of the port and bitmask + // for the digital pin connected to the DHT. Other platforms will use digitalRead. + uint8_t _bit, _port; + #endif + + uint32_t expectPulse(bool level); +}; +#endif diff --git a/arduino/HalMultiSensor/SensorDHT11.cpp b/arduino/HalMultiSensor/SensorDHT11.cpp deleted file mode 100755 index deb01d8e..00000000 --- a/arduino/HalMultiSensor/SensorDHT11.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// FILE: dht11.cpp -// VERSION: 0.3.2 -// PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino -// LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html) -// -// DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf -// -// HISTORY: -// George Hadjikyriacou - Original version (??) -// Mod by SimKard - Version 0.2 (24/11/2010) -// Mod by Rob Tillaart - Version 0.3 (28/03/2011) -// + added comments -// + removed all non DHT11 specific code -// + added references -// Refactored by Ziver Koc -// - -#include "SensorDHT11.h" - - -void SensorDHT11::setup(){} - - -void SensorDHT11::read(TemperatureData& data) -{ - // BUFFER TO RECEIVE - uint8_t bits[5] = {0}; - uint8_t cnt = 7; - uint8_t idx = 0; - - // REQUEST SAMPLE - pinMode(pin, OUTPUT); - digitalWrite(pin, LOW); - delay(18); - digitalWrite(pin, HIGH); - delayMicroseconds(40); - pinMode(pin, INPUT); - - // ACKNOWLEDGE or TIMEOUT - unsigned int loopCnt = 10000; - while(digitalRead(pin) == LOW) - if (loopCnt-- == 0) - { - DEBUG("DHT11 timeout"); - return;; - } - - loopCnt = 10000; - while(digitalRead(pin) == HIGH) - if (loopCnt-- == 0) - { - DEBUG("DHT11 timeout"); - return;; - } - - // READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT - for (int i=0; i<40; i++) - { - loopCnt = 10000; - while(digitalRead(pin) == LOW) - if (loopCnt-- == 0) - { - DEBUG("DHT11 timeout"); - return;; - } - - unsigned long t = micros(); - - loopCnt = 10000; - while(digitalRead(pin) == HIGH) - if (loopCnt-- == 0) - { - DEBUG("DHT11 timeout"); - return;; - } - - if ((micros() - t) > 40) bits[idx] |= (1 << cnt); - if (cnt == 0) // next byte? - { - cnt = 7; // restart at MSB - idx++; // next byte! - } - else cnt--; - } - - - uint8_t sum = bits[0] + bits[2]; - if (bits[4] != sum) - DEBUG("DHT11 checksum error"); - - // WRITE TO RIGHT VARS - // as bits[1] and bits[3] are allways zero they are omitted in formulas. - data.temperature = bits[2]; - data.humidity = bits[0]; -} - diff --git a/arduino/HalMultiSensor/SensorDHT11.h b/arduino/HalMultiSensor/SensorDHT11.h deleted file mode 100755 index 40bba2e8..00000000 --- a/arduino/HalMultiSensor/SensorDHT11.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SensorDHT11_h -#define SensorDHT11_h - -#include -#include "HalInterfaces.h" - - -class SensorDHT11 : public SensorTemperature -{ -public: - SensorDHT11(short pin) : pin(pin) {}; - - virtual void setup(); - virtual void read(TemperatureData& data); - -private: - short pin; -}; -#endif