Class for DHT11, DHT21 and DHT22 (temperature & humidity)

update: As the DHTLib is used more and more on ARM processors I added a separate repository for the stable 0.1.13 version of the DHT library on github. URL: Arduino/libraries/DHTstable at master · RobTillaart/Arduino · GitHub

Last week I posted a DHT class on the playground - Arduino Playground - DHTLib - that supports both DHT11 and DHT22 sensors.

Although the protocol / handshake is the same for both sensors the dataformats used differ unfortunately. The DHT22 has a wider range and higher resolution. The class is rewritten completely from scratch but inspired by earlier work of George Hadjikyriacou (see also - Arduino Playground - DHT11Lib ) . The class has two read functions called read11(PIN) and read22(PIN) to read the different sensors. This way one instance of the class can serve multiple, and even mixed sensors. The code of the lib is straightforward and can be stripped if one only has DHT11 or only DHT22's.

As always, comments and remarks are welcome.


update 2013-08-26: support for DHT21


update 2014-06-01: improved timing -> 0.1.10 version


update 2014-06-26: DHT33/44 support -> 0.1.13 version

latest version - Arduino/libraries/DHTlib at master · RobTillaart/Arduino · GitHub -

Note: Attached 0.1.13 version is (for now) latest that is compatible with pre 1.0 Arduino. It is the preferred version. (versions after 0.1.13 are exploring optimizations)

dht 0.1.13.zip (9.07 KB)

I have no immediate need to use these sensors but can certainly see some in my future so this will be very useful.

I may have to strip it down to the basics for a tiny85 if that's possible (I'll look at the code when the time comes).

Thanks.


Rob

Postman just dropped a notification, my order is waiting at the post office., My DHT11 will be tested this weekend.
Finally, I almost forget that it was on its way...

Cheers,
Kari

OK!

Get the package from post office, and just for curiosity ( http://arduino.cc/forum/index.php/topic,58585.0.html ) I had to check this component.
And it has four pins, no marking for nro 1 or any other.

Datasheet is not helping either, it shows similar component, and I have a problem with reading through all that text, how to identify pin nro 1.
Any tips? Thanks!

Cheers,
Kari

EDIT. Find it! And it works. I'm in a hurry until tomorrow, so I just tested it with the first code found...

DHT11_pins.jpg

Hi,

This is the good pinout for DHTxx components (which is strangely not written in the datasheet ...)

See ya !

Rob, Thanks for the great work on this (and other things) .... Now I can really try mine out !! (I read your code and you do good work.. real return codes!)..

BTW (Disclaimer) I have both types available in my online shop:
http://arduino-direct.com/sunshop/

I'm looking at sourcing other air environment sensors, and any suggestions would be appreciated...

Adder: Rob, may I use your Playground notes in my Wiki?? I'm trying to help users get many different input and output devices working on Arduino:
http://arduino-info.wikispaces.com/

Hi Terry,

Thanks for all complements, part of the kudos need to go to Simkard as he is the one who tested my code and gave me needed feedback. As you can see on the playground article there are still a few things needed to be tested - esp negative temperatures for the DHT22 - and I'm considdering to give both temp and humidity the value -500 or so if there is a problem reading the sensor. Now they keep the last value, so if someone doesn't check the return value of the read function (s)he might assume that the reading was OK as there is a valid looking temp/hum.

Good to know you have those sensors in your shop. The URL doesn't work for me (but I'll find them anyway)

It's OK to make a copy of the playground article, but please put a reference in it to the playground (I can do that in the code => good idea, thanks, welcome) as I will update only the playground article.

robtillaart:
...
It's OK to make a copy of the playground article, but please put a reference in it to the playground.

OK, I'll only copy the overview for people starting out with this. The details and examples and updates will be seen through the Playground link.

I'd like to end up with something like this I did for the DS18B20 : http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20

Here's my first pass: http://arduino-info.wikispaces.com/TemperatureHumidity PLEASE critique / comment!!

Thanks!

I've updated the article so that the lib will include a reference to the playground.

Rob, I don't see your combination library here: Arduino Playground - InterfacingWithHardware

...and there's a confusing mix of stuff there. (Can we just say your's is the best ?? 8) )

