If you are building a weather station or a greenhouse monitor, the DHT11 sensor is likely your first stop. The direct answer to how it communicates is simple: it outputs a single-bus digital signal, not an analog voltage. You cannot wire this to an ADC (Analog-to-Digital Converter) pin and read a varying voltage. Instead, it uses a microcontroller-driven timing protocol to send a 40-bit data packet containing relative humidity and temperature over a single DATA wire.
Because it relies on strict microsecond timing rather than voltage levels, interfacing the DHT11 requires understanding its digital protocol, managing parasitic capacitance on your wires, and respecting its 1 Hz sampling limit. Below is the bench-tested data, wiring logic, and code you need to get reliable readings on an Arduino or ESP32.
DHT11 Sensor Specifications and Pinout
Before wiring anything, you need to know the hard limits of the silicon. The DHT11 is a budget-tier sensor; pushing it outside its specified ranges will result in garbage data or permanent damage to the internal polymer.
| Parameter | Value / Range | Notes & Bench Reality |
|---|---|---|
| Operating Voltage | 3.3V to 5.5V DC | Works natively on ESP32 (3.3V) and Arduino Uno (5V). |
| Humidity Range | 20% to 90% RH | Readings below 20% or above 90% will flatline or drift. |
| Humidity Accuracy | ±5% RH | Expect ±3% in normal room conditions; degrades in high condensation. |
| Temperature Range | 0°C to 50°C (32°F to 122°F) | Will not read sub-zero temperatures. Do not use for freezers. |
| Temperature Accuracy | ±2°C | Often reads 1-2°C high if mounted near a warm microcontroller. |
| Resolution | 1% RH / 1°C | No decimal precision in the raw hardware output. |
| Sampling Rate | 1 Hz (1 reading/second) | Polling faster than 1000ms will cause checksum failures. |
Pinout and Wiring Table
The bare 4-pin DHT11 component and the common 3-pin breakout modules share the same internal logic, but the breakout modules include a surface-mount 10kΩ pull-up resistor. If you are using the bare 4-pin blue plastic package, you must add your own pull-up.
| Pin Number | Label | Function | Connection Target |
|---|---|---|---|
| 1 | VCC / VDD | Positive Supply (3.3V - 5.5V) | MCU 3.3V or 5V pin |
| 2 | DATA / OUT | Single-Bus Digital I/O | Any MCU GPIO (with 10kΩ pull-up to VCC) |
| 3 | NC | No Connection | Leave floating / unconnected |
| 4 | GND | Ground Reference | MCU GND pin |
Sensing Principle and Signal Output Math
The DHT11 measures humidity using a moisture-dependent capacitive polymer. As ambient water vapor is absorbed by the polymer substrate between two metal electrodes, the dielectric constant changes, altering the capacitance. The internal ASIC measures this capacitance shift and converts it to a digital percentage. For temperature, it relies on a surface-mount NTC (Negative Temperature Coefficient) thermistor. As the ambient temperature rises, the resistance of the thermistor drops predictably, which the internal ADC samples and digitizes.
Because both sensing elements are read by an internal 8-bit microcontroller, the output you receive on the DATA pin is strictly digital. The sensor does not output a varying analog voltage or current. Instead, the MCU pulls the DATA line low to initiate a request, and the DHT11 responds by shifting out a 40-bit serial data packet. This means you never have to perform analog-to-digital scaling or reference voltage math (like you would with a TMP36 analog sensor); the math is purely bitwise.
The 40-Bit Raw-to-Unit Math
When you trigger a reading, the DHT11 sends 5 bytes (40 bits). Here is the exact mathematical breakdown of how to decode that raw packet into physical units:
- Byte 0: Humidity Integer part (e.g., 45)
- Byte 1: Humidity Decimal part (e.g., 0 — DHT11 rarely uses this)
- Byte 2: Temperature Integer part (e.g., 24)
- Byte 3: Temperature Decimal part (e.g., 0)
- Byte 4: Checksum
The Checksum Formula:
Checksum = (Byte0 + Byte1 + Byte2 + Byte3) & 0xFF
If the calculated checksum does not exactly match Byte 4, the packet was corrupted by electrical noise, and your code must discard the reading. To get the final physical units, you simply combine the integer and decimal bytes:
Relative Humidity (%) = Byte0 + (Byte1 * 0.1)
Temperature (°C) = Byte2 + (Byte3 * 0.1)
The DHT11 is officially rated for 0°C to 50°C. However, if the environment drops below zero, the sensor sets the Most Significant Bit (Bit 7) of Byte 2 to
1 to indicate a negative value. If you are writing a custom bit-banging library, you must mask Bit 7 and apply a negative sign to the remaining 7 bits. For most hobbyists, just use the standard Adafruit library which handles this edge case automatically.
Wiring, Interference, and Calibration
Getting the wires to the breadboard is easy; getting clean data is where most makers fail. Because the DHT11 uses a single-bus protocol relying on microsecond pulse widths (a '0' bit is a 50µs low pulse, a '1' bit is a 70µs low pulse), signal integrity is paramount.
Common Interference Sources
- Parasitic Capacitance on Long Wires: If your DATA wire exceeds 20 meters, the capacitance of the copper will smear the sharp digital edges, causing the MCU to misread the pulse widths. Keep wires under 2 meters for unshielded jumper cables.
- ESP32 WiFi RF Noise: When the ESP32 transmits on WiFi (2.4 GHz), it draws current spikes and radiates RF. If your DHT11 DATA line is routed directly under or next to the ESP32 PCB antenna, the induced noise will flip bits and trigger checksum errors. Route the sensor wires away from the antenna quadrant.
- Thermal Bleed from Voltage Regulators: If you mount the DHT11 physically close to the AMS1117 voltage regulator on an ESP32 DevKit or Arduino Nano, the convective heat will skew the NTC thermistor. Mount the sensor at least 5cm away from heat-generating components, or use a 4-wire extension cable.
Is Calibration Needed?
The DHT11 is factory calibrated. The calibration coefficients are burned into the internal ASIC's OTP (One-Time Programmable) memory. You do not need to perform any raw-to-voltage scaling or write custom calibration curves in your firmware. However, because the ±2°C accuracy is relatively wide, bench testing often reveals a fixed offset (e.g., your specific sensor always reads 1.2°C higher than a reference Fluke thermometer). In production firmware, it is standard practice to apply a hardcoded software offset (e.g., finalTemp = rawTemp - 1.2) to correct this specific unit's bias.
ESP32 and Arduino Implementation Code
Do not attempt to write your own bit-banging timing routine unless you are doing it for educational purposes. Microsecond timing on RTOS-based boards like the ESP32 can be interrupted by WiFi tasks, causing packet drops. Instead, use the battle-tested Adafruit DHT Sensor Library, which disables interrupts during the critical 5-millisecond read window to ensure clean data capture.
Required Libraries
- Adafruit DHT Sensor Library (v1.4.4 or newer)
- Adafruit Unified Sensor Library (Dependency)
Copy-Paste Firmware (ESP32 / Arduino Compatible)
#include <DHT.h>
// Define the GPIO pin connected to the DATA line
// On ESP32, avoid strapping pins like GPIO 0, 2, 12, 15
#define DHTPIN 4
// Uncomment the type of sensor in use
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
Serial.println(F("DHT11 Sensor Interfacing Test"));
// Initialize the DHT sensor
dht.begin();
}
void loop() {
// CRITICAL: Wait at least 2 seconds between readings (1Hz max sampling rate)
delay(2000);
// Reading temperature or humidity takes about 250ms
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again)
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor! Check wiring and pull-up resistor."));
return;
}
// Compute heat index in Celsius
float hic = dht.computeHeatIndex(t, h, false);
Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% Temperature: "));
Serial.print(t);
Serial.print(F("°C Heat Index: "));
Serial.print(hic);
Serial.println(F("°C"));
}
If your serial monitor spits out
NaN (Not a Number), the library failed the checksum verification. 1. Verify you have a 10kΩ pull-up resistor between VCC and DATA (if using the bare 4-pin sensor).
2. Ensure your
delay() between reads is at least 2000ms.3. If using an ESP32, ensure you aren't using a GPIO pin that is reserved for internal flash memory or strapping (stick to GPIO 4, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33). See the Espressif GPIO Documentation for pin restrictions.
By respecting the single-bus digital protocol, keeping your wires short to avoid parasitic capacitance, and enforcing the 2-second sampling delay, the DHT11 will provide reliable, repeatable environmental data for your embedded projects.






