This one is about the wire, not the chip. Nothing below changes with the board you picked, which is why the chip and language switches are not on it. They come back on the ESP32 pages this one sits underneath.
One-wire sensor timing
A DHT11 or DHT22 sends forty bits down a single data wire, and the value of each bit is how long the line stays high — twenty-six microseconds for a zero, seventy for a one. There is no clock, no address and no error reporting, which is why this sensor is both the easiest to wire and the fussiest to read.
Step through the exchange. Every step is the same wire, changing hands.
One wire, two owners
The line idles high, held there by a pull-up resistor — usually already on the module. Your pin is an input, doing nothing.
To ask for a reading you make the pin an output and pull the line low for a millisecond or more. Then you let go, switch back to input, and from that moment the sensor is driving the same wire. It answers with a low, then a high, then forty bits, then releases the line and goes quiet for at least two seconds.
Nothing in that sequence is negotiated. Both ends simply agree, in advance, what the timings mean. That is what makes it cheap and what makes it brittle.
The bit is the pulse width
Every data bit starts with a 50 µs low that carries no information at all. What follows is either a short high (26–28 µs) or a long one (70 µs). Your code times that high pulse and compares it with about 50 µs. That comparison is the entire decoder.
Why this is fragile. Fifty microseconds is roughly four hundred instructions on an ESP32. If anything interrupts you mid-bit — Wi-Fi, a timer, another library — your measurement is long, the bit flips, and the reading is wrong. The five-byte checksum catches it and your library reports a failed read, which is the "sometimes it returns NaN" everybody meets.
What actually goes wrong
Reading too often. A DHT22 needs two seconds between reads, a DHT11 one. Ask sooner and it returns the previous sample or nothing at all.
No pull-up. Bare sensors need a 4.7 kΩ or 10 kΩ resistor from data to 3V3. Most modules already have one; a three-pin board almost certainly does, a four-pin bare sensor does not.
Long wires. Beyond about 20 cm the edges soften and the pulse widths blur. This protocol has no error correction, only detection — you find out by getting nothing.
Sharing the pin. One sensor per pin. There is no address, so two DHTs on one wire both answer at once and neither can be understood.
Use the library
#include <DHT.h>
#define DHTPIN 4
DHT dht(DHTPIN, DHT22);
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) Serial.println("bad read"); // expect a few
else Serial.printf("%.1f C %.1f %%\n", t, h);
delay(2000); // the minimum
}Timing this by hand is a good exercise and a bad plan: the library already
disables interrupts around the critical section and retries. Checking for nan
is not optional — a few failed reads per hundred is normal, not a fault.
The name collision
This is not the same thing as 1-Wire with a capital W. Dallas 1-Wire is a real bus with 64-bit addresses and many devices on one line, and it is the next page. The DHT just happens to use one wire, which is a description, not a protocol.
Edit this page — content/esp32/one-wire-sensor-timing.mdx
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.