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

int chk = DHT.read22(DHT22_PIN);

The read22() call tries to read data from the sensor and fills the variables DHT.temperature and DHT.humidity. The return value tells if something went wrong during that "exercise". Some people work with the "good weather" scenario and leave out all the checks, that's a design choice.

When I'm asking the sensor for the current humidity and temperature, are those two different requests?

NO, if you do a read22() both temperature and humidity are read. They can be obtained by reading the members DHT.temperature and DHT.humidity

Or does the
int chk = DHT.read22(DHT22_PIN);
request call all the sensor information, and load it into the Arduino memory, waiting for the DHT.temperature and DHT.humidity calls?

Yes, if you dive into the code of the library (don't be afraid :wink: , you see that temp and humidity are both filled in the read22() call.

MY errorrate with this sensor was definitely lower, no figures at hand.

I've posted on the retailer's website. I'll let you folks know what develops.
Thanks again!

Hi Terry, i´m new with Arduino and my first project is building a temperature-regulator. just i see your project and take parts from your code, but i can not see negative values on my display. have you got an idea, which part i must change? Sorry, i´m newbie and my english is not the best, but i hope, you or everyone can help...

thank you

olli

/*
Basierend auf einen Artikel auf dieser Seite:
http://arduino-info.wikispaces.com/PROJECT-Temp-Humidity-Display

den aktuellen Stand findest Du hier:
http://alturl.com/rpods
*/
 
/*-----( Import needed libraries )-----*/
#include <dht11.h>
#include <Wire.h>
#include <LiquidCrystal.h>
/*-----( Declare objects )-----*/
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //##### DFRobot LCD Keypadshield V1.0
 // legt die pins auf dem shield fest

/* begin des tastatur-bereichs */
int lcd_key = 0; // legt nutzung der tasten fest und dann die tasten selber
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
/* ab hier: einlesen der werte der tasten (wiederstands gebilde mit
unterschiedlichen spannungswerten zu jeder taste...*/

int read_LCD_buttons()
 {
 adc_key_in = analogRead(0); // read the value from the sensor 
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons
since it will be the most likely result
 if (adc_key_in < 50) return btnRIGHT; 
 if (adc_key_in < 195) return btnUP; 
 if (adc_key_in < 380) return btnDOWN; 
 if (adc_key_in < 555) return btnLEFT; 
 if (adc_key_in < 790) return btnSELECT; 
 return btnNONE; // when all others fail, return this...
 }
/* das wars mit dem tastatur-bereich */

dht11 DHT11;
/*-----( Declare Constants, Pin Numbers )-----*/
#define DHT11PIN 2

float alarmwert (20);
 
void setup() /*----( SETUP: RUNS ONCE )----*/
{
 Serial.begin(9600); 
 lcd.begin(16,2); //##### Display Size for DFRobot LCD Keypadshield V1.0
 lcd.home ();
 lcd.println ("Olliduino "); //##### schreibe willkommensnachricht und springe eine zeile weiter
 lcd.setCursor (0,1);
 lcd.print ("2011 by olli "); //##### schreibe willkommensnachricht
 lcd.home ();
 delay(3000);
 lcd.clear ();
 
}/*--(end setup )---*/
  

void loop() /*----( LOOP: RUNS CONSTANTLY )----*/
{

 // digitalWrite(13, HIGH);

 
 int chk = DHT11.read(DHT11PIN);
 
 Serial.println("---------------------------"); //der Lesbarkeit erstmal eine Zeile
 switch (chk) // teste, ob ueberhaupt daten fliessen
 {
 case 0: Serial.println("DHT11 ist OK");
 Serial.print ("gelieferter Wert: ");
 Serial.println ((float)DHT11.temperature,1); 
 break;
 case -1: Serial.println("Checksum error"); break;
 case -2: Serial.println("Time out error"); break;
 default: Serial.println("Unknown error"); break;
 }
Serial.print((float)alarmwert, 1);
 Serial.println("C Darunter-Gibt-es-ALARM-Temperatur");
 Serial.print((float)DHT11.temperature,1);
 Serial.println("C IST-Temperatur");
if ( DHT11.temperature < alarmwert ) 
 { 
 digitalWrite(13, HIGH);
 Serial.println("### !!! Alarm erreicht !!! ###"); 
 lcd.setCursor (15,0); //##### schreibe ab zeichen 14 in zeile 1 (zeile 1 ist gleich 0)
 lcd.print("!");
 lcd.setCursor (0,1);
 }
else
 {
 digitalWrite(13, LOW);
 Serial.println("Alarm nicht erreicht, alles OK");
 lcd.setCursor (15,0); //##### schreibe ab zeichen 14 in zeile 1 (zeile 1 ist gleich 0)
 lcd.print("*");
 lcd.setCursor (0,1);
 }

 
 //lcd.noAutoscroll();
 lcd.setCursor (0,1);
 lcd.print(alarmwert,0);
 lcd.print("Cs ");
 lcd.print((float)DHT11.temperature,1);
 lcd.print("Ci ");
 lcd.print((float)DHT11.humidity,1);
 lcd.print("%");

 digitalWrite(13, LOW);
 
 delay(1000);
 
 
 
 
 // jetzt lesen wir noch die tasten ein und machen was draus
 
 lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
 {
 case btnRIGHT:
 {
 lcd.setCursor (0,0);
 lcd.print("> ");
 break;
 }
 case btnLEFT:
 {
 lcd.setCursor (0,0);
 lcd.print("<");
 break;
 }
 case btnUP:
 {
 alarmwert = alarmwert + 1;
 lcd.setCursor (0,0);
 lcd.print("^");
 break;
 }
 case btnDOWN:
 {
 alarmwert = alarmwert - 1;
 lcd.setCursor (0,0);
 lcd.print("v");
 break;
 }
 case btnSELECT:
 {
 lcd.setCursor (0,0);
 lcd.print("*");
 break;
 }
 case btnNONE:
 {
 lcd.setCursor (0,0);
 lcd.print(" ");
 break;
 }
 } 
 
 
 
 
 
 
 
 
 
 
}
/* --(end main loop )-- */

updated the code to support Arduino 1.0 - as allways comments still welcome

Hi Rob,
Thank you so much for writing such an easy to use library!
I wanted to ask you a question if I may -
I'm using the DHT-11,
I tried supplying it with different voltages (3V, 3.3V, 5V - using the
Arduino Uno's 3V,5V and the Arduino Fio's 3.3V power supply)
and for each voltage there are different readings for the temperature and humidity (a
very big difference between 3V and 5V).
what is the correct voltage that it should be supplied with?
(or is there a way to work around this?)
according to the datasheet it can be supplied with 3V - 5.5V.

thanks!

I wanted to ask you a question if I may -

you may,

I tried supplying it with different voltages (3V, 3.3V, 5V - using the
Arduino Uno's 3V,5V and the Arduino Fio's 3.3V power supply)
and for each voltage there are different readings for the temperature and humidity (a
very big difference between 3V and 5V).
what is the correct voltage that it should be supplied with?Ac

As you say according to the datasheet, any voltage between 3 and 5.5V should work. I only can confirm that the readings makes good sense at 5Volt.

(or is there a way to work around this?)

External powersupply for the sensor? does also make sense if the sensor is a bit further away, long wires.

If you use 3.5 volt and you take longer delays between the readings, does the accuracy of the reading increase?

I just wanted to say THANK YOU for all of the work! I just received a Freetronics Eleven and the DHT22 sensor. I tried the Library suggested, but just kept getting error during the compile process. And then I found your tutorial!!! Although it took me a bit to figure out how to create the Library from your work, once I did, everything started working. Now I am trying to figure out how to combine the Dew Point and C to F conversion from the DHT11 sketch with the DHT22 sketch so I can have the most information from just the one sketch.

Thanks again,

Hi all,
At first I want to thank you for the library. Very nice and succint.

However, I noticed that in about 50% of all cases I'm getting a checksum error. This happens both, using 3.3V or 5V power supply.
Does anyone now whether this is a hardware problem (low cost sensor?) or a timing problem while retrieving the data from the sensor?
I read that someone else also had this problem. Any solution? Typical situation :

DHT22, Checksum error, 48.7, 1665.4
DHT22, Checksum error, 48.7, 1665.4
DHT22, Checksum error, 48.1, 846.2
DHT22, Checksum error, 48.1, 846.2
DHT22, OK, 48.5, 27.0
DHT22, Checksum error, 48.4, 846.2
DHT22, OK, 48.5, 27.0
DHT22, Checksum error, 48.4, 846.2
DHT22, OK, 48.5, 27.0
DHT22, OK, 48.3, 27.0

Thanks for any help!

Any solution?

You might need a pull up resistor (eg 4K) between +5V and the dataline.

How long is the line between the arduino and the sensor?

Rob

updated the code to 0.1.03;

  • added code to reflect faulty reading in temperature (-999) and humidity (-999) if there is a timeout. So if a sketch does not test the return value of read11() or read22() you will still see it clearly.

As allways comments still welcome

One suggestion for the code is to replace or augment the read11 and read22 routines by one unique read routine that would detect which one it is and return 11 or 22 in chk.

I'm not sure it is so easy, but for example, having both [2] and [4] zero with a DHT22 should almost never happen, right ?

They are the lsB if I get it right, so humidity has to be 25.6, 51.2 or 76.8 for byte[4] to be zero.
Then in that case temperature has to be precisely 25.6 etc.
Pretty unusual.

To be even more confident, there could be a "confidence" variable based on previous measurements:
increase/decrease a uint8_t counter for every non/zero value with saturation @ +127/-128, so DHT11 goes from zero @reset to -128 and DHT22 to +127.

Another thing is to replace the double by an int in tenths of degrees. So for DHT11 it would return array[0]*10;

One suggestion for the code is to replace or augment the read11 and read22 routines by one unique read routine that would detect which one it is and return 11 or 22 in chk

Don't mix error state with configuration information. That said, one could make a function int determine() that does just that. Typically it is called just once and remembered - you just needs one byte to keep the 11/22 flag of 8 sensors.

I'm not sure it is so easy, but for example, having both [2] and [4] zero with a DHT22 should almost never happen, right ?

possible but one could only account readings for which [2] and [4] are zero AND the checksum is OK.

Assuming a valid reading, both numbers have one decimal place 0..9 =>10 possible values. This implies that the chance would be about one in hundred for an individual reading to have two 0's as decimal. That is a small chance but too big imho to make a reliable determine() function, it is definitely not deterministic. Multiple readings with will improve this number but as the device needs 2 seconds between readings so determine() function becomes quite time consuming.

Note that especially for the DHT11 one can use a (running) average to get a higher precision - and thus decimal places ).

