The sensor DHT11 is the most ubiquitous entry-level temperature and humidity module in the maker space, but its simplicity is deceptive. Unlike I2C or SPI sensors that rely on hardware communication peripherals, the DHT11 uses a custom single-bus digital protocol that requires precise microsecond-level bit-banging from your microcontroller. This guide gives you the exact wiring, the raw-to-unit math, the failure modes I see on the bench, and a concrete decision path to tell you if you should actually be using it.
How the DHT11 Actually Measures the Air
Humidity is measured using a capacitive sensing element. The sensor contains a polymer dielectric substrate sandwiched between two conductive electrodes. As ambient water vapor is absorbed by the polymer, its dielectric constant changes, which proportionally alters the capacitance of the element. The internal 8-bit microcontroller samples this capacitance, linearizes it, and converts it into a digital relative humidity (RH) percentage.
Temperature is measured via an integrated NTC (Negative Temperature Coefficient) thermistor embedded in the same epoxy package. As ambient temperature rises, the electrical resistance of the thermistor drops exponentially. The internal MCU reads this voltage divider output, applies a Steinhart-Hart-style lookup table burned into its OTP (One-Time Programmable) memory, and outputs the final Celsius integer. Because both sensing elements share a single epoxy housing, thermal coupling is tight, but it also means the sensor's own self-heating can skew readings if polled too frequently.
Wiring the Sensor DHT11 to ESP32 and Arduino
The DHT11 operates on a supply range of 3.3V to 5.5V DC, making it compatible with both 5V Arduino Unos and 3.3V ESP32 DevKits. The most critical hardware detail is the pull-up resistor: the data line is open-drain, meaning the sensor can only pull the line LOW. It relies on an external resistor to pull the line HIGH.
| Sensor Pin | Function | Connection / Requirement |
|---|---|---|
| Pin 1 | VCC | 3.3V to 5.5V DC (Match to your MCU logic level) |
| Pin 2 | DATA | MCU GPIO. Requires 4.7kΩ pull-up to VCC |
| Pin 3 | NC | Not Connected (Leave floating) |
| Pin 4 | GND | System Ground |
If you are using a 3-pin breakout board (commonly sold by Adafruit or generic Amazon vendors), Pin 3 is omitted, and the 4.7kΩ pull-up resistor is already soldered onto the PCB. If you are using the bare 4-pin blue plastic component, you must solder or breadboard a 4.7kΩ resistor between VCC and the DATA pin, or your microcontroller will read floating noise.
- De-energize: Ensure your ESP32 or Arduino is unplugged from USB/power.
- Wire Power: Connect Sensor Pin 1 to the MCU 3V3 (or 5V) pin, and Sensor Pin 4 to MCU GND.
- Wire Data: Connect Sensor Pin 2 to a free MCU GPIO (e.g., ESP32 GPIO 4). If using a bare 4-pin sensor, install the 4.7kΩ pull-up resistor between VCC and Pin 2.
- Verify: Use a multimeter in continuity mode to verify the pull-up resistor is present between VCC and DATA before applying power.
Decoding the Output: Raw Bits to Physical Units
The output of the DHT11 is strictly a single-bus digital signal. It is not an analog voltage, and it is not I2C. The MCU must initiate communication by bit-banging the data line with precise microsecond timing, as documented in the Adafruit DHT Sensor Guide.
The Protocol Timing:
The MCU pulls the data line LOW for at least 18ms to wake the sensor, then pulls HIGH for 20-40µs. The DHT11 responds by pulling LOW for 80µs, then HIGH for 80µs. Data is then transmitted in 40 bits. Each bit begins with a 50µs LOW pulse. A '0' is represented by a 26-28µs HIGH pulse, while a '1' is represented by a 70µs HIGH pulse.
The 40-Bit Packet Structure:
- Byte 1: Relative Humidity Integer (e.g., 65 for 65%)
- Byte 2: Relative Humidity Decimal (Always 0 on DHT11)
- Byte 3: Temperature Integer (e.g., 25 for 25°C)
- Byte 4: Temperature Decimal (Always 0 on DHT11)
- Byte 5: Checksum
Raw-to-Unit Math:
To extract the physical units, you simply read the integer bytes. However, you must validate the transmission using the checksum to prevent acting on corrupted data caused by EMI. The math to verify the packet is:
Checksum == (Byte1 + Byte2 + Byte3 + Byte4) & 0xFF
If the sum of the first four bytes, masked to 8 bits, matches Byte 5, the data is valid. The physical temperature is exactly Byte3 in °C, and the physical humidity is exactly Byte1 in % RH. No floating-point scaling or complex polynomial conversion is required in your C++ code because the internal MCU has already done it.
Calibration, Interference, and Failure Modes
Calibration and Scaling:
The DHT11 is factory-calibrated; the calibration coefficients are burned into the sensor's OTP memory. You do not need to apply scaling factors to the 40-bit packet. However, because the internal 8-bit MCU and the thermistor share a tiny epoxy package, the sensor generates slight self-heating. On the bench, I typically apply a software offset of raw_temp - 1.2 to correct for this thermal bias if the sensor is polled continuously.
Common Interference Sources:
- Read Frequency: The DHT11 internal sampling cycle is 1 second. If your code attempts to read the sensor faster than 1Hz (e.g., inside a fast
loop()without adelay(2000)), the sensor will hang, return stale data, or fail the checksum. Always enforce a minimum 2-second delay between reads. - Wire Length and Capacitance: The single-bus protocol is highly susceptible to parasitic capacitance. If your jumper wires exceed 20 meters, the rise times of the 70µs pulses will degrade, causing the MCU to misread '1's as '0's. Keep wire runs under 1 meter for 3.3V logic, or drop the pull-up resistor to 2.2kΩ for runs up to 5 meters.
- Missing Pull-Up: Without the 4.7kΩ resistor, the open-drain line floats. The ESP32 GPIO pins will read random high-frequency noise, resulting in checksum failures and 'NaN' outputs in your serial monitor.
Decision Tree: Should You Use the Sensor DHT11 or Upgrade?
The DHT11 is cheap, but its specifications are severely limited compared to modern I2C alternatives. Use the Adafruit DHT Sensor Library logic below to determine if this sensor fits your build, or if you need to pivot.
| Condition / Requirement | If YES | If NO |
|---|---|---|
| Do you need to measure temperatures below 0°C or above 50°C? | ABORT. DHT11 cannot read outside 0-50°C. Upgrade to DHT22 (AM2302) or BME280. | Proceed to next question. |
| Do you need to measure humidity above 80% RH or below 20% RH? | ABORT. DHT11 polymer saturates and drifts wildly outside 20-80% RH. Upgrade to BME280. | Proceed to next question. |
| Is your strict component budget under $2.00 per unit? | Proceed to final pick. | Upgrade to Bosch BME280 for I2C hardware offloading and higher precision. |
| Do you only need 1°C and 1% RH resolution (no decimals)? | Proceed to final pick. | Upgrade to DHT22 (0.1°C / 0.1% RH resolution). |
If you passed all the conditions above, you are building a basic indoor climate monitor where extreme precision is unnecessary and budget is the primary constraint. For this specific use case, your default pick is the Aosong DHT11 3-pin breakout module (with integrated 4.7kΩ pull-up).






