25. DHT11 / DHT22 Temperature & Humidity
Read temperature and humidity from a DHT11 or DHT22 with the Adafruit library, and reject failed readings with isnan().
Learning outcomes
- Explain what temperature and relative humidity the DHT reports
- Compare DHT11 and DHT22 specs and constructor types
- Wire a bare sensor (with pull-up) or a 3-pin module
- Read with the Adafruit DHT library and reject failed readings with isnan
Parts and preparation
Uno, DHT11 or DHT22 sensor/module, 4.7-10 k ohm pull-up for a bare sensor and jumpers. Install both Adafruit libraries listed in the Libraries box.
Before power: inspect wiring, confirm supply voltage and ensure all connected circuits share GND.
Libraries for this lesson
In Arduino IDE 2 open Tools → Manage Libraries…. Search by the Library Manager name and install the package by the exact author below. Similar names from other authors can use different APIs and will break the example.
| Include | Library Manager name | Author | Install note |
|---|---|---|---|
DHT.h | DHT sensor library | Adafruit | Install via Library Manager. |
(dependency) | Adafruit Unified Sensor | Adafruit | Required dependency of the DHT sensor library. Install via Library Manager if prompted or if compile fails. |
What a DHT reports
A DHT family sensor measures air temperature (C) and relative humidity (%RH). It is a digital single-wire device: VCC, DATA and GND (plus NC on many bare 4-pin packages). It is not an analogue ADC sensor and not an I2C device.
Inside the package, sensing elements and a small controller exchange a timed bit protocol on DATA. Use a library for the first practical - hand-timing that protocol is easy to get wrong.
DHT11 vs DHT22
DHT11 is the cheap course default: modest range and coarse steps (about 1 C and 1 %RH). DHT22 (also sold as AM2302) covers a wider range with finer resolution and better accuracy, at higher cost.
Wiring is the same idea for both. The Adafruit constructor type must match the part you fitted: DHT11 or DHT22. A mismatch often produces failed reads or nonsense values.
| Item | DHT11 | DHT22 |
|---|---|---|
| Constructor | DHT11 | DHT22 |
| Typical use | Learning / rough checks | Better accuracy projects |
| Resolution | Coarse | Finer |
| Read interval | About 2 s or slower | About 2 s or slower |
Bare sensor vs module wiring
A common bare 4-pin DHT, viewed from the front grill, is often VCC, DATA, NC, GND left to right. Pin 3 is not connected. You must add a 4.7-10 k ohm pull-up from DATA to VCC.
Many 3-pin modules already include the pull-up and label VCC / DATA / GND on the silkscreen. Pin order is not universal - always check the board text before powering.
| Connection | Course practice |
|---|---|
| VCC | 5 V |
| DATA | D2 |
| GND | Uno GND |
| Bare pull-up | 4.7-10 k ohm DATA to VCC |
| Bare pin 3 | NC - leave open |
Sampling interval
DHT sensors need recovery time between readings. Reading much faster than about once every two seconds often returns failed or stale data. The worked sketch uses delay(2000) before each read.
Libraries and isnan
Install DHT sensor library by Adafruit and the Adafruit Unified Sensor dependency. Call dht.begin() in setup, then readHumidity() and readTemperature() in loop.
A failed read returns NaN (not a number). Always check isnan on both values before printing, logging or driving an LCD. The extension challenge is to keep the previous LCD values when a read fails.
#include <DHT.h>
const byte dhtPin = 2;
DHT dht(dhtPin, DHT11); // use DHT22 if that is the part fitted
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
delay(2000);
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("DHT read failed");
return;
}
Serial.print(t, 1);
Serial.print(" C ");
Serial.print(h, 1);
Serial.println(" %RH");
}Wiring and safe build sequence

