SHT31/Getting a reading/06. The first reading
Getting a reading · 06 of 11

The first reading

Four wires, one library and about twenty lines. The build is genuinely this short. The work is in getting the four wires right, because several of the ways this board fails look identical from the serial monitor.

The four wires

Four wires
Your board
Wires
4
Supply
3V3
Bus
I²C
Feed VCC from 3V3, not from 5V. The board's pull-ups tie SDA and SCL to whatever is on VCC, so a 5 V supply would sit 5 V on two pins rated for 3.3 V — it appears to work, which is the problem. The sensor is specified from 2.15 V, so 3V3 costs you nothing.

GND first. It is the pin on the square pad, and it is the one whose absence produces the most confusing failure — the power light can still come on, borrowing a return path through the signal lines, so the board looks alive while nothing answers.

Then VCC, and it is 3V3 on anything that is not an Uno. The board's two pull-ups tie SDA and SCL to VCC, so a 5 V supply idles both signal lines at 5 V against pins rated for 3.3 V.

Then SDA and SCL, to whichever pins your board's I²C hardware lives on. Get these two swapped and everything still looks right: both lines idle high, because both have a pull-up on them. Nothing is wrong except that your board is clocking the sensor's data pin.

Scan before you sketch

Run an I²C scanner once, before the sensor sketch. It is the single most useful thirty seconds in this whole chapter, because it separates "the wiring is wrong" from "the code is wrong" — two problems that look the same from the serial monitor and have nothing to do with each other.

A working board reports one device at 0x44. Anything else and the sketch below cannot help you: go to when the scan finds nothing.

The sketch

Two lines in it are worth reading twice.

sht.begin(SHT31_ADDR) returns a bool, and checking it is the difference between a clear message now and a stream of NaNs later. It brings the I²C bus up itself, on whatever pins your board calls SDA and SCL by default, so there is no Wire.begin() in the sketch at all.

sht.readBoth(&celsius, &humidity) takes one measurement and gives you both numbers out of it. The obvious alternative — readTemperature() then readHumidity() — takes two, twenty milliseconds apart, and nothing anywhere warns you. That is one measurement or two.

What you should see

Something close to the room, arriving every two seconds:

SHT31 found
22.59 C  48.29 %
22.61 C  48.27 %
22.60 C  48.34 %

Two decimal places, because that is the resolution. Roughly one of them is trustworthy, because that is the accuracy. Breathe on the board and the humidity climbs within a few seconds and takes a good deal longer to come back down — which is the 8-second response time doing exactly what it says.

If the temperature reads a degree or two above the room, that is not the sketch. It is where the board is sitting.

The code

sht31_first_reading.ino

One library, one address and one call that fetches both numbers. Install Adafruit SHT31 Library from the Library Manager and accept Adafruit BusIO when the IDE offers it.

/*
  SHT31 - first reading                                 TK120 / /p/tk120

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

    GND -> GND
    VCC -> 3V3      (5V on an Arduino Uno. Never 5V beside a 3.3 V board:
                     the board's pull-ups put VCC on both signal lines.)
    SDA -> GPIO 8   (Uno A4, ESP32 GPIO 21, ESP32-S3 GPIO 8, Pico GP4)
    SCL -> GPIO 9   (Uno A5, ESP32 GPIO 22, ESP32-S3 GPIO 9, Pico GP5)

  Arduino IDE
    Tools > Board                 ESP32S3 Dev Module
    Tools > Port                  the one that appears when you plug in
    Tools > USB CDC On Boot       Enabled
    Library Manager               "Adafruit SHT31 Library" by Adafruit,
                                  and accept "Adafruit BusIO" with it
*/

#include <Adafruit_SHT31.h>

// 0x44 is what a board answers to straight out of the bag, because R3
// holds the sensor's ADDR pin at ground. Bridge the ADDR pads on the
// back and it becomes 0x45.
#define SHT31_ADDR 0x44

Adafruit_SHT31 sht;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);        // native-USB boards: wait for the monitor

  // begin() brings up Wire itself, on whatever this board's default SDA
  // and SCL pins are. For other pins, call Wire.begin(sda, scl) first.
  if (!sht.begin(SHT31_ADDR)) {
    Serial.println("no SHT31 at 0x44 - check GND first, then SDA and SCL");
    while (true) delay(100);
  }

  Serial.println("SHT31 found");
}

void loop() {
  float celsius, humidity;

  // One command, one wait, one set of six bytes, both numbers.
  if (sht.readBoth(&celsius, &humidity)) {
    Serial.print(celsius);
    Serial.print(" C  ");
    Serial.print(humidity);
    Serial.println(" %");
  } else {
    // A checksum that did not match, or nothing on the bus at all. One
    // failure now and then is normal; every time is the wiring.
    Serial.println("read failed");
  }

  delay(2000);
}

readBoth is doing the work here, and it is deliberate: it takes one measurement and hands back both numbers. Calling readTemperature and then readHumidity would take two, and the article 'One measurement or two' is about why that is not obvious. The bool it returns is the failed read, which is why there is no isnan check anywhere in this sketch.

When it does not work

It prints no SHT31 at 0x44 every time.

Nothing acknowledged. Check GND first, because without it the sensor has no reference and may still light its power LED. Then check that SDA and SCL are not swapped — both lines idle high either way, so the board looks perfectly normal. Then check VCC is on a rail that is actually powered rather than a spare hole.

The scanner finds 0x44 but the sketch says no SHT31.

Almost always the library. Make sure it is Adafruit SHT31 Library and that Adafruit BusIO installed with it — begin returns false if the I²C device cannot be created, not only if the sensor is absent. Reinstall both from the Library Manager and recompile.

It compiles but the serial monitor stays empty.

On an ESP32-S3 or any native-USB board, set Tools > USB CDC On Boot to Enabled and reflash. Without it the USB serial port is not brought up at boot and the sketch is running perfectly with nowhere to print. Check the monitor's baud rate is 115200 too.

Every reading is 'read failed' but begin succeeded.

The sensor answered the address and its six bytes are not surviving the wires — one of the two checksums failed. Shorten the jumper wires, take it off a breadboard if you can, and if you set the bus to 400 kHz put it back to 100 kHz. Occasional failures are normal and worth retrying; constant ones are the bus.

Can I use different pins for SDA and SCL?

On an ESP32 or ESP32-S3, yes — call Wire.begin(sdaPin, sclPin) before sht.begin() and any two free GPIOs will do. On an Uno or a Pico the I²C hardware is wired to particular pins, and those are the ones in the comment header.

Where this goes next

What that one library call put on the bus, and why almost all of the time it took was spent waiting.

One command, six bytes

Edit this page — content/books/sht31/the-first-reading.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