Arduino Playground is read-only starting December 31st, 2018. For more info please look at this Forum Post

Class for DHTxx sensors (xx = 11-12-21-22-33-44).

Last Modified: June 25, 2017, at 08:35 AM
By: Seth
Platforms: UNO, Leonardo, Nano

Download

Latest version on github

Intro

Looking for a cheap DHT11-like sensor with better resolution and range I came across the DHT12 sensor which is a cheap ebay buy (1$/1€). It features 0.1 resolution in temperature and humidity readings and its data format is compatible to the other DHTxx sensors.
The DHT12 looks pin-compatible, however it is not! Data is exchanged via i2c instead of 1-wire. It took me quite some time to figure that out as information on the internet is scarce... All searches lead me to DHT11 resources and I wrongfully assumed also having 4 pins means pin-compatibility. Kudos to this guy https://github.com/Bobadas/DHT12_library_Arduino who managed to provide a data-sheet (in Chinese) as well as some descriptions including a pin description of the DHT12 and a wiring diagram.

DHT12 Features

From the Chinese data-sheet:

  • Relative Humidity
    • Resolution: 0.1%RH
    • Repeatability: ±1%RH
    • Accuracy: ±5%RH (@25°C)
    • Long-term Stability:<±0.5%RH/yr
    • Response Time: 1/e(63%)25°C 20s 1m/s air 6s
    • Sluggish:<±0.3%RH

I have no clear idea what the latter two mean...

  • Temperature
    • Resolution: 0.1°C
    • Repeatability: ±0.2°C
    • Accuracy: ±0.5°C (@25°C)
    • Response Time:1/e(63%)20s

Again, I have no clear idea what the latter means... I would assume the sensor does internally some kind of integration or moving average and these time would be the times until changes in sensed data is reflected to the readout.

  • Electrical Characteristics
    • Power Supply: DC 2.7-5.5V
    • Current: 1mA
    • Standby: 60uA
    • Sampling Period: >2s
    • Pin Definition 1 - VDD 2 - SDA 3 - GND 4 - SCL

Hardware

Make sure you orient the sensor correctly to get the PINOUT correct NEVER wire it as a DHT11 they are NOT compatible (Different PINOUTS, Different Protocols) The pins on the DH13 and others sensors in this range are not symmetrical. So single wire dupont connector will give a really BAD connection. Pop the pins of your 4 single wire female connector and pop them in order into a 4 PIN Dupont Connector. A small dab of hot glue on the top of the 4 wide female dupont connector applied once the sensor wires are almost in will help with a stable physical connection.

Calibration

These units are cheap, and not calibrated. If you have 10 most will be off by a few degrees. A simple way to address this is to calibrate the temp offset / humidity offset needed to bring the sensors closer to a known good value. Write the offset needed to correct each sensor on the unit eg. +2.1 C -3% HR etc for some application these units are fine. The DHT22 is better but costs a lot more!

References

Standing on the shoulder of giants... I kludged together my library from DHTLib and DHT11Lib and extended it for the DHT12 sensor. You should definitely check out these two pages, it is a good read around using the DHT sensors. My library basically uses this great pieces of work but is blended with my personal OO preferences :)

The library

Since DHT11 sensors provide a integer resolution and the other DHTxx sensors provide 0.1 resolution, I decided (avoiding floating point arithmetic) to return all values (temperature and humidity) in x10 scaled format. So reading a 21.2°C temperature my library would yield 210 on a DHT11 or 212 on a better, say DHT12 sensor.

The library provides two classes:

  • dht1wire(uint8_t _pin, dhtmodels _model);
    Use this class for any 1-wire sensor, instantiate with e.g. dht1wire sensor(11, dth::DHT11);
  • dht12(uint8_t _id = 0x5c);
    Use this class for the i2c DHT12 sensor, instantiate e.g. with dht12 sensor(0x5c); (0x5c is the default i2c bus address of the DHT12 sensor)
    Please note that due to a shortcoming of the Arduino build system you would also have to manually include the Wire library, as the build system fails to retrieve dependencies from libraries itself :(

Both classes derive from a common base class dht, which does all the common stuff like data conversion and provides the enums for model names (e.g. dht::DHT11) and return values of the read() function. I also kludged in the sloppy and quick dew point temperature function (using floats - there is no reasonable way avoiding this). dht1wire and dht12 implement the specific _readSensor() and _storeData() function that actually does the communication with the sensor.

Example

A very minimal sketch that reads out a DHT12 sensor every 5 seconds might look like this:


/*  
 *   Example for a DHT12 sensor
 *   Beware some of the diagrams about the pinouts are incorrect.
 *   Pin Definition 1.VDD 2.SDA 3.GND 4.SCL
 *   Look at the sensor one side has holes to allow air inside. Lets call the surface with holes the FRONT
 *   The BACK of the sensor has printed codes and no holes
 *   The 4 PINS for connection come out of the BOTTOM of the sensor
 *   OK so we have defined the orientation of the sensor.
 *   Looking at the FRONT of the Sensor with the legs pointing down the LEFTMOST PIN is PIN ONE
 *  
 *  
 *   -----------------
 *   !   O O O O O   !
 *   !   O O O O O   !
 *   !   O O O O O   !
 *   !   O O O O O   !
 *   -----------------
 *       !  !  !  !
 *       !  !  !  !
 *       !  !  !  !
 *       !  !  !  !
 *       1  2  3  4
 *      
*/


#include <Wire.h>
#include <dht.h>

dht12 DHT(0x5c);

void setup()
{
  Serial.begin(9600);
  Serial.println(F("DHT12 TEST PROGRAM"));
}

void loop()
{
  unsigned long b = micros();
  dht::ReadStatus chk = DHT.read();
  unsigned long e = micros();

  Serial.print(F("Read sensor: "));
  switch (chk)
  {
    case dht::OK:
      Serial.print(F("OK, took "));
      Serial.print (e - b); Serial.print(F(" usec, "));
      break;
    case dht::ERROR_CHECKSUM:
      Serial.println(F("Checksum error"));
      break;
    case dht::ERROR_TIMEOUT:
      Serial.println(F("Timeout error"));
      break;
    case dht::ERROR_CONNECT:
      Serial.println(F("Connect error"));
      break;
    case dht::ERROR_ACK_L:
      Serial.println(F("AckL error"));
      break;
    case dht::ERROR_ACK_H:
      Serial.println(F("AckH error"));
      break;
    default:
      Serial.println(F("Unknown error"));
      break;
  }

  Serial.print(F("Humidity: "));
  Serial.print((float)DHT.getHumidity()/(float)10);
  Serial.print(F("%, "));

  Serial.print(F(". Temperature (degrees C): "));
  Serial.print((float)DHT.getTemperature()/(float)10);

  Serial.print(F(", Dew Point (degrees C): "));
  Serial.println(DHT.dewPoint());

  delay(4000);
}
//
// END OF FILE
//