Often searched by hobbyists as the DTH11 humidity sensor, the correct manufacturer part number is the DHT11. Despite the common typo, the hardware remains a staple in environmental monitoring due to its low cost and simplicity. However, interfacing it with modern 3.3V microcontrollers like the ESP32 requires strict attention to its custom digital protocol. Unlike analog sensors that output a varying voltage, or standard digital sensors that use I2C/SPI, the DHT11 uses a proprietary single-bus serial protocol. This guide breaks down the exact timing, raw-to-unit math, and ESP32-specific interrupt handling required to get reliable reads without checksum errors.
Sensing Principle and Hardware Specifications
The DHT11 measures relative humidity using a resistive polymer substrate. As ambient moisture increases, the polymer absorbs water vapor, which increases its electrical conductivity. The internal circuitry measures this resistance change and correlates it to a relative humidity percentage. For temperature, it relies on an internal NTC (Negative Temperature Coefficient) thermistor, where resistance drops predictably as temperature rises.
Rather than outputting raw analog voltages for you to scale, the sensor houses an internal 8-bit microcontroller. This MCU performs the ADC conversion, applies factory calibration coefficients stored in its OTP (One-Time Programmable) memory, and serializes the data into a 40-bit digital packet. Because the internal MCU handles the heavy lifting, the host microcontroller only needs a single GPIO pin to read the data, provided it can bit-bang the strict timing requirements of the single-bus protocol.
| Parameter | Specification | Notes / Bench Realities |
|---|---|---|
| Operating Voltage | 3.3V to 5.5V DC | 3.3V operation requires a 4.7kΩ pull-up to 3.3V, not 5V. |
| Operating Current | 0.3mA (standby), 1mA (measuring) | Average current is microamps if polled infrequently. |
| Sampling Rate | 1 Hz (1 read per second) | Polling faster than 1000ms will yield stale data or timeouts. |
| Humidity Range | 20% to 90% RH | Accuracy is ±5% RH. Condensation causes permanent damage. |
| Temperature Range | 0°C to 50°C | Accuracy is ±2°C. Not suitable for freezer or outdoor winter use. |
Wiring Pinout and Interference Mitigation
The physical DHT11 module typically features a 4-pin footprint, but only 3 pins are electrically active. Pin 3 is internally disconnected. When wiring to an ESP32, the most critical mistake is omitting the pull-up resistor or using the wrong voltage rail. The sensor's output is open-drain; it pulls the line low to transmit data but relies on the external pull-up resistor to bring the line high.
| Pin Number | Silk Label | Function | ESP32 DevKit V1 Connection |
|---|---|---|---|
| 1 | VDD / + | Power Supply (3.3V - 5.5V) | ESP32 3V3 pin (Use 3.3V to avoid frying GPIO) |
| 2 | DATA / S | Single-Bus Digital I/O | GPIO 4 (with 4.7kΩ resistor to 3V3) |
| 3 | NC | No Connection | Leave unconnected |
| 4 | GND / - | Ground Reference | ESP32 GND pin |
If you power the DHT11 from the ESP32's 3.3V pin, you must place a 4.7kΩ resistor between the DATA pin and the 3.3V rail. If you use a 10kΩ resistor, the rise time on the digital edge will be too slow, causing the ESP32 to misinterpret Bit 1s as Bit 0s. Never pull up to 5V when using a 3.3V microcontroller; doing so will backfeed 5V into the ESP32 GPIO, eventually degrading the silicon.
Common Interference Sources:
- Wire Capacitance: The single-bus protocol relies on microsecond-level edge detection. If your jumper wires exceed 2 meters, the parasitic capacitance will round off the sharp digital edges, causing checksum failures. Keep wire runs under 1 meter for unshielded ribbon cables.
- RTOS Interrupt Latency: The ESP32 runs FreeRTOS. If a WiFi stack interrupt fires while the ESP32 is reading a 70µs Bit 1 pulse, the pulse will be missed. You must use a library that temporarily disables interrupts or utilizes the ESP32's RMT (Remote Control) peripheral to handle the timing in hardware.
- Electromagnetic Interference (EMI): Routing the DATA wire parallel to AC mains or switching power supplies will induce voltage spikes that the DHT11 internal MCU interprets as start signals, resulting in random read timeouts.
Decoding the 40-Bit Output Signal (Raw-to-Unit Math)
The host microcontroller initiates communication by pulling the DATA line low for at least 18ms, then releasing it high. The DHT11 responds by pulling the line low for 80µs, then high for 80µs. After this handshake, it clocks out 40 bits of data. Understanding this timing is crucial for debugging when standard libraries fail.
| Signal Phase | Line State | Duration | Host Action |
|---|---|---|---|
| Start Signal | Low | 18ms (minimum) | MCU pulls GPIO low, then releases high. |
| Response | Low | 80µs | MCU waits for sensor to pull line low. |
| Sync | High | 80µs | MCU prepares to read 40 bits. |
| Bit '0' Data | Low / High | 50µs / 26-28µs | Short high pulse = logic 0. |
| Bit '1' Data | Low / High | 50µs / 70µs | Long high pulse = logic 1. |
The 40-bit payload is structured as five 8-bit bytes. To convert the raw binary data into physical units, you must concatenate the integer and decimal bytes. Here is the exact raw-to-unit math:
- Byte 0: Relative Humidity Integer
- Byte 1: Relative Humidity Decimal
- Byte 2: Temperature Integer
- Byte 3: Temperature Decimal
- Byte 4: Checksum
Conversion Math:
Humidity (%RH) = Byte[0] + (Byte[1] * 0.1)
Temperature (°C) = Byte[2] + (Byte[3] * 0.1)
Checksum Validation:
Before trusting the data, verify the integrity. The checksum is the 8 least significant bits of the sum of the first four bytes.
Checksum = (Byte[0] + Byte[1] + Byte[2] + Byte[3]) & 0xFF
If the calculated checksum does not match Byte[4], discard the reading and retry. Bench note: While the protocol supports decimal values via Bytes 1 and 3, the DHT11 hardware internally only resolves integers. Bytes 1 and 3 will almost always read as 0x00. If you need 0.1°C resolution, upgrade to the DHT22.
ESP32 Implementation and Calibration Realities
Because the ESP32's dual-core architecture and WiFi stack cause unpredictable microsecond delays, standard Arduino bit-banging code (like the legacy Adafruit DHT library) frequently throws checksum errors on the ESP32. For production or reliable bench work, use a library that leverages the ESP32's RMT peripheral, such as DHTesp. The RMT peripheral handles the pulse-width counting in dedicated hardware, completely immune to RTOS interrupt latency.
Below is a robust implementation using the ESP32 Arduino core and DHTesp:
#include <DHTesp.h>
const int DHT_PIN = 4;
DHTesp dht;
void setup() {
Serial.begin(115200);
// Initialize the sensor and specify the hardware type
dht.setup(DHT_PIN, DHTesp::DHT11);
Serial.println("DHT11 initialized on GPIO 4");
}
void loop() {
// DHTesp handles the 1Hz timing and RMT/interrupt management internally
TempAndHumidity data = dht.getTempAndHumidity();
if (dht.getStatus() != DHTesp::ERROR_NONE) {
Serial.print("Sensor Error: ");
Serial.println(dht.getStatusString());
} else {
Serial.print("Humidity: ");
Serial.print(data.humidity);
Serial.print(" %RH | Temp: ");
Serial.print(data.temperature);
Serial.println(" °C");
}
// Respect the 1Hz maximum sampling rate
delay(2000);
}
Calibration and Scaling:
The DHT11 is factory-calibrated. The calibration coefficients are burned into the sensor's internal OTP memory, meaning no user scaling or software calibration math is required beyond the byte concatenation shown above. You cannot adjust the calibration curve via software. If your sensor reads consistently 10% high compared to a reference hygrometer, the polymer substrate has likely degraded due to age, exposure to condensation, or chemical vapors (like flux fumes or solvents). In such cases, replacement is the only viable fix, as the DHT11 is a consumable-grade component with an expected lifespan of 1-2 years in harsh environments.






