diff --git a/SimpleDHT/CONTRIBUTING.md b/SimpleDHT/CONTRIBUTING.md new file mode 100644 index 0000000..998600a --- /dev/null +++ b/SimpleDHT/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contribution Guidelines + +This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work. The best way to ask for help or propose a new idea is to [create a new issue](https://github.com/winlinvip/SimpleDHT/issues/new) while creating a Pull Request with your code changes allows you to share your own innovations with the rest of the community. + +The following are some guidelines to observe when creating issues or PRs: + +- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and it is okay for people to have different ideas + +- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); it helps us help you when we can read your code! On that note also refrain from pasting more than 30 lines of code in a post, instead [create a gist](https://gist.github.com/) if you need to share large snippets + +- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile: + +- Be detailed; refrain from mentioning code problems without sharing your source code and always give information regarding your board and version of the library. diff --git a/SimpleDHT/LICENSE b/SimpleDHT/LICENSE new file mode 100644 index 0000000..00dec4c --- /dev/null +++ b/SimpleDHT/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2017 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SimpleDHT/README.md b/SimpleDHT/README.md new file mode 100644 index 0000000..4b61043 --- /dev/null +++ b/SimpleDHT/README.md @@ -0,0 +1,182 @@ +# SimpleDHT + +## Description + +An Arduino library for the DHT series of low-cost temperature/humidity sensors. + +You can find DHT11 and DHT22 tutorials [here](https://learn.adafruit.com/dht). + +## Installation + +### First Method + +![image](https://user-images.githubusercontent.com/36513474/68069796-09e62200-fd87-11e9-81e0-dc75e38efed0.png) + +1. In the Arduino IDE, navigate to Sketch > Include Library > Manage Libraries +1. Then the Library Manager will open and you will find a list of libraries that are already installed or ready for installation. +1. Then search for SimpleDHT using the search bar. +1. Click on the text area and then select the specific version and install it. + +### Second Method + +1. Navigate to the [Releases page](https://github.com/winlinvip/SimpleDHT/releases). +1. Download the latest release. +1. Extract the zip file +1. In the Arduino IDE, navigate to Sketch > Include Library > Add .ZIP Library + +## Usage + +To use this library: + +1. Open example: Arduino => File => Examples => SimpleDHT => DHT11Default +1. Connect the DHT11 and upload the program to Arduino. +1. Open the Serial Window of Arduino IDE, we got the result as follows. + +```Cpp +================================= +Sample DHT11... +Sample OK: 19 *C, 31 H +================================= +Sample DHT11... +Sample OK: 19 *C, 31 H +================================= +``` + +> Remark: For DHT11, no more than 1 Hz sampling rate (once every second). +> Remark: For DHT22, no more than 0.5 Hz sampling rate (once every 2 seconds). + +## Features + +- ### Simple + + Simple C++ code with lots of comments. + +- ### Stable + + Strictly follow the standard DHT protocol. + +- ### Fast + + Support 0.5HZ(DHT22) or 1HZ(DHT11) sampling rate. + +- ### Compatible + + SimpleDHT sensor library is compatible with multiple low-cost temperatures and humidity sensors like DHT11 and DHT22. A few examples are implemented just to demonstrate how to modify the code for different sensors. + +- ### MIT License + + DHT sensor library is open-source and uses one of the most permissive licenses so you can use it on any project. + + - Commercial use + - Modification + - Distribution + - Private use + +## Functions + +- read() +- setPinInputMode() +- setPin() +- getBitmask() +- getPort() +- levelTime() +- bits2byte() +- parse() +- read2() +- sample() + +## Sensors + +- [x] DHT11, The [product](https://www.adafruit.com/product/386), [datasheet](https://akizukidenshi.com/download/ds/aosong/DHT11.pdf) and [example](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT11Default), 1HZ sampling rate. +- [x] DHT22, The [product](https://www.adafruit.com/product/385), [datasheet](http://akizukidenshi.com/download/ds/aosong/AM2302.pdf) and [example](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT22Default), 0.5Hz sampling rate. + +## Examples + +This library including the following examples: + +1. [DHT11Default](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT11Default): Use DHT11 to sample. +1. [DHT11WithRawBits](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT11WithRawBits): Use DHT11 to sample and get the 40bits RAW data. +1. [DHT11ErrCount](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT11ErrCount): Use DHT11 to sample and stat the success rate. +1. [DHT22Default](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT22Default): Use DHT22 to sample. +1. [DHT22WithRawBits](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT22WithRawBits): Use DHT22 to sample and get the 40bits RAW data. +1. [DHT22Integer](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT22Integer): Use DHT22 to sample and ignore the fractional data. +1. [DHT22ErrCount](https://github.com/winlinvip/SimpleDHT/tree/master/examples/DHT22ErrCount): Use DHT22 to sample and stat the success rate. +1. [TwoSensorsDefault](https://github.com/winlinvip/SimpleDHT/tree/master/examples/TwoSensorsDefault): Use two DHT11 to sample. + +One of the SimpleDHT examples is the following: + +- ### DHT22Integer + +```Cpp +#include + +int pinDHT22 = 2; +SimpleDHT22 dht22(pinDHT22); + +void setup() { + Serial.begin(115200); +} + +void loop() { + + Serial.println("================================="); + Serial.println("Sample DHT22..."); + + byte temperature = 0; + byte humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht22.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT22 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(2000); + return; + } + + Serial.print("Sample OK: "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)humidity); Serial.println(" RH%"); + + delay(2500); +} +``` + +## Links + +1. [adafruit/DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library) +1. [Arduino #4469: Add SimpleDHT library.](https://github.com/arduino/Arduino/issues/4469) +1. [DHT11 datasheet and protocol.](https://akizukidenshi.com/download/ds/aosong/DHT11.pdf) +1. [DHT22 datasheet and protoocl.](http://akizukidenshi.com/download/ds/aosong/AM2302.pdf) + +Winlin 2016.1 + +## Contributing + +If you want to contribute to this project: + +- Report bugs and errors +- Ask for enhancements +- Create issues and pull requests +- Tell others about this library +- Contribute new protocols + +Please read [CONTRIBUTING.md](https://github.com/winlinvip/SimpleDHT/blob/master/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. + +## Credits + +The author and maintainer of this library is Winlin . + +Based on previous work by: + +- t-w +- O. Santos +- P. H. Dabrowski +- per1234 +- P. Rinn +- G. M. Vacondio +- D. Faust +- C. Stroie +- Samlof +- Agha Saad Fraz + +## License + +This library is licensed under [MIT](https://github.com/winlinvip/SimpleDHT/blob/master/LICENSE). diff --git a/SimpleDHT/SimpleDHT.cpp b/SimpleDHT/SimpleDHT.cpp new file mode 100644 index 0000000..6fa990a --- /dev/null +++ b/SimpleDHT/SimpleDHT.cpp @@ -0,0 +1,364 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2017 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "SimpleDHT.h" + +SimpleDHT::SimpleDHT() { +} + +SimpleDHT::SimpleDHT(int pin) { + setPin(pin); +} + +void SimpleDHT::setPin(int pin) { + this->pin = pin; +#ifdef __AVR + // (only AVR) - set low level properties for configured pin + bitmask = digitalPinToBitMask(pin); + port = digitalPinToPort(pin); +#endif +} + +int SimpleDHT::setPinInputMode(uint8_t mode) { + if (mode != INPUT && mode != INPUT_PULLUP) { + return SimpleDHTErrPinMode; + } + this->pinInputMode = mode; + return SimpleDHTErrSuccess; +} + +int SimpleDHT::read(byte* ptemperature, byte* phumidity, byte pdata[40]) { + int ret = SimpleDHTErrSuccess; + + if (pin == -1) { + return SimpleDHTErrNoPin; + } + + float temperature = 0; + float humidity = 0; + if ((ret = read2(&temperature, &humidity, pdata)) != SimpleDHTErrSuccess) { + return ret; + } + + if (ptemperature) { + *ptemperature = (byte)(int)temperature; + } + + if (phumidity) { + *phumidity = (byte)(int)humidity; + } + + return ret; +} + +int SimpleDHT::read(int pin, byte* ptemperature, byte* phumidity, byte pdata[40]) { + setPin(pin); + return read(ptemperature, phumidity, pdata); +} + +#ifdef __AVR +int SimpleDHT::getBitmask() { + return bitmask; +} + +int SimpleDHT::getPort() { + return port; +} +#endif + +long SimpleDHT::levelTime(byte level, int firstWait, int interval) { + unsigned long time_start = micros(); + long time = 0; + +#ifdef __AVR + uint8_t portState = level ? bitmask : 0; +#endif + + bool loop = true; + for (int i = 0 ; loop; i++) { + if (time < 0 || time > levelTimeout) { + return -1; + } + + if (i == 0) { + if (firstWait > 0) { + delayMicroseconds(firstWait); + } + } else if (interval > 0) { + delayMicroseconds(interval); + } + + // for an unsigned int type, the difference have a correct value + // even if overflow, explanation here: + // https://arduino.stackexchange.com/questions/33572/arduino-countdown-without-using-delay + time = micros() - time_start; + +#ifdef __AVR + loop = ((*portInputRegister(port) & bitmask) == portState); +#else + loop = (digitalRead(pin) == level); +#endif + } + + return time; +} + +byte SimpleDHT::bits2byte(byte data[8]) { + byte v = 0; + for (int i = 0; i < 8; i++) { + v += data[i] << (7 - i); + } + return v; +} + +int SimpleDHT::parse(byte data[40], short* ptemperature, short* phumidity) { + short humidity = bits2byte(data); + short humidity2 = bits2byte(data + 8); + short temperature = bits2byte(data + 16); + short temperature2 = bits2byte(data + 24); + byte check = bits2byte(data + 32); + byte expect = (byte)humidity + (byte)humidity2 + (byte)temperature + (byte)temperature2; + if (check != expect) { + return SimpleDHTErrDataChecksum; + } + + *ptemperature = temperature<<8 | temperature2; + *phumidity = humidity<<8 | humidity2; + + return SimpleDHTErrSuccess; +} + +SimpleDHT11::SimpleDHT11() { +} + +SimpleDHT11::SimpleDHT11(int pin) : SimpleDHT (pin) { +} + +int SimpleDHT11::read2(float* ptemperature, float* phumidity, byte pdata[40]) { + int ret = SimpleDHTErrSuccess; + + if (pin == -1) { + return SimpleDHTErrNoPin; + } + + byte data[40] = {0}; + if ((ret = sample(data)) != SimpleDHTErrSuccess) { + return ret; + } + + short temperature = 0; + short humidity = 0; + if ((ret = parse(data, &temperature, &humidity)) != SimpleDHTErrSuccess) { + return ret; + } + + if (pdata) { + memcpy(pdata, data, 40); + } + if (ptemperature) { + *ptemperature = (int)(temperature>>8); + } + if (phumidity) { + *phumidity = (int)(humidity>>8); + } + + // For example, when remove the data line, it will be success with zero data. + if (temperature == 0 && humidity == 0) { + return SimpleDHTErrZeroSamples; + } + + return ret; +} + +int SimpleDHT11::read2(int pin, float* ptemperature, float* phumidity, byte pdata[40]) { + setPin(pin); + return read2(ptemperature, phumidity, pdata); +} + +int SimpleDHT11::sample(byte data[40]) { + // empty output data. + memset(data, 0, 40); + + // According to protocol: [1] https://akizukidenshi.com/download/ds/aosong/DHT11.pdf + // notify DHT11 to start: + // 1. PULL LOW 20ms. + // 2. PULL HIGH 20-40us. + // 3. SET TO INPUT or INPUT_PULLUP. + // Changes in timing done according to: + // [2] https://www.mouser.com/ds/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf + // - original values specified in code + // - since they were not working (MCU-dependent timing?), replace in code with + // _working_ values based on measurements done with levelTimePrecise() + pinMode(pin, OUTPUT); + digitalWrite(pin, LOW); // 1. + delay(20); // specs [2]: 18us + + // Pull high and set to input, before wait 40us. + // @see https://github.com/winlinvip/SimpleDHT/issues/4 + // @see https://github.com/winlinvip/SimpleDHT/pull/5 + digitalWrite(pin, HIGH); // 2. + pinMode(pin, this->pinInputMode); + delayMicroseconds(25); // specs [2]: 20-40us + + // DHT11 starting: + // 1. PULL LOW 80us + // 2. PULL HIGH 80us + long t = levelTime(LOW); // 1. + if (t < 30) { // specs [2]: 80us + return simpleDHTCombileError(t, SimpleDHTErrStartLow); + } + + t = levelTime(HIGH); // 2. + if (t < 50) { // specs [2]: 80us + return simpleDHTCombileError(t, SimpleDHTErrStartHigh); + } + + // DHT11 data transmite: + // 1. 1bit start, PULL LOW 50us + // 2. PULL HIGH: + // - 26-28us, bit(0) + // - 70us, bit(1) + for (int j = 0; j < 40; j++) { + t = levelTime(LOW); // 1. + if (t < 24) { // specs says: 50us + return simpleDHTCombileError(t, SimpleDHTErrDataLow); + } + + // read a bit + t = levelTime(HIGH); // 2. + if (t < 11) { // specs say: 20us + return simpleDHTCombileError(t, SimpleDHTErrDataRead); + } + data[ j ] = (t > 40 ? 1 : 0); // specs: 26-28us -> 0, 70us -> 1 + } + + // DHT11 EOF: + // 1. PULL LOW 50us. + t = levelTime(LOW); // 1. + if (t < 24) { // specs say: 50us + return simpleDHTCombileError(t, SimpleDHTErrDataEOF); + } + + return SimpleDHTErrSuccess; +} + +SimpleDHT22::SimpleDHT22() { +} + +SimpleDHT22::SimpleDHT22(int pin) : SimpleDHT (pin) { +} + +int SimpleDHT22::read2(float* ptemperature, float* phumidity, byte pdata[40]) { + int ret = SimpleDHTErrSuccess; + + if (pin == -1) { + return SimpleDHTErrNoPin; + } + + byte data[40] = {0}; + if ((ret = sample(data)) != SimpleDHTErrSuccess) { + return ret; + } + + short temperature = 0; + short humidity = 0; + if ((ret = parse(data, &temperature, &humidity)) != SimpleDHTErrSuccess) { + return ret; + } + + if (pdata) { + memcpy(pdata, data, 40); + } + if (ptemperature) { + *ptemperature = (float)((temperature & 0x8000 ? -1 : 1) * (temperature & 0x7FFF)) / 10.0; + } + if (phumidity) { + *phumidity = (float)humidity / 10.0; + } + + return ret; +} + +int SimpleDHT22::read2(int pin, float* ptemperature, float* phumidity, byte pdata[40]) { + setPin(pin); + return read2(ptemperature, phumidity, pdata); +} + +int SimpleDHT22::sample(byte data[40]) { + // empty output data. + memset(data, 0, 40); + + // According to protocol: http://akizukidenshi.com/download/ds/aosong/AM2302.pdf + // notify DHT22 to start: + // 1. T(be), PULL LOW 1ms(0.8-20ms). + // 2. T(go), PULL HIGH 30us(20-200us), use 40us. + // 3. SET TO INPUT or INPUT_PULLUP. + pinMode(pin, OUTPUT); + digitalWrite(pin, LOW); + delayMicroseconds(1000); + // Pull high and set to input, before wait 40us. + // @see https://github.com/winlinvip/SimpleDHT/issues/4 + // @see https://github.com/winlinvip/SimpleDHT/pull/5 + digitalWrite(pin, HIGH); + pinMode(pin, this->pinInputMode); + delayMicroseconds(40); + + // DHT22 starting: + // 1. T(rel), PULL LOW 80us(75-85us). + // 2. T(reh), PULL HIGH 80us(75-85us). + long t = 0; + if ((t = levelTime(LOW)) < 30) { + return simpleDHTCombileError(t, SimpleDHTErrStartLow); + } + if ((t = levelTime(HIGH)) < 50) { + return simpleDHTCombileError(t, SimpleDHTErrStartHigh); + } + + // DHT22 data transmite: + // 1. T(LOW), 1bit start, PULL LOW 50us(48-55us). + // 2. T(H0), PULL HIGH 26us(22-30us), bit(0) + // 3. T(H1), PULL HIGH 70us(68-75us), bit(1) + for (int j = 0; j < 40; j++) { + t = levelTime(LOW); // 1. + if (t < 24) { // specs says: 50us + return simpleDHTCombileError(t, SimpleDHTErrDataLow); + } + + // read a bit + t = levelTime(HIGH); // 2. + if (t < 11) { // specs say: 26us + return simpleDHTCombileError(t, SimpleDHTErrDataRead); + } + data[ j ] = (t > 40 ? 1 : 0); // specs: 22-30us -> 0, 70us -> 1 + } + + // DHT22 EOF: + // 1. T(en), PULL LOW 50us(45-55us). + t = levelTime(LOW); + if (t < 24) { + return simpleDHTCombileError(t, SimpleDHTErrDataEOF); + } + + return SimpleDHTErrSuccess; +} diff --git a/SimpleDHT/SimpleDHT.h b/SimpleDHT/SimpleDHT.h new file mode 100644 index 0000000..f931d87 --- /dev/null +++ b/SimpleDHT/SimpleDHT.h @@ -0,0 +1,189 @@ +/* + The MIT License (MIT) + + Copyright (c) 2016-2017 winlin + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +#ifndef __SIMPLE_DHT_H +#define __SIMPLE_DHT_H + +#include + +// High 8bits are time duration. +// Low 8bits are error code. +// For example, 0x0310 means t=0x03 and code=0x10, +// which is start low signal(0x10) error. +// @see https://github.com/winlinvip/SimpleDHT/issues/25 +#define simpleDHTCombileError(t, err) ((t << 8) & 0xff00) | (err & 0x00ff) + +// Get the time duration from error. +#define SimpleDHTErrDuration(err) ((err&0xff00)>>8) +// Get the error code defined bellow. +#define SimpleDHTErrCode(err) (err&0x00ff) + +// Success. +#define SimpleDHTErrSuccess 0 +// Error to wait for start low signal. +#define SimpleDHTErrStartLow 16 +// Error to wait for start high signal. +#define SimpleDHTErrStartHigh 17 +// Error to wait for data start low signal. +#define SimpleDHTErrDataLow 18 +// Error to wait for data read signal. +#define SimpleDHTErrDataRead 19 +// Error to wait for data EOF signal. +#define SimpleDHTErrDataEOF 20 +// Error to validate the checksum. +#define SimpleDHTErrDataChecksum 21 +// Error when temperature and humidity are zero, it shouldn't happen. +#define SimpleDHTErrZeroSamples 22 +// Error when pin is not initialized. +#define SimpleDHTErrNoPin 23 +// Error when pin mode is invalid. +#define SimpleDHTErrPinMode 24 + +class SimpleDHT { +protected: + long levelTimeout = 500000; // 500ms + int pin = -1; + uint8_t pinInputMode = INPUT; +#ifdef __AVR + // For direct GPIO access (8-bit AVRs only), store port and bitmask + // of the digital pin connected to the DHT. + // (other platforms use digitalRead(), do not need this) + uint8_t bitmask = 0xFF; + uint8_t port = 0xFF; +#endif +public: + SimpleDHT(); + SimpleDHT(int pin); +public: + // To (eventually) change the pin configuration for existing instance + // @param pin The DHT11 or DHT22 pin. + virtual void setPin(int pin); + // Set the input mode of the pin from INPUT and INPUT_PULLUP + // to permit the use of the internal pullup resistor for + // for bare modules + // @param mode the pin input mode. + // @return SimpleDHTErrSuccess is success; otherwise, failed. + virtual int setPinInputMode(uint8_t mode); +public: + // Read from dht11 or dht22. + // @param pin The DHT11 pin. + // @param ptemperature output, NULL to igore. In Celsius. + // @param phumidity output, NULL to ignore. + // For DHT11, in H, such as 35H. + // For DHT22, in RH%, such as 53%RH. + // @param pdata output 40bits sample, NULL to ignore. + // @remark the min delay for this method is 1s(DHT11) or 2s(DHT22). + // @return SimpleDHTErrSuccess is success; otherwise, failed. + virtual int read(byte* ptemperature, byte* phumidity, byte pdata[40]); + virtual int read(int pin, byte* ptemperature, byte* phumidity, byte pdata[40]); + // To get a more accurate data. + // @remark it's available for dht22. for dht11, it's the same of read(). + virtual int read2(float* ptemperature, float* phumidity, byte pdata[40]) = 0; + virtual int read2(int pin, float* ptemperature, float* phumidity, byte pdata[40]) = 0; +protected: + // For only AVR - methods returning low level conf. of the pin +#ifdef __AVR + // @return Bitmask to access pin state from port input register + virtual int getBitmask(); + // @return Bitmask to access pin state from port input register + virtual int getPort(); +#endif +protected: + // Measure and return time (in microseconds) + // with precision defined by interval between checking the state + // while pin is in specified state (HIGH or LOW) + // @param level state which time is measured. + // @param interval time interval between consecutive state checks. + // @return measured time (microseconds). -1 if timeout. + virtual long levelTime(byte level, int firstWait = 10, int interval = 6); + // @data the bits of a byte. + // @remark please use simple_dht11_read(). + virtual byte bits2byte(byte data[8]); + // read temperature and humidity from dht11. + // @param data a byte[40] to read bits to 5bytes. + // @return 0 success; otherwise, error. + // @remark please use simple_dht11_read(). + virtual int sample(byte data[40]) = 0; + // parse the 40bits data to temperature and humidity. + // @remark please use simple_dht11_read(). + virtual int parse(byte data[40], short* ptemperature, short* phumidity); +}; + +/* + Simple DHT11 + + Simple, Stable and Fast DHT11 library. + + The circuit: + * VCC: 5V or 3V + * GND: GND + * DATA: Digital ping, for instance 2. + + 23 Jan 2016 By winlin + + https://github.com/winlinvip/SimpleDHT#usage + https://akizukidenshi.com/download/ds/aosong/DHT11.pdf + https://cdn-shop.adafruit.com/datasheets/DHT11-chinese.pdf + +*/ +class SimpleDHT11 : public SimpleDHT { +public: + SimpleDHT11(); + SimpleDHT11(int pin); +public: + virtual int read2(float* ptemperature, float* phumidity, byte pdata[40]); + virtual int read2(int pin, float* ptemperature, float* phumidity, byte pdata[40]); +protected: + virtual int sample(byte data[40]); +}; + +/* + Simple DHT22 + + Simple, Stable and Fast DHT22 library. + + The circuit: + * VCC: 5V or 3V + * GND: GND + * DATA: Digital ping, for instance 2. + + 3 Jun 2017 By winlin + + https://github.com/winlinvip/SimpleDHT#usage + http://akizukidenshi.com/download/ds/aosong/AM2302.pdf + https://cdn-shop.adafruit.com/datasheets/DHT22.pdf + +*/ +class SimpleDHT22 : public SimpleDHT { +public: + SimpleDHT22(); + SimpleDHT22(int pin); +public: + virtual int read2(float* ptemperature, float* phumidity, byte pdata[40]); + virtual int read2(int pin, float* ptemperature, float* phumidity, byte pdata[40]); +protected: + virtual int sample(byte data[40]); +}; + +#endif diff --git a/SimpleDHT/examples/DHT11Default/DHT11Default.ino b/SimpleDHT/examples/DHT11Default/DHT11Default.ino new file mode 100644 index 0000000..a0aca08 --- /dev/null +++ b/SimpleDHT/examples/DHT11Default/DHT11Default.ino @@ -0,0 +1,35 @@ +#include + +// for DHT11, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT11 = 2; +SimpleDHT11 dht11(pinDHT11); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT11..."); + + // read without samples. + byte temperature = 0; + byte humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT11 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(1000); + return; + } + + Serial.print("Sample OK: "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)humidity); Serial.println(" H"); + + // DHT11 sampling rate is 1HZ. + delay(1500); +} diff --git a/SimpleDHT/examples/DHT11ErrCount/DHT11ErrCount.ino b/SimpleDHT/examples/DHT11ErrCount/DHT11ErrCount.ino new file mode 100644 index 0000000..b95c308 --- /dev/null +++ b/SimpleDHT/examples/DHT11ErrCount/DHT11ErrCount.ino @@ -0,0 +1,42 @@ +#include + +// for DHT11, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT11 = 2; +SimpleDHT11 dht11(pinDHT11); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT11 with error count"); + + int cnt = 0; + int err_cnt = 0; + for (;;) { + cnt++; + + byte temperature = 0; + byte humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT11 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.print(SimpleDHTErrDuration(err)); + err_cnt++; + } else { + Serial.print("DHT11, "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)humidity); Serial.print(" H"); + } + Serial.print(", total: "); Serial.print(cnt); + Serial.print(", err: "); Serial.print(err_cnt); + Serial.print(", success rate: "); Serial.print((cnt - err_cnt) * 100.0 / (float)cnt); Serial.println("%"); + + delay(1500); + } +} diff --git a/SimpleDHT/examples/DHT11WithRawBits/DHT11WithRawBits.ino b/SimpleDHT/examples/DHT11WithRawBits/DHT11WithRawBits.ino new file mode 100644 index 0000000..a2408d1 --- /dev/null +++ b/SimpleDHT/examples/DHT11WithRawBits/DHT11WithRawBits.ino @@ -0,0 +1,45 @@ +#include + +// for DHT11, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT11 = 2; +SimpleDHT11 dht11(pinDHT11); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT11 with RAW bits..."); + + // read with raw sample data. + byte temperature = 0; + byte humidity = 0; + byte data[40] = {0}; + int err = SimpleDHTErrSuccess; + if ((err = dht11.read(&temperature, &humidity, data)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT11 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(1000); + return; + } + + Serial.print("Sample RAW Bits: "); + for (int i = 0; i < 40; i++) { + Serial.print((int)data[i]); + if (i > 0 && ((i + 1) % 4) == 0) { + Serial.print(' '); + } + } + Serial.println(""); + + Serial.print("Sample OK: "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)humidity); Serial.println(" H"); + + // DHT11 sampling rate is 1HZ. + delay(1500); +} diff --git a/SimpleDHT/examples/DHT22Default/DHT22Default.ino b/SimpleDHT/examples/DHT22Default/DHT22Default.ino new file mode 100644 index 0000000..eabdba5 --- /dev/null +++ b/SimpleDHT/examples/DHT22Default/DHT22Default.ino @@ -0,0 +1,37 @@ +#include + +// for DHT22, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT22 = 2; +SimpleDHT22 dht22(pinDHT22); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT22..."); + + // read without samples. + // @remark We use read2 to get a float data, such as 10.1*C + // if user doesn't care about the accurate data, use read to get a byte data, such as 10*C. + float temperature = 0; + float humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht22.read2(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT22 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(2000); + return; + } + + Serial.print("Sample OK: "); + Serial.print((float)temperature); Serial.print(" *C, "); + Serial.print((float)humidity); Serial.println(" RH%"); + + // DHT22 sampling rate is 0.5HZ. + delay(2500); +} diff --git a/SimpleDHT/examples/DHT22ErrCount/DHT22ErrCount.ino b/SimpleDHT/examples/DHT22ErrCount/DHT22ErrCount.ino new file mode 100644 index 0000000..4c3e771 --- /dev/null +++ b/SimpleDHT/examples/DHT22ErrCount/DHT22ErrCount.ino @@ -0,0 +1,42 @@ +#include + +// for DHT22, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT22 = 2; +SimpleDHT22 dht22(pinDHT22); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT22 with error count"); + + int cnt = 0; + int err_cnt = 0; + for (;;) { + cnt++; + + float temperature = 0; + float humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht22.read2(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT22 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.print(SimpleDHTErrDuration(err)); + err_cnt++; + } else { + Serial.print("DHT22, "); + Serial.print((float)temperature); Serial.print(" *C, "); + Serial.print((float)humidity); Serial.print(" RH%"); + } + Serial.print(", total: "); Serial.print(cnt); + Serial.print(", err: "); Serial.print(err_cnt); + Serial.print(", success rate: "); Serial.print((cnt - err_cnt) * 100.0 / (float)cnt); Serial.println("%"); + + delay(2500); + } +} diff --git a/SimpleDHT/examples/DHT22Integer/DHT22Integer.ino b/SimpleDHT/examples/DHT22Integer/DHT22Integer.ino new file mode 100644 index 0000000..1f3ed47 --- /dev/null +++ b/SimpleDHT/examples/DHT22Integer/DHT22Integer.ino @@ -0,0 +1,35 @@ +#include + +// for DHT22, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT22 = 2; +SimpleDHT22 dht22(pinDHT22); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT22..."); + + // read without samples. + byte temperature = 0; + byte humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht22.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT22 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(2000); + return; + } + + Serial.print("Sample OK: "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)humidity); Serial.println(" RH%"); + + // DHT22 sampling rate is 0.5HZ. + delay(2500); +} diff --git a/SimpleDHT/examples/DHT22WithRawBits/DHT22WithRawBits.ino b/SimpleDHT/examples/DHT22WithRawBits/DHT22WithRawBits.ino new file mode 100644 index 0000000..d1d5b24 --- /dev/null +++ b/SimpleDHT/examples/DHT22WithRawBits/DHT22WithRawBits.ino @@ -0,0 +1,47 @@ +#include + +// for DHT22, +// VCC: 5V or 3V +// GND: GND +// DATA: 2 +int pinDHT22 = 2; +SimpleDHT22 dht22(pinDHT22); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // start working... + Serial.println("================================="); + Serial.println("Sample DHT22 with RAW bits..."); + + // read with raw sample data. + // @remark We use read2 to get a float data, such as 10.1*C + // if user doesn't care about the accurate data, use read to get a byte data, such as 10*C. + float temperature = 0; + float humidity = 0; + byte data[40] = {0}; + int err = SimpleDHTErrSuccess; + if ((err = dht22.read2(&temperature, &humidity, data)) != SimpleDHTErrSuccess) { + Serial.print("Read DHT22 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(2000); + return; + } + + Serial.print("Sample RAW Bits: "); + for (int i = 0; i < 40; i++) { + Serial.print((int)data[i]); + if (i > 0 && ((i + 1) % 4) == 0) { + Serial.print(' '); + } + } + Serial.println(""); + + Serial.print("Sample OK: "); + Serial.print((float)temperature); Serial.print(" *C, "); + Serial.print((float)humidity); Serial.println(" RH%"); + + // DHT22 sampling rate is 0.5HZ. + delay(2500); +} diff --git a/SimpleDHT/examples/TwoSensorsDefault/TwoSensorsDefault.ino b/SimpleDHT/examples/TwoSensorsDefault/TwoSensorsDefault.ino new file mode 100644 index 0000000..3397282 --- /dev/null +++ b/SimpleDHT/examples/TwoSensorsDefault/TwoSensorsDefault.ino @@ -0,0 +1,66 @@ +#include + +// Created by santosomar Ωr using SimpleDHT library to read data from two DHT11 sensors +// for DHT11, +// VCC: 5V or 3V +// GND: GND +// SENSOR 1 is in Digital Data pin: 2 +// SENSOR 2 is in Digital Data pin: 4 + +int dataPinSensor1 = 2; +int dataPinSensor2 = 4; +SimpleDHT11 dht1(dataPinSensor1); +SimpleDHT11 dht2(dataPinSensor2); + +void setup() { + Serial.begin(115200); +} + +void loop() { + // Reading data from sensor 1... + Serial.println("================================="); + + // Reading data from sensor 1... + Serial.println("Getting data from sensor 1..."); + + // read without samples. + byte temperature = 0; + byte humidity = 0; + int err = SimpleDHTErrSuccess; + if ((err = dht1.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read Sensor 1 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(1000); + return; + } + + // converting Celsius to Fahrenheit + byte f = temperature * 1.8 + 32; + Serial.print("Sample OK: "); + Serial.print((int)temperature); Serial.print(" *C, "); + Serial.print((int)f); Serial.print(" *F, "); + Serial.print((int)humidity); Serial.println(" H humidity"); + + + // Reading data from sensor 2... + // ============================ + Serial.println("Getting data from sensor 2..."); + + byte temperature2 = 0; + byte humidity2 = 0; + if ((err = dht2.read(&temperature2, &humidity2, NULL)) != SimpleDHTErrSuccess) { + Serial.print("Read Sensor 2 failed, err="); Serial.print(SimpleDHTErrCode(err)); + Serial.print(","); Serial.println(SimpleDHTErrDuration(err)); delay(1000); + return; + } + + // converting Celsius to Fahrenheit + byte fb = temperature2 * 1.8 + 32; + + Serial.print("Sample OK: "); + Serial.print((int)temperature2); Serial.print(" *C, "); + Serial.print((int)fb); Serial.print(" *F, "); + Serial.print((int)humidity2); Serial.println(" H humidity"); + + // DHT11 sampling rate is 1HZ. + delay(1500); +} diff --git a/SimpleDHT/keywords.txt b/SimpleDHT/keywords.txt new file mode 100644 index 0000000..85bd132 --- /dev/null +++ b/SimpleDHT/keywords.txt @@ -0,0 +1,18 @@ +########################################### +# Syntax Coloring Map For SimpleDHT +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### +SimpleDHT11 KEYWORD1 +SimpleDHT22 KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### +read KEYWORD2 + +########################################### +# Constants (LITERAL1) +########################################### diff --git a/SimpleDHT/library.properties b/SimpleDHT/library.properties new file mode 100644 index 0000000..b56786a --- /dev/null +++ b/SimpleDHT/library.properties @@ -0,0 +1,9 @@ +name=SimpleDHT +version=1.0.15 +author=Winlin +maintainer=Winlin +sentence=Arduino Temp & Humidity Sensors for DHT11 and DHT22. +paragraph=Simple C++ code with lots of comments, strictly follow the standard DHT protocol, supports 0.5HZ(DHT22) or 1HZ(DHT11) sampling rate. +category=Sensors +url=https://github.com/winlinvip/SimpleDHT +architectures=*