Temperature & Humidity Sensors
By the end of this lesson you will be able to read temperature and humidity from a DHT22 sensor, handle failed readings properly, convert an analog temperature sensor's voltage into degrees, and choose a better sensor when accuracy matters. Your board will finally measure something about the real world.
Temperature and humidity matter everywhere in India: a mushroom farm in Himachal, a pharmacy cold box, a server room, or just deciding whether to switch on the cooler in a Jaipur summer.
Two kinds of sensors
Humidity is the amount of water vapour in the air. Relative humidity (RH), given as a percentage, compares it with the most the air could hold at that temperature. Mumbai in the monsoon can sit near 90% RH; Jaisalmer in summer can drop below 20%.
| Sensor | Measures | Output | Range and accuracy (datasheet, typical) | Notes |
|---|---|---|---|---|
| DHT11 | Temperature, humidity | Digital, one data wire | 0 to 50 °C (±2 °C), 20 to 90% RH (±5%) | Cheap, slow, low accuracy |
| DHT22 (AM2302) | Temperature, humidity | Digital, one data wire | -40 to 80 °C (±0.5 °C), 0 to 100% RH (±2 to 5%) | Better; read at most every 2 s |
| TMP36 | Temperature only | Analog voltage | -40 to 125 °C, about ±2 °C | Needs only analogRead() |
| BME280, SHT31, SHT4x | Temperature, humidity (BME280 also pressure) | I2C | More accurate | Use with the I2C lessons |
Accuracy figures vary between manufacturers and clones, so read the datasheet for your exact part. Cheap DHT clones in particular may not meet the original specification.
Step 1: Wire a DHT22 module
Most kits sell the DHT22 on a small module with three pins and a pull-up resistor already fitted.
| Part | Pin | Connects to |
|---|---|---|
| DHT22 module | + (VCC) | Arduino 5V (use 3.3V on an ESP32) |
| DHT22 module | OUT (data) | Arduino D4 |
| DHT22 module | - (GND) | Arduino GND |
If you have the bare 4-pin sensor instead, add a 10 kΩ resistor from the data pin to VCC, and leave the third pin unconnected. Check the pin order in your sensor's datasheet; it is printed facing the grille side.
Step 2: Install the library
The DHT sensors use a timing-based protocol on one wire. Writing it yourself is hard, so use a library:
- Open the Library Manager.
- Search for
DHT sensor libraryand install the one by Adafruit. - When asked, choose Install all to also install its dependency, Adafruit Unified Sensor.
Step 3: Read the sensor
#include <DHT.h>
const int DHT_PIN = 4;
DHT dht(DHT_PIN, DHT22); // use DHT11 here for a DHT11
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
delay(2000); // the DHT22 needs 2 s between reads
float humidity = dht.readHumidity();
float tempC = dht.readTemperature(); // Celsius by default
if (isnan(humidity) || isnan(tempC)) {
Serial.println("Sensor read failed, check wiring");
return; // skip this pass, try again
}
Serial.print("Temp: ");
Serial.print(tempC, 1);
Serial.print(" C Humidity: ");
Serial.print(humidity, 0);
Serial.println(" %");
}In a room in Pune on a monsoon afternoon, you might see something like:
Temp: 28.6 C Humidity: 74 % Temp: 28.6 C Humidity: 74 % Temp: 28.7 C Humidity: 75 %
These are example readings; yours depend on your room. Breathe gently on the sensor and the humidity should rise within a few seconds.
isnan() means "is not a number". When the library cannot read the sensor (loose wire, wrong pin, wrong type), it returns a special value called NaN instead of a temperature. Always check for it. Otherwise, your code may switch on a fan because of a reading that does not exist.
return inside loop() ends this pass early. loop() then simply starts again.
Step 4: Turn readings into decisions
Numbers are only useful when they lead to a decision. Keep the decision logic in its own function so you can test it with fixed values before trusting it with real ones:
const char* comfort(float tempC, float humidity) {
if (tempC >= 32 && humidity >= 60) return "hot and humid: turn on the fan";
if (tempC >= 32) return "hot and dry: drink water";
if (tempC < 18) return "cool";
return "comfortable";
}
void setup() {
Serial.begin(9600);
while (!Serial && millis() < 3000) { }
const float temps[] = {34.5, 35.0, 26.0, 15.5};
const float hums[] = {72, 30, 55, 80};
for (int i = 0; i < 4; i++) {
Serial.print(temps[i], 1);
Serial.print(" C, ");
Serial.print(hums[i], 0);
Serial.print(" % -> ");
Serial.println(comfort(temps[i], hums[i]));
}
}
void loop() {
}34.5 C, 72 % -> hot and humid: turn on the fan 35.0 C, 30 % -> hot and dry: drink water 26.0 C, 55 % -> comfortable 15.5 C, 80 % -> cool
The order of the if checks matters. The most specific case (hot and humid) comes first; otherwise "hot and dry" would catch every hot reading. The thresholds here are only examples; choose your own for your project.
An analog sensor: TMP36
The TMP36 is a three-legged chip that outputs a voltage: 500 mV at 0 °C, rising 10 mV for every degree. So:
temperature in °C = (millivolts − 500) ÷ 10
| Part | Pin | Connects to |
|---|---|---|
| TMP36 (flat side facing you) | Left | 5V |
| TMP36 | Middle | A1 |
| TMP36 | Right | GND |
Getting the pins backwards makes a TMP36 hot quickly, so double-check against the datasheet before powering on, and unplug immediately if it warms up.
This sketch tests the conversion on fixed ADC readings:
float tmp36Celsius(int raw) {
float millivolts = raw * 5000.0 / 1023.0; // 5 V UNO, 10-bit ADC
return (millivolts - 500.0) / 10.0;
}
void setup() {
Serial.begin(9600);
while (!Serial && millis() < 3000) { }
const int samples[] = {123, 153, 164, 205};
for (int i = 0; i < 4; i++) {
Serial.print("raw ");
Serial.print(samples[i]);
Serial.print(" -> ");
Serial.print(tmp36Celsius(samples[i]), 1);
Serial.println(" C");
}
}
void loop() {
}raw 123 -> 10.1 C raw 153 -> 24.8 C raw 164 -> 30.2 C raw 205 -> 50.2 C
For the live sensor, call tmp36Celsius(analogRead(A1)) in loop(). Each ADC step is about 4.9 mV, which is about half a degree, so averaging several readings (from Analog Input) helps.
Common mistakes
- Reading a DHT22 too often. Reads faster than every 2 s may return old values or NaN.
- Wrong sensor type in code.
DHT11in code with a DHT22 connected gives nonsense. - Not checking
isnan(). Failed reads become decisions based on nothing. - Bare DHT sensor without a pull-up. Add 10 kΩ from data to VCC, or use a module.
- Trusting cheap sensors for critical uses. For medicine storage or labs, use calibrated sensors.
Key points
- DHT11 and DHT22 send temperature and humidity digitally on one data wire; DHT22 is more accurate.
- Use the Adafruit DHT sensor library:
dht.begin(),readTemperature(),readHumidity(). - Check readings with
isnan()and wait about 2 s between DHT22 reads. - TMP36: °C = (millivolts − 500) ÷ 10, read with
analogRead(). - Test decision logic with fixed values before connecting it to real sensors.
Exercise
Write a function fanSpeed(float tempC) that returns a PWM value: 0 below 28 °C, 128 from 28 °C up to (but not including) 33 °C, and 255 at 33 °C and above. Test it with 25.0, 28.0, 32.9 and 33.0, printing each result.
Show solution
int fanSpeed(float tempC) {
if (tempC >= 33.0) return 255;
if (tempC >= 28.0) return 128;
return 0;
}
void setup() {
Serial.begin(9600);
while (!Serial && millis() < 3000) { }
const float tests[] = {25.0, 28.0, 32.9, 33.0};
for (int i = 0; i < 4; i++) {
Serial.print(tests[i], 1);
Serial.print(" C -> fan PWM ");
Serial.println(fanSpeed(tests[i]));
}
}
void loop() {
}25.0 C -> fan PWM 0 28.0 C -> fan PWM 128 32.9 C -> fan PWM 128 33.0 C -> fan PWM 255
Testing the exact edges (28.0 and 33.0) and just below an edge (32.9) catches mistakes between > and >=.
Quick Quiz
1. What does isnan(tempC) check?
The library returns NaN when it cannot read the sensor, so always check before using the value.
2. How often should you read a DHT22?
The DHT22 needs about 2 seconds between readings.
3. A TMP36 outputs 750 mV. What is the temperature?
(750 − 500) ÷ 10 = 25 °C.
4. Why test decision functions with fixed values first?
Fixed test values show quickly whether every branch and boundary behaves correctly.
Learn IoT & Arduino with a mentor
Free lessons get you started. Our IoT & Embedded Systems training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
