SHT31/Three ways to get it wrong/09. One measurement or two
Three ways to get it wrong · 09 of 11

One measurement or two

The two obvious lines of sketch take two whole measurements where one would have done — twice the time, twice the energy, and no warning of any kind. The habit comes straight from the DHT library next door, by the same author, where it was free.

The two lines everybody writes

float celsius  = sht.readTemperature();
float humidity = sht.readHumidity();
Serial.print(celsius); Serial.print(" C  ");
Serial.print(humidity); Serial.println(" %");

That is correct code. It compiles, it prints two sensible numbers, and it does twice as much work as it needed to.

One measurement, or two
Your sketch says
Measurements
2
Sensor busy
25.0 ms
Your loop blocked
41.8 ms
Two calls, two whole measurements. Adafruit SHT31 Library keeps no cache at all — both readTemperature() and readHumidity() call the same private routine, which measures again every time — so this sketch blocks for 42 ms instead of 21 and prints two numbers taken 20 ms apart. Nothing warns you: the numbers look right, the loop is just slower than it needed to be. This is the opposite of Adafruit's DHT library, which caches for two seconds, and the habit carries over wrongly.

What is actually in the library

Both functions do the same thing:

float Adafruit_SHT31::readTemperature(void) {
  if (!readTempHum()) return NAN;
  return temp;
}

float Adafruit_SHT31::readHumidity(void) {
  if (!readTempHum()) return NAN;
  return humidity;
}

And readTempHum() sends the measure command, waits 20 ms, reads six bytes and checks both checksums — every time it is called. There is no cache. There is no timestamp. Nothing anywhere in the class asks "have I just done this?".

So two calls is two commands, two twenty-millisecond waits and two sets of six bytes: about 42 ms of blocked sketch where 21 would have done, and twice the energy per reading.

Twenty milliseconds is nothing to a room, so the two numbers are not meaningfully out of step with each other. The cost is the time and the energy — and the tidiness of a reading that is one measurement rather than two.

The call that does it once

float celsius, humidity;
if (sht.readBoth(&celsius, &humidity)) {
  Serial.print(celsius); Serial.print(" C  ");
  Serial.print(humidity); Serial.println(" %");
}

One measurement, both numbers, and a bool instead of two NaNs to test for. It is half the time, half the energy, and one fewer thing to reason about when something downstream combines the two values — a dew point, a comfort index, an absolute humidity in grams per cubic metre all assume the temperature and the humidity describe the same air.

Why this is a trap rather than a quirk

Because the habit is correct next door.

Adafruit's DHT library, by the same author, with the same shape of API, caches for two seconds: #define MIN_INTERVAL 2000, and a read inside that window returns the previous result without touching the wire. So on a DHT22, calling readTemperature() and then readHumidity() is one exchange and the right thing to do.

Move to the SHT31 and the identical two lines are two exchanges. Nothing in either library's documentation puts those two facts next to each other, and neither produces an error. You get right-looking numbers and a loop that is twice as slow as it should be.

The general lesson is duller and more useful than the specific one: when a library gives you two getters for two things that arrive together, find out whether calling both costs one fetch or two. Reading the source is usually quicker than guessing.

And put it on a timer

While you are here, the delay(2000) in the first reading is fine for a sketch that only prints and wrong for one that does anything else. The sensor has no minimum interval to respect — unlike a DHT, which refuses to answer inside one or two seconds — so read it as often as your project needs, and use a millis() timestamp rather than stopping the whole sketch:

unsigned long lastRead = 0;

void loop() {
  if (millis() - lastRead >= 2000) {
    lastRead = millis();
    // ... readBoth, print
  }
  // and everything else your sketch does, still running
}

When it does not work

How do I know the library is not caching?

Read it. Both readTemperature and readHumidity call the same private readTempHum, and readTempHum sends the measure command, waits 20 ms and reads six bytes, unconditionally. There is no timestamp anywhere in the class and no stored 'last result' to return — only a temp and a humidity that the next call overwrites.

Is there any harm in measuring twice?

Not to the sensor, and not to the numbers — 20 ms is nothing to a room. The harm is to your loop, which blocks for 42 ms instead of 21, and to a battery, which pays for two measurements to print one line. On a sketch that only prints every two seconds it genuinely does not matter; it is worth the habit anyway.

readBoth is not in my version of the library.

Update it from the Library Manager; readBoth is in 2.2.2, which is what this book is written against. There is no workaround from outside the class — the temp and humidity members are private — so on an older version two calls is genuinely the only option.

My old DHT sketch called both functions and it was fine.

It was, and that is exactly why this catches people. Adafruit's DHT library caches for 2000 ms, so the second call there returns the bytes the first one fetched and costs nothing. Same author, same shape of API, opposite behaviour — the only way to know is to read each one.

Should I put the reading on a timer instead of a delay?

Yes, for any sketch that does more than print. A 20 ms blocking read every two seconds is fine; a delay(2000) after it means your sketch cannot do anything else for two seconds. Keep a millis() timestamp and read when enough time has passed.

Where this goes next

The sensor's current, the power light's current, and which of the two decides how long a battery lasts.

What a reading costs

Edit this page — content/books/sht31/one-measurement-or-two.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

SHT31 Temperature and Humidity Sensor

Loading 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