Its under Humidity

  • DHT_lib One library that supports both DHT11 and DHT 22 <<<<<<<<<<<<<<<<<< that one

This is the direct URL - Arduino Playground - DHTLib

Don't know if mine is the best, best is a subjective term at best (oops recursion) and it allways depends on the project context what is the best match.

Ustedes usan la linea de datos conectada directamente a un puerto?. And not use a resistor entre la linea de datos y Vcc.

Ustedes usan la linea de datos conectada directamente a un puerto?. And not use a resistor entre la linea de datos y Vcc.
You use the data line connected directly to a port?. And not use a resistor between the Vcc and data line.

No I did not use a resistor between the data line and the Vcc. But in my project the lines were very short. If your lines are longer you could try a 4K7 resistor (similar to I2C).

Regards,
Rob
Translation by Google translate


No, no hizo uso de una resistencia entre la línea de datos y la Vcc. Pero en mi proyecto de las líneas eran muy cortos. Si las líneas son más largas que podría tratar de una resistencia de 4K7 (similar a I2C).

Saludos,
robar
Traducción de Google Translate

I'm trying to build a simple sensor upload to Pachube. I've been troubleshooting this for awhile, and it seems that the problem is with the DHT22 readings, not with the push to Pachube.
I'm reading the data from the DHT22 correctly:

+++++++++++++++++++++++++++++++++++++++++++++++++
OK, 47.2, 26.0
sync status code <OK == 200> => 200
data count=> 4
,
0,654
1,712
2,1
3,1

That's my serial output.
The line after the "+"s is the checksum and humidity and temperature read from the DHT22. The two lines below that are link messages regarding my connection to Pachube. The final 5 lines deal with the data being sent to Pachube. The first two pieces (0 and 1) of data are analog reads from a light sensor and a motion sensor connected to analog lines. The two items following that (2,3) are the temperature and humidity reads from the DHT22.
I can read the DHT22 in the first portion of my code. I cannot read them in the second portion of my code. Why?
I've tried various methods of placing the initial DHT22 data into variables, and printing those variables. Inevitably the serial monitor prints out a "1" when it is trying to send the data feed to Pachube.

Am I wrong? Am I attacking this the wrong way, and instead should be looking at the Pachube end of things?

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
*  Sensors:  DHT22 dataline connected to pin 7.  Suggested 4.7k Pull-up used
              Analog Pin 0 is a photocell to detect light levels
              Analog Pin 1 is a motion sensor

* Based on code:
* Created 22 April 2011
* By Jeffrey Sun
* http://code.google.com/p/pachubelibrary/
* and 
* robtillart
* http://arduino.cc/forum/index.php/topic,58531.0.html
* http://arduino.cc/playground/Main/DHTLib

*/
#include <dht.h>
#include "ERxPachube.h"
#include <Ethernet.h>
#include <SPI.h>

dht DHT;
#define DHT22_PIN 7
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x21, 0xE3 };
byte ip[] = { 192, 168, 1, 20   };                  // no DHCP so we set our own IP address

int Temp;
int Humidity;
int OldTemp = Temp;
int OldHumidity = Humidity;

#define PACHUBE_API_KEY				"PACHUBE API KEY" // fill in your API key PACHUBE_API_KEY
#define PACHUBE_FEED_ID				34665 // fill in your feed id

ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);

void PrintDataStream(const ERxPachube& pachube);

void setup() {

	Serial.begin(9600);
	Ethernet.begin(mac, ip);

	dataout.addData(0);
	dataout.addData(1);
	dataout.addData(2);
        dataout.addData(3);
}

void loop() {

	Serial.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
	float fSensorData = 15.23;
        int chk = DHT.read22(DHT22_PIN);
        switch (chk)
        {
          case 0:  Serial.print("OK,\t"); break;
          case -1: Serial.print("Checksum error,\t"); break;
          case -2: Serial.print("Time out error,\t"); break;
          default: Serial.print("Unknown error,\t"); break;
          }
        // DISPLAY DATA
        Temp = (DHT.temperature, 1);
        Humidity = (DHT.humidity, 1);
        //Serial.print(Temp);
        //Serial.print(",\t");
        //Serial.println(Humidity);
        Serial.print(DHT.humidity, 1);
        Serial.print(",\t");
        Serial.println(DHT.temperature, 1);
	dataout.updateData(0, analogRead(0));
	dataout.updateData(1, analogRead(1));
	dataout.updateData(2, (DHT.temperature,1));
        dataout.updateData(3, (DHT.humidity,1));
	int status = dataout.updatePachube();

	Serial.print("sync status code <OK == 200> => ");
	Serial.println(status);

	PrintDataStream(dataout);
        OldTemp = Temp;
        OldHumidity = Humidity;
	delay(30000);
}

