The Direct Answer: Wiring and Specs at a Glance

To wire an Arduino humidity sensor DHT11 to an Arduino Uno R3, connect the sensor's VCC pin to the Uno's 5V pin, the GND pin to the Uno's GND, and the Data (OUT) pin to Digital Pin 2. If you are using a bare 4-pin DHT11 component instead of a pre-assembled 3-pin module, you must add a 4.7kΩ or 10kΩ pull-up resistor between the VCC and Data pins to stabilize the single-bus communication line.

Project Difficulty: Beginner (2/5)
Estimated Time: 15 minutes for wiring, 10 minutes for coding and debugging.

The DHT11 uses a proprietary single-wire protocol. It is not I2C or 1-Wire; it relies on precise microsecond timing to transmit 40 bits of data (humidity integer, humidity decimal, temperature integer, temperature decimal, and a checksum). Because of its internal polymer humidity capacitor and NTC thermistor, it has strict physical limitations you must respect in your code and circuit design.

DHT11 Sensor Specifications
ParameterValuePractical Note
Operating Voltage3.3V to 5.5V DC5V is strongly recommended for reliable timing over jumper wires.
Humidity Range20% to 90% RHWill saturate and stall if exposed to >90% RH for long periods.
Humidity Accuracy±5% RHNot suitable for precision incubators or medical environments.
Temperature Range0°C to 50°CFreezing temperatures will damage the internal polymer.
Sampling Rate1 Hz (1 reading/sec)Polling faster than 1000ms will cause checksum failures and NaN errors.

Parts List and Exact Pin Mapping

Before you start stripping wires, verify you have the correct module variant. The DHT11 is sold in two common physical form factors: the bare 4-pin blue plastic package, and a 3-pin PCB module (often with a built-in pull-up resistor and filtering capacitor). The code and wiring below assume the 3-pin module, but we include the resistor requirement for the bare component.

Required Components

  • Microcontroller: Arduino Uno R3 (or compatible ATmega328P clone).
  • Sensor: DHT11 3-pin module (e.g., Adafruit product ID 386) OR bare 4-pin DHT11.
  • Resistor: 10kΩ (only required if using the bare 4-pin sensor).
  • Wiring: Half-size breadboard and 22 AWG solid-core jumper wires.
Pin Mapping: DHT11 to Arduino Uno R3
DHT11 3-Pin ModuleDHT11 Bare 4-PinArduino Uno R3 PinFunction
VCC (or +)Pin 1 (VDD)5VPower supply (Do not use 3.3V for long wire runs)
DATA (or OUT)Pin 2 (DATA)Digital Pin 2Single-bus data communication
NC (Not Connected)Pin 3 (NC)NoneLeave floating / unconnected
GND (or -)Pin 4 (GND)GNDCommon ground reference
Bench Tip: If your jumper wires are longer than 1 meter, the parasitic capacitance of the wire will distort the microsecond timing pulses. Keep wires under 50cm for the DHT11, or switch to an I2C sensor like the AHT20 for longer runs.

Complete Compilable Code for Arduino Uno R3

This code targets the Arduino Uno R3 (ATmega328P). It requires the DHT sensor library by Adafruit and its dependency, the Adafruit Unified Sensor library. Install both via the Arduino IDE Library Manager before compiling.

The code includes explicit pin definitions and robust error handling to catch the inevitable NaN (Not a Number) returns that occur when the single-wire protocol drops a bit.

// Target Board: Arduino Uno R3 (ATmega328P)
// Libraries required: DHT sensor library (Adafruit), Adafruit Unified Sensor

#include <DHT.h>
#include <DHT_U.h>

// --- PIN DEFINITIONS ---
#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 Uno
DHT dht(DHTPIN, DHTTYPE);

// Variables to hold readings
float humidity;
float temperatureC;
float heatIndexC;

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHT11 Sensor Initialization..."));
  
  // Start the sensor
  dht.begin();
  
  Serial.println(F("Setup complete. Waiting for first reading (2s delay)..."));
  delay(2000); // DHT11 requires 2 seconds on startup to stabilize
}

void loop() {
  // Wait a minimum of 1 second between readings (1Hz max sampling rate)
  delay(1500); 

  // Read humidity (%)
  humidity = dht.readHumidity();
  // Read temperature as Celsius
  temperatureC = dht.readTemperature();

  // --- ERROR HANDLING ---
  // Check if any reads failed and exit early (to try again).
  if (isnan(humidity) || isnan(temperatureC)) {
    Serial.println(F("Failed to read from DHT sensor! Check wiring and pull-up resistor."));
    // Do not return or halt; just skip this loop iteration and try again next cycle
    return; 
  }

  // Compute heat index in Celsius
  heatIndexC = dht.computeHeatIndex(temperatureC, humidity, false);

  // --- SERIAL OUTPUT ---
  Serial.print(F("Humidity: "));
  Serial.print(humidity);
  Serial.print(F("% | Temp: "));
  Serial.print(temperatureC);
  Serial.print(F("°C | Heat Index: "));
  Serial.print(heatIndexC);
  Serial.println(F("°C"));
}

Debugging the Dreaded "NaN" Error and Read Failures

