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.
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
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
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.
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.
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.
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.
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
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.