What you will learn
- Connect a DHT11 module rated for 3.3 V to GPIO26 with an external 10 kΩ pull-up to 3V3.
- Install DHT sensor library by Adafruit and Adafruit Unified Sensor at the specified versions.
- Schedule reading attempts every 2500 ms, starting after the initial interval.
- Display temperature in °C and relative humidity as a percentage with clear unit labels.
- Check both readings with isnan() and distinguish missing data from a numerical zero.
Before you start
Complete courses 01 and 07: uploading sketches, using Serial Monitor and connecting sensor module power with a common ground.
Reference setup
- Board in Arduino IDE
- ESP32 Dev Module
- Arduino-ESP32
- 3.3.12
- Serial Monitor
- 115200 baud
This is a reference profile, not an identification of the pictured board. Adapt the GPIO mapping and verify the circuit before using ESP32-C3/S2/S3 or a differently labelled board.
What we will build
We will connect a DHT11 to the ESP32 and display air temperature and relative humidity in Serial Monitor. The program attempts a new reading every 2.5 seconds. A successful result includes both values and their units; an unsuccessful result produces a clear error message.
We will learn to handle numerical sensor data and unavailable measurements with equal care.
What you will learn
- Connect the power supply, DATA line and external pull-up resistor.
- Install the correct Arduino library and its dependency.
- Read temperature in °C and relative humidity as a percentage.
- Schedule readings with
millis(). - Recognise
NaNand report an error without inventing a zero value.
Prerequisites
Complete courses 01 and 07: sketch uploads, Serial Monitor and module power with common ground. We now move from a binary sensor output to a library for its data protocol.
Required equipment
| Component | Quantity | Specification and notes |
|---|---|---|
| Development board with a classic ESP32-WROOM-32 module | 1 | Match the reference GPIO labels; check physical header positions on the actual board. |
| USB data and power cable | 1 | Use the connector fitted to your board; the pictured kit lists Micro-USB. |
| Solderless breadboard | 1 | The kit lists 830 tie points. Check whether the power rails are split. |
| DHT11 temperature and relative humidity module | 1 | Three-terminal VCC/GND/DATA module verified for 3.3 V; DATA pull-up only to 3V3. Some variants are unreliable at 3.3 V. |
| 10 kΩ resistor | 1 | R2: DATA pull-up to 3V3. The quantity per resistance value in the kit is unconfirmed. |
| Jumper wires | 5 | Use male-to-male or female-to-male leads to suit the board headers. Approximate quantity, depending on layout and connector types. |
Use a classic ESP32-WROOM-32 and a three-terminal DHT11 module confirmed to work at 3.3 V. Check the physical order of VCC, DATA and GND. A bare four-pin DHT11 has a different pin arrangement; do not substitute it based on this diagram's appearance.
Understanding the measurements
Temperature describes thermal conditions around the sensor. Relative humidity also depends on temperature; its percentage is not the percentage of air volume occupied by water. The DHT11 is useful for learning to acquire measurements, but displaying a decimal place does not establish that level of accuracy. The Adafruit DHT overview describes its limitations.
The DHT11 uses a digital protocol on one DATA line. This is neither an analogue output nor I²C. The library handles signal timing, decodes data and checks the transmission. The Adafruit library implementation shows its timing, checksum and failed-reading handling.
Wiring and assembly
Wiring diagram
Use a three-terminal DHT11 module verified for 3.3 V operation. R2 is an additional 10 kΩ pull-up to 3V3; DATA and GPIO26 share one node. Do not move a module with an onboard pull-up to 5 V without adapting the logic levels.
| From | To | Connection |
|---|---|---|
ESP32.3V3 | DHT1.VCC | Use a DHT11 module that operates reliably at 3.3 V. |
ESP32.GND | DHT1.GND | Common ground. |
DHT1.DATA | ESP32.GPIO26 | Bidirectional DHT11 data line. |
ESP32.3V3 | R2.1 | R2 is a 10 kΩ pull-up to 3V3. |
R2.2 | DHT1.DATA | Connect the other end of R2 to the DATA/GPIO26 node. |
- Disconnect USB. Verify that your exact module's documentation permits a 3.3 V supply.
- Connect module VCC to 3V3 and module GND to ESP32 GND.
- Connect DATA to GPIO26.
- Add R2, 10 kΩ between DATA and 3V3. It is not in series with the signal wire: one end joins the DATA/GPIO26 connection and the other joins 3V3.
- If the module already has a pull-up, confirm that it also connects to 3.3 V. Our reference circuit retains the external R2 to make this connection explicit.
- Inspect the short wires and terminals, then power the board through USB.
A pull-up returns the data line to a high level when communicating devices are not pulling it towards ground. The Adafruit wiring guide specifies a 10 kΩ resistor and notes that 3.3 V is insufficient for some units. If your module is unreliable at 3.3 V, verify its variant; do not simply power it at 5 V, because an onboard pull-up could then apply 5 V to GPIO26.
Arduino setup
In Arduino IDE 2.x, select ESP32 Dev Module, the correct port and esp32 by Espressif Systems 3.3.12. In Library Manager, install:
- DHT sensor library by Adafruit, version 1.4.7.
- Adafruit Unified Sensor, version 1.1.15, as the package dependency.
Check the author: similarly named libraries can expose different APIs. See the Adafruit Arduino guide. Our sketch uses DHT without the Unified API layer, but we install its declared dependency.
Extract the example, open dht11_monitor/dht11_monitor.ino and keep the matching folder name. Set Serial Monitor to 115200 baud.
| Library and release | Version | Dependencies |
|---|---|---|
| DHT sensor library | 1.4.7 | Adafruit Unified Sensor 1.1.15 |
| Adafruit Unified Sensor | 1.1.15 | None |
Complete Arduino sketch
#include <Arduino.h>
#include <DHT.h>
#include <math.h>
constexpr uint8_t DHT_PIN = 26;
constexpr uint32_t SAMPLE_MS = 2500;
DHT dht(DHT_PIN, DHT11);
uint32_t lastSampleAt = 0;
void setup() {
Serial.begin(115200);
dht.begin();
lastSampleAt = millis();
Serial.println("DHT11: first sample after 2.5 seconds; units are Celsius and percent RH.");
}
void loop() {
const uint32_t now = millis();
if (static_cast<uint32_t>(now - lastSampleAt) < SAMPLE_MS) return;
lastSampleAt = now;
const float humidity = dht.readHumidity();
const float temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("SENSOR ERROR: DHT11 read failed; check DATA, 3.3 V, GND and pull-up.");
return;
}
Serial.print("T_C="); Serial.print(temperature, 1);
Serial.print(" RH_pct="); Serial.println(humidity, 1);
}
Run the supplied sketch unchanged first. It uses DHT_PIN = 26, sensor type DHT11 and SAMPLE_MS = 2500.
Reading one sample
The object DHT dht(DHT_PIN, DHT11) associates the selected pin with the sensor type. dht.begin() prepares communication. The program stores lastSampleAt and makes its first attempt only after 2500 ms have passed from the schedule's starting point in setup().
Calls to readHumidity() and readTemperature() return humidity and temperature. Temperature defaults to Celsius. For consecutive calls, the library reuses the stored result of the same communication, so this pair should not be interpreted as two independent measurements at the same instant. Our chosen interval exceeds the library's internal two-second minimum.
Before printing, the program applies isnan() to both values. If either is invalid, it rejects the entire pair and reports SENSOR ERROR. Zero is a possible numerical value; it must not represent a failed transmission. The program continues and tries again at the next scheduled interval.
Running and interpreting the output
Click Verify, then Upload. Open Serial Monitor and wait for the first attempt. Successful messages use T_C and RH_pct; errors are labelled separately. Readings depend on your room, placement and sensor; no number here represents your experiment's actual outcome.
Do not expect every sample to change. Keep the sensor away from the warm ESP32 board, direct sunlight and contact with your fingers. Allow it time to respond to changed conditions. This arrangement is an indoor learning exercise; its enclosure and measurement setup are not prepared for outdoor weather exposure.
Experiment and observation log
Record ten consecutive attempts. For each, write down the message time, temperature, relative humidity and status. Leave the measurement fields blank when an error occurs.
| Situation | Expected behaviour | Observe |
|---|---|---|
| Successful reading | Both values are displayed. | Units and message interval. |
| Stable room | Several results may be identical. | Repetition alone is not an error. |
| Sensor moved away from a warm board | A gradual change is possible. | Allow settling before comparison. |
| DATA disconnected before power-on | An error appears at each attempt. | No replacement zeros. |
For the final experiment, disconnect USB, remove the DATA connection, reconnect power and observe. Disconnect USB again before restoring the wire.
Troubleshooting
| Symptom | Check and action |
|---|---|
DHT.h cannot be found | Install the DHT library published by Adafruit. |
Continuous SENSOR ERROR | Check DATA/GPIO26, GND, DHT11 type, R2 and the module's supported supply. |
| Occasional errors | Secure and shorten wires; restore the 2500 ms interval and check power. |
| Unreadable messages | Select 115200 baud and the correct serial port. |
| Temperature appears too high | Move the sensor away from heat sources; comparison requires similar placement and settling time. |
Independent challenge
Increase SAMPLE_MS to 5000 and observe the message interval. Then work through these fictional temperatures on paper: 22.0; invalid; 24.0. Calculate the mean of valid readings and compare it with the incorrect mean obtained by replacing the error with zero.
Check your understanding
- Why does R2 connect to 3V3 rather than 5 V?
- Does a communication error mean that the temperature is 0 °C?
- Would more frequent printing make the DHT11 more accurate?
Worked guidance and answers
With an interval of 5000 ms, new attempts occur approximately every five seconds. The mean of valid readings 22.0 and 24.0 is 23.0 °C. Including an invented zero would produce approximately 15.3 °C and hide the missing data. This calculation is an exercise, not a measurement made on a board.
Pulling up to 3V3 maintains an appropriate DATA high level. NaN represents an invalid number, not a zero temperature. A higher printing rate cannot improve the sensor's measurement characteristics. Restore the interval to 2500 ms before the indoor station course.
