One command, six bytes
One library call is two separate conversations with a twelve-millisecond gap in the middle. Almost none of the time a reading takes is spent moving data, which is the fact the rest of this chapter and the next one both rest on.
Two conversations, not one
readBoth() looks like one function call and is two exchanges on the bus with
a wait between them.
First, your board writes three bytes: the sensor's address with the write
bit, then the two halves of one 16-bit command. 0x2400 means measure once,
at high repeatability, and do not stretch the clock. The sensor acknowledges
each byte, and the acknowledgement of the command is what starts the
measurement.
Then the bus goes quiet. The sensor is busy. It has up to 15 ms and typically takes 12.5; Adafruit's library simply waits 20 ms, which is safely past the maximum.
Finally your board writes the address again, this time with the read bit, and the sensor sends six bytes.
Where the time goes
At the 100 kHz every Arduino core starts Wire at, one byte costs nine clock
pulses — eight of data and one for the acknowledge — so it takes 90 µs.
| Bytes | Time | |
|---|---|---|
| Command out | 3 | 0.27 ms |
| Six bytes back, plus the address | 7 | 0.63 ms |
| The wait | — | 12.5 ms |
The traffic is under a millisecond. The wait is more than ten times all of it put together, and it is the sensor's own physics rather than anything about the bus — so running the bus at 400 kHz makes a reading about 0.7 ms faster out of 21, which is nothing.
That ratio is why the library's twenty-millisecond wait is worth knowing about, and why taking two measurements when you needed one costs so much.
The order the bytes come in
Six bytes, in this order:
- Temperature, high byte
- Temperature, low byte
- A checksum over those two
- Humidity, high byte
- Humidity, low byte
- A checksum over those two
Temperature comes first. This catches people out constantly, because nearly every library, example and tutorial prints humidity first — so the order in the serial monitor is the reverse of the order on the wire. If you ever decode the six bytes yourself, that is the mistake to expect.
The clock-stretching alternative
The sensor offers each measurement command twice: once with clock stretching and once without.
With stretching, the sensor answers the read header immediately and then holds SCL down until the measurement is finished. Your read blocks, the sensor releases the line when it is ready, and nobody has to guess a delay.
It sounds strictly better and is not. A device holding the clock down is something the host's I²C hardware has to be prepared for, and not every implementation is — the failure is a hang rather than an error. Adafruit's library sends the non-stretching command and waits, and that is why it works on everything.
Two more commands worth knowing
Beyond measuring, three commands come up:
- Soft reset,
0x30A2. The only reset this board has, since nRESET is not brought out to the header.sht.reset()sends it. - Read status,
0xF32D. A 16-bit register with a heater bit, an alert bit and a flag saying whether the last command was accepted.sht.readStatus(). - Heater on and off,
0x306Dand0x3066. There is a heating element inside the sensor and the datasheet is emphatic that it is for plausibility checking only — switch it on, watch the temperature rise a few degrees and the humidity fall, and you have proved both elements are alive. It is not a way to dry the sensor out, and leaving it on makes every reading wrong. It is off after a reset.
When it does not work
Because there is nothing to read until you ask. The sensor is idle between measurements — a fifth of a microamp idle — and takes a measurement only when a command tells it to. Reading it without a command gets a NACK, which the library reports as a failed read.
An alternative to waiting. With stretching enabled the sensor holds SCL down until the measurement is finished, so your read blocks instead of you timing it. Adafruit's library always sends the non-stretching command and waits 20 ms, which is the safer choice: not every microcontroller's I²C hardware handles a device holding the clock, and the ones that do not simply hang.
The sensor can — there are commands for low and medium repeatability, 2.5 ms and 4.5 ms — but this library cannot. readTempHum always sends 0x2400, the high-repeatability one, whatever you do. Getting the others means writing the two command bytes yourself with Wire.
Not in this mode. Single-shot means one command produces exactly one data pair and then the sensor goes idle again. The sensor also has a periodic mode where one command starts a stream at up to ten readings a second, and this library does not use it.
Two bytes, one straight line and a checksum that turns a corrupted reading into no reading at all.
From bytes to degrees →Edit this page — content/books/sht31/one-command-six-bytes.mdx
Questions about this product
See what other owners have asked, and read their solutions.
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.