DHT sensors/Two builds and a check/11. A comfort reading
Two builds and a check · 11 of 12

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.

Dew point, and how sure you are of it
24 °C · 62 % RH
Temperature24 °C
Relative humidity62 %
Which sensor gave you those two numbers
Dew point
16.3 °C
It feels
Sticky
Give or take
0.5 °C
Sticky. Noticeable. Most people reach for a fan. Dew point is the temperature the air would have to fall to before water came out of it, and unlike a humidity percentage it means the same thing in every room — which is why it is the number worth putting on a display. The width of that band is what the better sensor buys you: the same reading through a DHT11 is worth ±1.3 °C and through a DHT22 ±0.5 °C, and the DHT22's is 2.5 times the other’s. On a chart that is the difference between a trend and a smear.

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 pointIt feels
under 10 °Cdry
10 to 16 °Ccomfortable
16 to 18 °Csticky
18 to 21 °Chumid
over 21 °Coppressive

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

comfort_reading.ino

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

The dew point comes out higher than the temperature

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.

Why not just show the humidity percentage?

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.

log() will not compile

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 verdict flickers between two words

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.

Which coefficients are these?

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.

Where this goes next

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

Community

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.

Browse Modules and blocks on the forum