A comfort reading
Sixty per cent humidity means something different in every room, because it is a percentage of a limit that moves with temperature. The dew point does not — and computing it from the two numbers you already have is four lines of arithmetic and the clearest demonstration of what the better sensor buys you.
A number that means the same thing everywhere
Move both sliders, then switch the sensor.
The dew point is the temperature the air would have to fall to before water started coming out of it. Unlike a relative humidity percentage it is not measured against anything that moves, so 17 °C dew point feels the same in a conservatory and a cellar, and two rooms with different temperatures can be compared directly.
It is also what actually predicts the things people care about: condensation on a cold window, mould in a corner, and whether a night is going to be uncomfortable to sleep in.
The arithmetic
Four lines, from the two numbers the sensor already gave you:
float dewPoint(float tC, float rh) {
float g = log(rh / 100.0) + (17.62 * tC) / (243.12 + tC);
return (243.12 * g) / (17.62 - g);
}That is the Magnus–Tetens approximation with Sonntag's coefficients, which is good to about a third of a degree over a range wider than either sensor covers. It is not the source of error here.
Where the error does come from
The humidity reading, multiplied by the shape of that formula.
Run the same arithmetic at the edges of each sensor's stated tolerance and the dew point comes out as a range rather than a value. Around 24 °C and 60 % humidity, the DHT22's ±2 % puts the dew point inside about ±0.4 °C. The DHT11's ±5 % puts it inside about ±0.9 °C.
That is a band more than twice as wide, and it straddles two comfort categories where the DHT22's sits inside one. Which is the concrete version of the argument in DHT11 or DHT22: the accuracy matters exactly when something downstream acts on the number.
Bands worth using
These are the boundaries the US National Weather Service uses for comfort, converted from Fahrenheit and rounded:
| Dew point | It feels |
|---|---|
| under 10 °C | dry |
| 10 to 16 °C | comfortable |
| 16 to 18 °C | sticky |
| 18 to 21 °C | humid |
| over 21 °C | oppressive |
For a home, the useful thing is not the band but the trend: a dew point that climbs every evening and does not come back down is a ventilation problem, and it will show up in the numbers long before it shows up on a wall.
The code
Reads a DHT22 and prints temperature, relative humidity, the dew point computed from both, and a one-word verdict. Change DHT_TYPE to DHT11 if that is the board you wired; the arithmetic is the same and the answer is simply less certain.
// A comfort reading: temperature, humidity, and the dew point from both.
//
// Wiring, sensor to board:
// Sensor GND -> board GND
// Sensor VCC -> board 5V on an Uno, 3V3 on an ESP32, ESP32-S3 or Pico
// Sensor NC -> nothing
// Sensor DATA -> Uno D2, ESP32 GPIO 18, ESP32-S3 GPIO 4, Pico GP2
//
// Count the pins from the square pad: GND, VCC, NC, DATA. Mount the sensor
// in free air, away from the board -- a warm sensor reads dry, and the dew
// point is computed from the humidity, so the error goes straight through.
//
// Arduino IDE: install "DHT sensor library" by Adafruit from the Library
// Manager, and accept "Adafruit Unified Sensor" when it offers it.
#include <DHT.h>
#include <math.h>
#define DHT_PIN 2 // Uno D2. ESP32: 18. ESP32-S3: 4. Pico: 2.
#define DHT_TYPE DHT22 // DHT22 for the white cage, DHT11 for the blue one.
DHT dht(DHT_PIN, DHT_TYPE);
// Magnus-Tetens with the Sonntag 1990 coefficients: good to about 0.35 C
// between -45 and 60 C, which is wider than either sensor's range.
const float MAGNUS_A = 17.62;
const float MAGNUS_B = 243.12;
float dewPoint(float tC, float rh) {
if (rh < 1) rh = 1; // log(0) is not a temperature
float g = log(rh / 100.0) + (MAGNUS_A * tC) / (MAGNUS_B + tC);
return (MAGNUS_B * g) / (MAGNUS_A - g);
}
const char *howItFeels(float dp) {
if (dp < 10) return "dry";
if (dp < 16) return "comfortable";
if (dp < 18) return "sticky";
if (dp < 21) return "humid";
return "oppressive";
}
const unsigned long EVERY = 10000; // nothing in a room changes faster
unsigned long last = 0;
void setup() {
Serial.begin(115200);
dht.begin();
}
void loop() {
if (millis() - last < EVERY) return;
last = millis();
float rh = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(rh) || isnan(t)) {
Serial.println("read failed");
return;
}
float dp = dewPoint(t, rh);
Serial.print(t, 1); Serial.print(" C ");
Serial.print(rh, 1); Serial.print(" % dew point ");
Serial.print(dp, 1); Serial.print(" C -- ");
Serial.println(howItFeels(dp));
}The dew point is always at or below the air temperature, and the two meet at 100 % humidity. If your dew point comes out above the temperature, the humidity reading is wrong rather than the maths — a sensor that has just been breathed on can briefly report over 100 %.
When it does not work
That is impossible in air, so the humidity reading is at fault. A sensor that has just been breathed on, or one that has been somewhere cold and is condensing, can briefly report at or above 100 %. Give it a few minutes in normal air and it comes back.
Because it is not comparable between rooms. 60 % in a 30 °C conservatory holds nearly three times as much water as 60 % in a 12 °C garage, and only one of them feels sticky. The dew point is an absolute temperature, so the same figure means the same thing everywhere.
Add #include <math.h> at the top. It is in the sketch above. On the ESP32 cores it usually comes in through another header and works without it, which is exactly why it is easy to leave out and then be surprised on an Uno.
The reading is sitting on a band boundary. Either widen the bands, or add a little hysteresis — only change the word when the dew point has crossed the boundary by half a degree. A DHT11 will do this more than a DHT22 because it moves in whole steps.
The Magnus-Tetens approximation with Sonntag's 1990 constants, 17.62 and 243.12 °C, which is the pair the WMO guidance uses. It is accurate to roughly 0.35 °C over a range wider than either sensor covers, so it is not the limiting factor here — the humidity reading is.
Five things a DHT prints when something is wrong, and what each one narrows it to.
When every reading is nan →Edit this page — content/books/dht22/a-comfort-reading.mdx
Questions about this product
See what other owners have asked, and read their solutions.
This page covers several products. Choose yours to see the right discussions.
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.