Hi robtllaart

robtillaart:
updated the code to 0.1.03;

  • added code to reflect faulty reading in temperature (-999) and humidity (-999) if there is a timeout. So if a sketch does not test the return value of read11() or read22() you will still see it clearly.

As allways comments still welcome

I would change the follow code in read22() and read11() functions from

int rv = read(pin);
        if (rv != 0) 
    {

to

int rv = read(pin);
        if (rv != DHTLIB_OK) 
    {

No functionally change but improves readability.

That is very keen eye! I will change it asap

Thanks,
Rob

updated on the playground to version 0.1.04

  • added the rv != DHTLIB_OK as suggested by jrbenito (thanks)
  • added #define DHTLIB_INVALID_VALUE -999 to remove that magic number from the lib too.

Rob

robtillaart:

  • added #define DHTLIB_INVALID_VALUE -999 to remove that magic number from the lib too.

Rob

Wow! Very good too.

Thanks for this code and best regards,
Benito.

Hi,

Nice library. However, it does not work correctly for negative temperatures. I'm using version 0.1.04. When a negative temperature is measured the class will return DHTLIB_ERROR_CHECKSUM. The problem is at line 74 in dht.cpp. Here bits[2] is modified, which makes the checksum calculation incorrect. There are, of course, many ways to fix the problem. I have fixed it by changing the code in the following way.

Old Code:

        int sign = 1;
        if (bits[2] & 0x80) // negative temperature
        {
                bits[2] = bits[2] & 0x7F;
                sign = -1;
        }
        temperature = sign * word(bits[2], bits[3]) * 0.1;

New Code:

        if (bits[2] & 0x80) // negative temperature
        {
                temperature = word(bits[2]&0x7F, bits[3]) * 0.1;
                temperature = -1.0 * temperature;
        }
        else
        {
                temperature = word(bits[2], bits[3]) * 0.1;
        }

Thanks for the library, and with this fix it is just perfect for me!

Thanks for this feedback, I'll fix it a.s.a.p.

updated the playground article to include the patch above.

Thanks again!

No idea why someone wants to write code if there already exists a perfectly fine library... but... I just checked in a DHT library with the following features:

  • Support for DHT11 and DHT22, AM2302, RHT03
  • Auto detect sensor model
  • Very low memory footprint
  • Very small code

Maybe useful for someone - feel free to report bugs.