DHT22/Reading it/05. Every two seconds
Reading it · 05 of 9

Every two seconds

The DHT22's datasheet asks for more than two seconds between readings, and Adafruit's library refuses to go to the wire more often than every 2000 ms. Ask sooner and you get the previous answer back with nothing to say so. For a log, time the loop with millis() at 2.5 s or slower, and every line is a new reading on time.

The floor and the cache are the same number

The DHT22's datasheet puts it twice: §3 gives an average sensing period of 2 s, and §7 says the collecting period "should be : >2 second". The DHT11 is allowed one second, so the DHT22 is the slower of the two.

Adafruit's library has its own floor, MIN_INTERVAL, and it is 2000 ms for every sensor type. Inside that window read() does not touch the wire. It returns whatever it returned last time, the same five bytes and the same success or failure. For a DHT11 that throws away half its speed, as how often you may ask shows. For the DHT22 the two numbers agree, so the library is protecting the sensor rather than slowing it down.

Which asks reach the sensor

Set how often the loop asks and how it waits, and see which asks get a new reading.

Which asks reach the sensor
delay() · every 2.307 s
The sketch waits with
Ask every2000 ms
Other work in loop()300 ms
Really every
2.307 s
Fresh / cached
9 / 0
Lines an hour
1561
Every reading is fresh, but not every 2 s. delay() waits after the work, so the loop really runs every 2.307 s and a log stamped “every 2 s” drifts 479 s behind the clock each hour. A millis() timer keeps the spacing.

Asked faster than every two seconds, some readings are repeats. Nothing marks them: the numbers are real, just old, and isnan() is false.

Asked at exactly 2000 ms by a timer, the library can still say no. It stamps each read with its own millis() a moment after your timer fired, so two seconds later by your clock can be a millisecond short by its clock. Asking every 2.5 s or slower keeps clear of the edge.

delay() or a timer

delay(2000) at the end of loop() is fine for a first sketch: the read and the printing come on top of it, so the gap is always a little over two seconds and never a repeat.

For a log it drifts. Every pass is the delay plus the read plus whatever else the loop does, so a line stamped "every 10 s" falls further behind the clock each hour. The logger above measures from when the last pass started, last += EVERY_MS, so the lines stay on a ten-second grid however long each pass takes.

Ten seconds is plenty for a room. How fast the sensor itself can follow a change is a separate limit, and a slower one: how slowly it catches up.

The code

dht22_logger.ino

Prints one comma-separated line every ten seconds: seconds since power-up, temperature, humidity. The timer is millis(), so the lines stay ten seconds apart however long the printing takes. Paste the Serial Monitor into a spreadsheet to plot it.

/*
  DHT22 - a line every ten seconds                      TK39 / /p/tk39

  Wiring. Count from the square pad on the TinkerBlock board, sensor
  side up, header at the bottom:

    GND  -> GND
    VCC  -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
    NC   -> nothing   (unconnected on the board)
    DATA -> D2 on an Uno, GPIO 18 on an ESP32,
            GPIO 4 on an ESP32-S3, GP2 on a Raspberry Pi Pico

  Arduino IDE
    Tools > Board                 your board, e.g. ESP32S3 Dev Module
    Tools > Port                  the one that appears when you plug in
    Tools > USB CDC On Boot       Enabled   (ESP32-S3 only)
    Tools > Manage Libraries      DHT sensor library, by Adafruit.
                                  Say yes to Adafruit Unified Sensor.
*/

#include <DHT.h>

// Uno: 2. ESP32: 18. ESP32-S3: 4. Pico: 2.
#define DHT_PIN  4
#define DHT_TYPE DHT22

DHT dht(DHT_PIN, DHT_TYPE);

// Well clear of the library's 2000 ms. Nothing in a room changes
// faster than this, and a day is 8640 lines.
const unsigned long EVERY_MS = 10000;
unsigned long last = 0;

void setup() {
  Serial.begin(115200);
  dht.begin();
  last = millis();          // first line EVERY_MS after power-up
  Serial.println("s,celsius,humidity");
}

void loop() {
  // Measured from the last start, not the last finish, so the time
  // spent reading and printing does not push the next line later.
  if (millis() - last < EVERY_MS) return;
  last += EVERY_MS;

  float humidity = dht.readHumidity();
  float celsius  = dht.readTemperature();

  Serial.print(last / 1000);
  Serial.print(",");
  if (isnan(humidity) || isnan(celsius)) {
    Serial.println(",");    // a gap you can see in the log
    return;
  }
  Serial.print(celsius, 1);
  Serial.print(",");
  Serial.println(humidity, 1);
}

The first line comes ten seconds after power-up, which also clears the datasheet's one second of quiet. A failed read prints the time and two empty fields rather than skipping, so gaps in the log are visible. The sketch compiles for an Uno and an ESP32-S3.

When it does not work

The number never changes, however fast I ask

You are asking inside the library's 2000 ms window, and it is handing back the previous reading without touching the wire. Asking faster only prints the same line more often. Time the loop at 2.5 s or slower.

A failed reading keeps coming back as nan

The library caches the result as well as the bytes: a failed read stays failed for the next 2000 ms. A sketch that retries immediately gets the same nan until the window closes, so wait at least two seconds before asking again.

My timestamps drift from the clock

The loop waits with delay() after reading and printing, so each pass is the delay plus everything else. Over an hour that adds up. Measure from the last start with millis(), as the logger does, and the lines stay on a fixed grid.

Can I force a fresh read?

readTemperature(false, true) and readHumidity(true) skip the cache. Do not use it to go faster than two seconds: the DHT22's datasheet asks for more than 2 s between readings, and the library's number is there because of it.

Where this goes next

A DHT22 and a DHT11 on one board, printing both, so the datasheets' accuracy becomes a number you can see.

Both sensors side by side

Edit this page — content/books/dht22/every-two-seconds.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