void PrintDataStream(const ERxPachube& pachube)
{
	unsigned int count = pachube.countDatastreams();
	Serial.print("data count=> ");
	Serial.println(count);

	Serial.println("<id>,<value>");
	for(unsigned int i = 0; i < count; i++)
	{
		Serial.print(pachube.getIdByIndex(i));
		Serial.print(",");
		Serial.print(pachube.getValueByIndex(i));
		Serial.println();
	}
}

Possibly related, maybe not:
I'm getting a fair number of checksum errors (Approximately 1 in 10). Is there a way to reduce that number? Any suggestions?

Probably your sample frequency is too high, IIRC the datasheet advices 2000 millis between samples.
Can that be the problem?

A quick update:
I started playing around a bit more and fixed the problem. It seems that i needed to drop the comma after the sensor request (dht.temperature) instead of (dht.temperature, 1). I'm not sure why that matters. I'm getting serial prints using the previuos codes.

Sorry, missed a comment in between.

I'm pretty sure I'm sampling every thirty seconds. However, I just realized that my code is getting the data several times in each iteration. I'd think that this would simply get the old values, but perhaps not. I've done some code revisions. I also changed the temperature format to the US standard Fahrenheit, to allow my girlfriend to use the system.

Right now the system is working. I'm still getting checksum errors at about half the rate.

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
*  Sensors:  DHT22 dataline connected to pin 7.  Suggested 4.7k Pull-up used
              Analog Pin 0 is a photocell to detect light levels
              Analog Pin 1 is a motion sensor

* Based on code:
* Created 22 April 2011
* By Jeffrey Sun
* http://code.google.com/p/pachubelibrary/
* and 
* robtillart
* http://arduino.cc/forum/index.php/topic,58531.0.html
* http://arduino.cc/playground/Main/DHTLib

*/
#include <dht.h>
#include "ERxPachube.h"
#include <Ethernet.h>
#include <SPI.h>

dht DHT;
#define DHT22_PIN 7
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x21, 0xE3 };
byte ip[] = { 192, 168, 1, 20   };                  // no DHCP so we set our own IP address

float TempC = (DHT.temperature, 1);
float Humidity =(DHT.humidity, 1);
float TempF;
float OldTemp = TempF;
float OldHumidity = Humidity;

#define PACHUBE_API_KEY				"Your API Key HERE" // fill in your API key PACHUBE_API_KEY
#define PACHUBE_FEED_ID				34665 // fill in your feed id

ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);

void PrintDataStream(const ERxPachube& pachube);

void setup() {

	Serial.begin(9600);
	Ethernet.begin(mac, ip);

	dataout.addData(0);
	dataout.addData(1);
	dataout.addData(2);
        dataout.addData(3);
}

void loop() {

	Serial.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
	float fSensorData = 15.23;
        int chk = DHT.read22(DHT22_PIN);
        switch (chk)
        {
          case 0:  Serial.print("OK,\t"); TempC = (DHT.temperature); Humidity = (DHT.humidity); break;
          case -1: Serial.print("Checksum error,\t"); break;
          case -2: Serial.print("Time out error,\t"); break;
          default: Serial.print("Unknown error,\t"); break;
          }
        // DISPLAY DATA
        //Temp = (DHT.temperature, 1);
        //Humidity = (DHT.humidity, 1);
        //int(Temp);
        //int(Humidity);
        //Serial.print(Temp);
        //Serial.print(",\t");
        //Serial.println(Humidity);
        TempF = float((TempC * float(1.8))+32);
        //Serial.print(DHT.humidity, 1);
        //Serial.print(",\t");
        //Serial.println(TempC);
        //Serial.println(TempF);
        
	dataout.updateData(0, analogRead(0));
	dataout.updateData(1, analogRead(1));
	//dataout.updateData(2, (DHT.temperature,1));
        //dataout.updateData(3, (DHT.humidity,1));
        dataout.updateData(2, TempF);
        dataout.updateData(3, Humidity);
	int status = dataout.updatePachube();

	Serial.print("sync status code <OK == 200> => ");
	Serial.println(status);

	PrintDataStream(dataout);
        OldTemp = TempF;
        OldHumidity = Humidity;
	delay(30000);
}

