Temperature and humidity sensors are among the most commonly used components in Arduino projects — weather stations, automatic watering, incubators, smart homes. But while connecting a sensor is simple, reading its values is full of pitfalls: wrong libraries, sensors that "freeze," distorted values, and typical wiring mistakes. In this article, we will look at three of the most popular sensors and how to read them properly.
Sensor Overview
Before we get to the code, let's see what each sensor offers:
| Property | DHT11 | DHT22 | DS18B20 |
|---|---|---|---|
| Temperature | 0 to 50 °C (±2 °C) | -40 to 80 °C (±0.5 °C) | -55 to 125 °C (±0.5 °C) |
| Humidity | 20–80% (±5%) | 0–100% (±2%) | does not measure |
| Protocol | single-wire, proprietary | single-wire, proprietary | 1-Wire |
| Minimum interval between readings | 1 second | 2 seconds | 750 ms (12-bit resolution) |
| Price | lowest | medium | low |
Quick pick: for room conditions and learning, the DHT11 is sufficient. For more serious projects, choose the DHT22, which also measures below zero. For pure temperature (even in water, remotely over a single cable, multiple sensors on one pin), the DS18B20 is the best choice.
DHT11 and DHT22: Wiring
Both sensors have (on a 3-pin module) three pins:
- VCC — power supply 3.3 V or 5 V (depending on the module)
- DATA — data pin to any digital pin (in the example we use pin 2)
- GND — ground
IMPORTANT: Many DHT modules already contain a built-in pull-up resistor on the data pin. If you use a bare 4-pin sensor, you must connect a 10 kΩ resistor between DATA and VCC. Without it, the sensor will not work or will return random values.
Reading DHT Sensors
For reading, we use the Adafruit DHT sensor library (together with the Adafruit Unified Sensor dependency):
// Reading temperature and humidity from a DHT22 sensor
// Library: Adafruit DHT sensor library
#include <DHT.h>
#define DHTPIN 2 // data pin
#define DHTTYPE DHT22 // DHT11 or DHT22
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
// reading takes about 250 ms
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
// check whether the reading succeeded
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read sensor!");
} else {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" C, Humidity: ");
Serial.print(humidity);
Serial.println(" %");
}
delay(2000); // DHT22: at most one reading every 2 seconds!
}
Most Common DHT Problems
- Wrong type in the code: If the code says DHT11 but a DHT22 is connected (or vice versa), readings fail or are distorted
- Reading too fast: The DHT11 needs at least 1 second, the DHT22 at least 2 seconds between readings. Reading too quickly causes NaN values
- Missing pull-up resistor: With a bare sensor without a built-in 10 kΩ resistor
- Wire too long: With wire longer than about 1 meter at 5 V (and even shorter at 3.3 V), the signal becomes unstable
- Low sensor quality: The market is full of counterfeit DHT11/DHT22 parts returning unstable values
DS18B20: Multiple Sensors on One Pin
The DS18B20 is a digital temperature sensor with the 1-Wire protocol. Its greatest advantage: you can hang multiple sensors on a single data pin — each has its own unique 64-bit address code by which you address it.
Wiring: VCC to 5 V, GND to ground, DATA to a digital pin (pin 2 in the example) and a 4.7 kΩ resistor between DATA and VCC. This resistor is mandatory with the DS18B20!
Reading the DS18B20
Two libraries are needed: OneWire and DallasTemperature:
// Reading temperature from a DS18B20 sensor
// Libraries: OneWire, DallasTemperature
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 // data pin
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(9600);
sensors.begin();
}
void loop() {
sensors.requestTemperatures(); // request measurements
// first sensor on the bus (index 0)
float temperature = sensors.getTempCByIndex(0);
if (temperature == DEVICE_DISCONNECTED_C) {
Serial.println("Error: sensor not connected!");
} else {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
}
delay(1000);
}
To read multiple sensors on the same pin, change the index: getTempCByIndex(1) returns the second sensor and so on. If you want to print the addresses (e.g., to record which sensor is where), use the sensors.getAddress(address, i) function.
Most Common DS18B20 Problems
- Missing 4.7 kΩ resistor: The most common mistake — without the pull-up resistor the sensor is unreachable
- Value of 85 °C: This is the power-on default value. It means the reading failed — usually due to too little delay between request and get
- Swapped power pin: With the standard TO-92 package, check the datasheet carefully — the pinout differs from other components
- Parasite power: The DS18B20 supports powering through the data pin (parasite mode), but it is less reliable. Start with normal 3-wire power
- Cables too long: With longer runs (several meters), a lower pull-up resistor value is recommended
Smoothing Values (Averaging)
All three sensors occasionally throw out a distorted value — a spike from electrical noise or interference. Programmers fix this simply by reading multiple times and averaging:
// Average of 5 measurements
float readTemp(const int COUNT = 5) {
float sum = 0;
int successful = 0;
for (int i = 0; i < COUNT; i++) {
float t = dht.readTemperature();
if (!isnan(t)) {
sum += t;
successful++;
}
delay(2200); // respect the minimum interval!
}
if (successful == 0) {
return NAN; // no measurement succeeded
}
return sum / successful;
}
An even better solution for removing spikes is the median — sort the measurements by size and take the middle value. Spikes (sudden extremes) corrupt the average, but the median stays stable.
Mistakes NOT to Make
| Mistake | Why it's bad | Correct |
|---|---|---|
| delay(100) in the loop for DHT | Reading fails because the sensor needs at least 1–2 seconds | delay(2000) for DHT22, delay(1000) for DHT11 |
| Not checking isnan() values | NaN spreads through calculations and processing | Always check isnan() before using the value |
| Relying on a single measurement | A single spike ruins the whole decision | Multiple measurements + average or median |
| 3.3 V with a long wire | The signal weakens, values become random | 5 V and as short a wire as possible |
| DHT22 humidity in water | The sensor is not waterproof, it gets destroyed | For water, use a DS18B20 in a sealed probe |
Conclusion
Reading sensors properly is not just connect and read — it is respecting intervals between readings, checking for invalid values, using the right resistors, and putting moderate trust in cheap clones. Those who follow these basics will have a weather station or watering system running smoothly for months. Those who don't will hunt for bugs in software while the problem is a single missing resistor.