When working with the Arduino humidity sensor DHT11, the most common failure mode is seeing NaN printed to the Serial Monitor, accompanied by the exact error string: "Failed to read from DHT sensor! Check wiring and pull-up resistor." This happens when the microcontroller's interrupt-driven timing fails to catch the 40-bit data stream from the sensor, resulting in a failed checksum.

If your sensor fails to read, here are the first three things to check, ranked by probability:

  1. Missing or Incorrect Pull-Up Resistor: If you are using a bare 4-pin DHT11, the data line is open-drain. Without a 4.7kΩ or 10kΩ resistor tying the Data pin to 5V, the line will float, and the Uno will read random noise. If using a 3-pin module, verify the module actually has the resistor soldered on the back (some cheap clones omit it).
  2. Timing Violation (Polling Too Fast): The DHT11 hardware requires a minimum of 1000ms between read commands. If your loop() delay is set to 500ms, the sensor will ignore the second request, causing a timeout and returning NaN. Ensure your delay is at least 1500ms to account for code execution time.
  3. Power Starvation on 3.3V: While the DHT11 datasheet claims 3.3V operation, the internal NTC thermistor and polymer capacitor draw a brief current spike during the read cycle. On a 3.3V rail with long wires, this causes a brownout, resetting the sensor mid-transmission. Always power the DHT11 from the Uno's 5V pin.
Advanced Debugging: If you have an oscilloscope, probe the Data pin. You should see the Uno pull the line LOW for 18ms (start signal), release it, and then the DHT11 pulls it LOW for 80µs, HIGH for 80µs, followed by 40 bits of data where a '0' is 50µs LOW / 26µs HIGH, and a '1' is 50µs LOW / 70µs HIGH. If the line stays HIGH or LOW continuously, your sensor is dead or unpowered.

Extending or Simplifying Your DHT11 Build

Once you have the basic Arduino humidity sensor DHT11 circuit working, you will likely want to modify the project for real-world deployment. Here is how to extend or simplify the build based on your end goal.

How to Simplify the Build (Upgrading the Sensor)

If you are tired of the DHT11's ±5% accuracy and 1Hz polling limit, simplify your hardware debugging by switching to an AHT20 or AHT21 sensor. Unlike the DHT series, the AHT series uses standard I2C communication. This completely eliminates the single-wire microsecond timing issues, meaning no more NaN errors caused by interrupt latency. You simply wire SDA to A4 and SCL to A5 on the Uno, and use the Adafruit AHTX0 library. Alternatively, upgrading to a DHT22 (AM2302) uses the exact same wiring and code structure as the DHT11 but offers ±2% RH accuracy and a wider -40°C to 80°C temperature range.

How to Extend the Build (Displays and Networking)

To extend the project into a standalone environmental monitor:

  • Add a Display: Wire an SSD1306 128x64 I2C OLED display. Connect SDA to A4 and SCL to A5. Use the Adafruit_SSD1306 library to print the humidity and temperature locally without needing a PC.
  • Add Data Logging: Connect a MicroSD card breakout board via SPI (CS to Pin 10, MOSI to 11, MISO to 12, SCK to 13) and log timestamped CSV data using the SD library.
  • Move to WiFi (ESP32): If you want to push data to an MQTT broker or cloud dashboard, migrate the code to an ESP32 DevKit V1. Warning: When moving to ESP32, change #define DHTPIN 2 to #define DHTPIN 4. GPIO 2 on the ESP32 is a strapping pin tied to the onboard LED and can cause boot failures if pulled low by the DHT11 during startup.

Frequently Asked Questions

Why is my Arduino humidity sensor DHT11 reading 0% or NaN?

A reading of exactly 0% usually means the sensor's internal polymer humidity capacitor has become saturated with moisture (often from condensation or being breathed on directly) and cannot discharge, or the sensor is physically damaged. A reading of NaN means the communication protocol failed entirely. For NaN, check your pull-up resistor, ensure you are waiting at least 1000ms between reads, and verify the sensor is receiving a stable 5V supply.

Can I power the Arduino humidity sensor DHT11 with 3.3V?

Technically yes, as the datasheet lists 3.3V to 5.5V. However, in practice on a breadboard, 3.3V is highly discouraged for the DHT11. The sensor draws a brief current spike during the read cycle. If your 3.3V rail has any voltage drop (common with cheap Uno clones using linear regulators), the sensor will brownout mid-transmission. Always use the 5V pin for the DHT11 unless you are using a dedicated low-dropout regulator right next to the sensor.

What is the difference between the DHT11 3-pin module and 4-pin bare sensor?

The bare 4-pin DHT11 is just the raw component. It requires you to manually add a 4.7kΩ or 10kΩ pull-up resistor between VCC and the Data pin, and it is highly recommended to add a 100nF decoupling capacitor between VCC and GND. The 3-pin module is a small PCB that already includes the pull-up resistor and filtering capacitor on the board, making it strictly plug-and-play for breadboards.

How often can I read data from the Arduino humidity sensor DHT11?

The absolute maximum sampling rate for the DHT11 is 1 Hz, which means one reading per second (1000ms). However, because the dht.readHumidity() function takes a few milliseconds to execute and block interrupts, it is best practice to set your loop delay to at least 1500ms or 2000ms. Reading faster than 1Hz will cause the sensor to ignore the host's start signal, resulting in checksum errors.