void PrintDataStream(const ERxPachube& pachube)
{
	unsigned int count = pachube.countDatastreams();
	Serial.print("data count=> ");
	Serial.println(count);

	Serial.println("<id>,<value>");
	for(unsigned int i = 0; i < count; i++)
	{
		Serial.print(pachube.getIdByIndex(i));
		Serial.print(",");
		Serial.print(pachube.getValueByIndex(i));
		Serial.println();
	}
}

The statement "float TempC = (DHT.temperature, 1); " makes little sense,
You copied it from : Serial.println(DHT.temperature, 1); where it means print the float DHT.temperature with one decimal You cannot copy that into an assigment,

Here a patched (& stripped) version of your code, not tried as I don't have the pachube lib and sensor nearby to rebuild your sketch.
Let me know how it works...

#include <dht.h>
#include "ERxPachube.h"
#include <Ethernet.h>
#include <SPI.h>

dht DHT;
#define DHT22_PIN 7
byte mac[] = { 
  0x90, 0xA2, 0xDA, 0x00, 0x21, 0xE3 };
byte ip[] = { 
  192, 168, 1, 20   };                  // no DHCP so we set our own IP address

float TempC = 0;
float Humidity = 0;
float TempF = 0;
float OldTemp = 0;
float OldHumidity = 0;

#define PACHUBE_API_KEY				"Your API Key HERE" // fill in your API key PACHUBE_API_KEY
#define PACHUBE_FEED_ID				34665 // fill in your feed id

ERxPachubeDataOut dataout(PACHUBE_API_KEY, PACHUBE_FEED_ID);

void PrintDataStream(const ERxPachube& pachube);

void setup() 
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);

  dataout.addData(0);
  dataout.addData(1);
  dataout.addData(2);
  dataout.addData(3);
}

void loop() {

  Serial.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
  float fSensorData = 15.23;
  int chk = DHT.read22(DHT22_PIN);
  switch (chk)
  {
  case 0:  
    Serial.print("OK,\t"); 
    TempC = DHT.temperature; 
    Humidity = DHT.humidity; 
    break;
  case -1: 
    Serial.print("Checksum error,\t"); 
    break;
  case -2: 
    Serial.print("Time out error,\t"); 
    break;
  default: 
    Serial.print("Unknown error,\t"); 
    break;
  }
  
  TempF = float((TempC * float(1.8))+32);

  dataout.updateData(0, analogRead(0));
  dataout.updateData(1, analogRead(1));
  dataout.updateData(2, TempF);
  dataout.updateData(3, Humidity);
  
  int status = dataout.updatePachube();

  Serial.print("sync status code <OK == 200> => ");
  Serial.println(status);

  PrintDataStream(dataout);
  OldTemp = TempF;
  OldHumidity = Humidity;
  delay(30000);
}

void PrintDataStream(const ERxPachube& pachube)
{
  unsigned int count = pachube.countDatastreams();
  Serial.print("data count=> ");
  Serial.println(count);

  Serial.println("<id>,<value>");
  for(unsigned int i = 0; i < count; i++)
  {
    Serial.print(pachube.getIdByIndex(i));
    Serial.print(",");
    Serial.print(pachube.getValueByIndex(i));
    Serial.println();
  }
}

robtillaart,
Thank you very much!
I'm in the process of trying to reduce the number of erroneous readings with the DHT22 sensor. It seems that a 1 in 10 error rate is something to actually shoot for. Some of my test runs are scoring an error rate of closer to 4 in 10 or higher.

Has anyone had any success reducing the error rate with this sensor? I've placed the filter capacitor across the power and ground pins, but that didn't seem to have much of an effect.