- VCC -> 5 V
- GND -> GND
- DATA -> D2
- Bare sensor: 4.7-10 k ohm from DATA to VCC
- Pin 3 of a common bare four-pin package is not connected
Worked sketch
Download .ino#include <DHT.h>
const byte dhtPin = 2;
DHT dht(dhtPin, DHT11); // use DHT22 if that is the part fitted
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
delay(2000);
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("DHT read failed");
return;
}
Serial.print(temperature, 1);
Serial.print(" C ");
Serial.print(humidity, 1);
Serial.println(" %RH");
}How the code works
- isnan detects the library's failed floating-point reading.
- The two-second delay respects sensor timing.
- Change DHT11 to DHT22 in the constructor when you fit a DHT22 / AM2302.
Test and record evidence
Practical evidence checklist
Common faults and checks
- Verify sensor orientation and module pin labels.
- Install both required Adafruit libraries.
- Add/check the data pull-up for a bare sensor.
- Confirm the constructor type matches DHT11 or DHT22.
- Slow the loop if reads fail when polled too quickly.
Check your understanding
Q1. Why check isnan?
Show answer
A failed DHT read returns a not-a-number value.
Q2. How frequently should a DHT11 be read?
Show answer
About once every two seconds or slower.
Q3. What must you change in code when swapping DHT11 for DHT22?
Show answer
The type constant in the DHT constructor (DHT22).
Q4. Why does a bare DHT need a pull-up on DATA?
Show answer
DATA is an open single-wire line; without a pull-up the level is undefined when idle.
Optional: practise in your browser
Write and test this lesson's code on a virtual Uno. Work through the 4 exercises in order. Press Test and each one checks itself. This practice is optional - do it if you have time.
Optional practice: a DHT11 on the virtual Uno
This practice is optional. Do it if you have time, or to revise before the environment monitor. Nothing in class depends on it.
The virtual board has a DHT11 wired to D2, just like the lesson. While a sketch runs you can:
- drag the Temperature and Humidity sliders - the air around the sensor changes
- tick Sensor fault - that is the data wire coming loose, so every reading fails and comes back as
NaN(not a number)
Three things behave exactly like the Adafruit library on a real board. A DHT11 reports whole numbers, so 21.6 °C reads as 22.0. A reading within 2 seconds of the last one just repeats the last values - which is why the sketches wait 2 s between reads. And dht.begin() must run in setup() first, or every read fails.
What the simulator does not model: the DHT11's own error (about ±2 °C and ±5 %RH), how slowly a real sensor follows a change of air, and the pull-up resistor a bare sensor needs. Those are what the bench is for.
The lesson's sketch
Press Run, then move the sliders and tick Sensor fault. Watch how long it takes for each change to reach the Serial Monitor.
22.0 C 50.0 %RH 22.0 C 50.0 %RH 22.0 C 50.0 %RH
return;insideloop()ends this pass early - the next pass starts with the nextdelay(2000).- A change can take up to 2 s to show, because the sketch only asks every 2 s. That is fine for room air.
Read the temperature
Everything is set up. In loop(), read the temperature into a float and print it like this, every 2 seconds:
Temperature: 22.0 C
Print the number with 1 decimal place. The test warms the air to 26 °C after 3 seconds, so the second line should change.
Temperature: 22.0 C Temperature: 26.0 C
Temperature and humidity on one line
Add the humidity. Each line should read like the lesson's sketch:
22.0 C 50.0 %RH
Read it with dht.readHumidity() and print it with 1 decimal place. The test makes the air damper (65 %) after 3 seconds.
22.0 C 50.0 %RH 22.0 C 65.0 %RH
Catch a failed reading
This sketch prints whatever the sensor gives it - so when the data wire comes loose it prints nan C nan %RH. Press Run and tick Sensor fault to see it.
Change it so that when either reading failed it prints Sensor error instead of the numbers. isnan(value) is true when a value is NaN. The test unplugs the sensor between 3 and 5 seconds.
22.0 C 50.0 %RH Sensor error 22.0 C 50.0 %RH
Too hot or broken: the alarm goes on
The alarm LED on D8 must be on when the temperature is 30 °C or more, and off otherwise.
There is a catch. Every comparison with NaN is false, so temperature >= TOO_HOT on its own leaves the alarm off when the sensor is unplugged - a broken monitor that says all is well. The course rule is fail safe: a sensor fault switches the alarm on. It is the same rule Practical Task B marks.
The test warms the air to 32 °C, cools it to 24 °C, then unplugs the sensor.
Try it on a real Uno
Wire the DHT11 as in Lesson 25 - DATA to D2, and a 4.7-10 kΩ pull-up if it is a bare sensor - and upload Catch a failed reading. Breathe on the sensor: humidity jumps within a few seconds, temperature creeps up much more slowly. Then pull the data wire out and check you get Sensor error, not a number.
Too hot or broken is the heart of the alarm in Lesson 27, so it is worth having in your fingers before you start that build.
Want more? Code Along chapter 17 has a Deeper exercise that goes further than this lesson. It is optional.