Estimated Time: 20 minutes
Target Board: Arduino Uno R3 (ATmega328P)
The Verdict: When to Use the DHT11 with Arduino
The DHT11 is the most ubiquitous entry-level temperature and humidity sensor in the maker space, but it is not a universal solution. Before wiring it up, you need to know if it is actually the right tool for your specific environment. The DHT11 uses a thermistor for temperature and a resistive humidity measurement component, communicating over a proprietary single-bus protocol. It is cheap, but it lacks precision and range.
Use the decision tree below to determine if the DHT11 is the correct pick, or if you should pivot to a more capable sensor.
| Your Requirement | If True, Choose... | Why? |
|---|---|---|
| Temp range is strictly 0°C to 50°C, budget is under $2 | DHT11 | Cheapest option, perfectly adequate for basic indoor room monitoring. |
| Need to measure sub-zero temperatures (down to -40°C) | DHT22 (AM2302) | Same single-bus protocol, but uses a better NTC thermistor for wider range and 0.1°C resolution. |
| Need barometric pressure or high-precision lab-grade data | Bosch BME280 | Uses I2C/SPI, no bit-banging timing issues, includes pressure, highly stable. |
| Operating in high-humidity condensing environments | Sensirion SHT31 | DHT sensors permanently fail if the internal polymer gets saturated with liquid water. |
The Concrete Pick: If you are building a simple bedroom weather station or a classroom demonstration on a strict budget, stick with the DHT11. If you are building a greenhouse monitor, a weatherproof outdoor station, or anything requiring long-term data logging where accuracy matters, default to the Bosch BME280.
Hardware Specifications and Exact Parts List
Understanding the DHT11's electrical limits prevents brownouts and logic-level mismatches. The sensor operates natively at 3.3V to 5.5V, making it compatible with both 5V Arduino boards and 3.3V ESP32 boards without a logic level shifter.
| Parameter | Value | Notes |
|---|---|---|
| Operating Voltage | 3.3V - 5.5V DC | Do not exceed 5.5V or the internal IC will burn out. |
| Temperature Range | 0°C to 50°C | Resolution is 1°C. Accuracy is ±2°C. |
| Humidity Range | 20% to 80% RH | Resolution is 1%. Accuracy is ±5% RH. |
| Sampling Rate | 1 Hz (1 reading/sec) | Software libraries enforce a 2-second delay for stability. |
| Communication | Single-bus (proprietary) | Requires a 10kΩ pull-up resistor on the DATA line. |
Exact Parts List
- Microcontroller: Arduino Uno R3 (Rev3) with ATmega328P DIP or SMD.
- Sensor: DHT11 Temperature and Humidity Module. Crucial distinction: Buy the 3-pin module variant (usually mounted on a small blue or green PCB). It includes the required surface-mount pull-up resistor. If you buy the bare 4-pin plastic canister, you must supply your own 10kΩ resistor.
- Wiring: 3x Male-to-Male or Male-to-Female jumper wires (22 AWG stranded).
- Prototyping: Standard 830-tie-point solderless breadboard.
Wiring the DHT11 to the Arduino Uno R3
The wiring for a DHT11 Arduino setup is straightforward, but confusing the pinout is the number one cause of dead sensors. The 3-pin module standardizes the layout, but always verify the silkscreen on your specific board.
| DHT11 Module Pin | Arduino Uno R3 Pin | Wire Color (Suggested) |
|---|---|---|
| VCC (or +) | 5V | Red |
| GND (or -) | GND | Black |
| DATA (or OUT/S) | Digital Pin 2 | Yellow or Blue |
Step-by-Step Wiring Procedure
- De-energize the board: Unplug the USB cable from your Arduino Uno R3 before making connections to prevent accidental short circuits.
- Connect Power: Insert the red jumper wire from the DHT11 VCC pin to the Arduino 5V pin. While the DHT11 can run on 3.3V, using 5V on a 5V logic board like the Uno R3 ensures cleaner logic-high thresholds.
- Connect Ground: Insert the black jumper wire from the DHT11 GND pin to any Arduino GND pin.
- Connect Data: Insert the yellow jumper wire from the DHT11 DATA pin to Arduino Digital Pin 2.
- Verify Pull-up: Look at the back of your DHT11 module. If you see a small SMD resistor (labeled 103 for 10kΩ) bridging the VCC and DATA traces, you are good. If you are using a bare 4-pin sensor, you must physically insert a 10kΩ through-hole resistor between the 5V and DATA lines on your breadboard.
analogRead(). The DHT11 does not output a variable voltage; it outputs a digital, time-based bitstream. It must be read using digital GPIO functions.
Complete Arduino Code with Error Handling
The code below targets the Arduino Uno R3. It uses the industry-standard Adafruit DHT Sensor Library. You must install this library via the Arduino IDE Library Manager (search for "DHT sensor library" by Adafruit, and also install its dependency, the "Adafruit Unified Sensor" library).
This sketch includes explicit pin definitions, strict delay timing to prevent sensor lockups, and robust error handling to catch NaN (Not a Number) values before they corrupt your serial output or downstream logic.
#include <DHT.h>
// --- PIN DEFINITIONS ---
// Explicitly define the data pin and sensor type
#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // Sensor type (DHT11, DHT22, or DHT21)
// Initialize DHT sensor for normal 16MHz Arduino
DHT dht(DHTPIN, DHTTYPE);
// Timing variables to enforce the 2-second polling limit
unsigned long previousMillis = 0;
const long interval = 2500; // Poll every 2.5 seconds (safely above the 2s minimum)
void setup() {
Serial.begin(9600);
Serial.println(F("DHT11 Arduino Test - Initializing..."));
// Start the sensor
dht.begin();
}
void loop() {
unsigned long currentMillis = millis();
// Non-blocking delay to respect the DHT11 sampling rate
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Read temperature and humidity
float h = dht.readHumidity();
float t = dht.readTemperature(); // Celsius by default
float f = dht.readTemperature(true); // Fahrenheit
// --- ERROR HANDLING ---
// Check if any reads failed and exit early (to try again)
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println(F("Failed to read from DHT sensor!"));
return; // Abort this loop iteration, wait for the next interval
}
// Compute heat index (requires Adafruit Unified Sensor library)
float hif = dht.computeHeatIndex(f, h);
float hic = dht.computeHeatIndex(t, h, false);
// --- OUTPUT ---
Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% | Temperature: "));
Serial.print(t);
Serial.print(F("°C / "));
Serial.print(f);
Serial.print(F("°F | Heat Index: "));
Serial.print(hic);
Serial.print(F("°C / "));
Serial.print(hif);
Serial.println(F("°F"));
}
}
Debugging "NaN" and "Failed to Read" Errors
The DHT11 communicates via a proprietary single-bus protocol that relies on precise microsecond timing (bit-banging). The Arduino pulls the data line LOW for 18ms to wake the sensor, then releases it. The sensor responds by pulling the line LOW and HIGH to transmit 40 bits of data. If the timing is off by even a few microseconds, the checksum fails, and the library returns NaN.
When your serial monitor spits out the exact error string Failed to read from DHT sensor! or prints NaN for your values, do not replace the sensor immediately. Run through these first three checks.
The First Three Things to Check When It Fails
- Polling Rate Violation (Most Common): The DHT11 datasheet mandates a minimum 1-second sampling period. If you poll it every 500ms, the internal microcontroller locks up and stops responding. Ensure your code enforces a delay of at least 2000ms between reads. The code above uses 2500ms for a safety margin.
- Missing or Incorrect Pull-Up Resistor: The single-bus protocol is open-drain. The data line must be pulled HIGH to 5V via a resistor when idle. If you are using a bare 4-pin DHT11 and forgot the 10kΩ pull-up resistor between VCC and DATA, the line will float, causing random bit errors and checksum failures. Measure the resistance between VCC and DATA with your multimeter; it should read ~10kΩ.
- Interrupt Collisions and Power Sag: Because the protocol requires microsecond precision, if a hardware interrupt fires (like a timer interrupt or software serial RX) during the 40-bit read sequence, the timing skews and the read fails. Additionally, if your Arduino is powered via a weak USB port and the sensor draws its peak 2.5mA, a voltage sag can corrupt the logic levels. Try plugging into a powered USB hub or a dedicated 5V wall adapter.
| Rank | Cause | Fix / Measurement Threshold |
|---|---|---|
| 1 | Polling too fast | Increase delay() or millis() interval to ≥ 2000ms. |
| 2 | Missing pull-up resistor | Verify 10kΩ between VCC and DATA. Add one if using bare sensor. |
| 3 | Interrupt collision | Disable other time-critical interrupts during the read, or switch to an I2C sensor (BME280). |
| 4 | Wire length / capacitance | Keep DATA wire under 1 meter. Long wires add capacitance, slowing the rise time of the digital signal. |
| 5 | Dead sensor (water damage) | If humidity reads a locked 99% or 0%, the internal polymer is saturated or destroyed. Replace unit. |
Extending or Simplifying Your Build
Once you have stable, error-free reads from your DHT11 Arduino circuit, you will likely want to refine the project for its final deployment.
How to Simplify the Build
If you are struggling with wiring errors or breadboard clutter, switch to a 3-pin DHT11 module rather than the bare 4-pin component. The 3-pin modules (often sold as "DHT11 Sensor Module" on Amazon or AliExpress for around $1.50) integrate the 10kΩ pull-up resistor and a small power-filtering capacitor directly onto the PCB. This eliminates the most common wiring mistake (forgetting the pull-up) and reduces your jumper wire count to exactly three.
How to Extend the Build
To turn this basic serial-monitor sketch into a standalone appliance, extend the hardware with an I2C display. Because the DHT11 only uses one digital GPIO pin, you have the entire I2C bus (A4/SDA and A5/SCL on the Uno R3) free for peripherals.
- Add a Display: Wire a 0.96-inch SSD1306 I2C OLED display. Use the
Adafruit_SSD1306library to render the temperature and humidity locally without needing a PC. - Add Data Logging: Connect an SD card module via SPI to log the 2.5-second interval readings to a CSV file for long-term trend analysis.
- Migrate to WiFi: If you need remote monitoring, port this exact code to an ESP32 DevKit V1. The DHT11 wiring remains identical (just change the
DHTPINdefinition to a valid ESP32 GPIO like GPIO 4), and you can add theWiFiandPubSubClientlibraries to push theNaN-checked data to an MQTT broker like Mosquitto for Home Assistant integration.
For further reading on the underlying digital protocols and pin configurations, refer to the official Arduino Uno R3 documentation and the comprehensive Adafruit DHT Sensor Guide. By respecting the sensor's timing constraints and ensuring proper pull-up biasing, the DHT11 remains a highly reliable, ultra-low-cost entry point into environmental sensing.






