Temperature and humidity

SHT31 with ESP32 and Arduino: Wiring, Code and I2C Errors

Connect an SHT31 to ESP32 or Arduino, check I2C addresses and CRC, and diagnose temperature or humidity errors using the official datasheet.

Contents

The SHT31-DIS measures temperature and relative humidity over I2C. For an ESP32 starting circuit, use a compatible module at 3.3 V, common ground, SDA/SCL with pull-ups to 3.3 V, and address 0x44 or 0x45. Check the actual module schematic: a regulator does not automatically make its I2C pins safe at every voltage.

Real photo of the original Adafruit SHT31-D breakout with a pin header, without STEMMA QT connectors.
Original header-only Adafruit SHT31-D breakout, not the newer STEMMA QT board. Image “adafruit_products_2857_kit_ORIG.jpg”, lady ada / Adafruit; source and permission, CC BY-SA 3.0. Native 800px display version; no local content edits. Not an LCENJ hardware-test photo.

Choose the sensor and module separately

The SHT30, SHT31 and SHT35 share much of their interface but have different accuracy specifications. Check the exact order code rather than treating every board marked “SHT3x” as the same product. The bare chip's supply specification is not a guarantee for an assembled breakout board.

SHT31-DIS is useful for indoor monitoring, data logging and environmental control. It does not measure air pressure or gas concentration. For temperature only, compare the DS18B20 and its 1-Wire interface. Follow the temperature and humidity learning path for selection and installation guidance.

Accuracy is different from resolution

The familiar typical figures are ±2%RH and ±0.2°C within the relevant datasheet conditions, not guaranteed limits across the entire operating range. Read the accuracy curves for your application. Repeatability describes variation between repeated readings; extra decimal places do not establish better absolute accuracy. See accuracy, resolution and calibration.

The specified temperature range is −40 to +125°C and humidity range is 0–100%RH. For long-term stability, Sensirion identifies a normal operating region of 5–60°C and 20–80%RH. Extended exposure outside it, particularly at high humidity, can cause a temporary offset. Range and accuracy are separate questions.

Wiring and the I2C address

Existing SHT31 pinout and example I2C connection diagram.
LCENJ educational diagram: match the exact chip package and breakout revision. Place 100 nF close to VDD and VSS.
SignalArduino Uno exampleESP32 example
SupplyAccording to the breakout board specification3.3 V on a compatible board
GroundGNDGND
SDAA4Board-selected SDA; GPIO21 is common on classic ESP32 boards
SCLA5Board-selected SCL; GPIO22 is common on classic ESP32 boards

These ESP32 pins are examples, not a universal mapping for ESP32-S3, C3 or every development board. Use Wire.begin(SDA_PIN, SCL_PIN) when appropriate. For the bare chip, ADDR low selects 0x44 and ADDR high selects 0x45. Follow the pin drawing for the exact package.

I2C needs pull-up resistors. Check whether the module already includes them before adding more. Parallel pull-ups lower the total resistance; their voltage, total bus capacitance and clock speed all matter. Keep a 100 nF bypass capacitor close to the chip supply pins in a custom design. An address scan confirms a response, not a valid temperature measurement. Use the ESP32 I2C troubleshooting guide if the device is missing or communication is intermittent.

Measurement commands, conversion and CRC

Single-shot mode takes one measurement on request. Periodic mode measures repeatedly and is read with a fetch command. Choose a rate that meets the application need; unnecessary repeated measurements can increase self-heating.

Single-shot modeHigh repeatabilityMediumLow
No clock stretching0x24000x240B0x2416
Clock stretching0x2C060x2C0D0x2C10
SHT31 six-byte measurement response: temperature, CRC, humidity, CRC.
Two temperature bytes and CRC, followed by two humidity bytes and CRC; based on the SHT3x-DIS datasheet.

A complete read contains two temperature bytes, their CRC, two humidity bytes and their CRC. For unsigned 16-bit raw values: T = −45 + 175 × rawT / 65535 in °C and RH = 100 × rawRH / 65535 in %RH. Validate each pair with CRC-8 polynomial 0x31, initialization 0xFF. A successful I2C transfer alone does not validate the contents.

Arduino example using Adafruit SHT31

Install the Adafruit SHT31 library and its dependencies using Library Manager. Wire the board, confirm its address, and set the serial monitor to 115200 baud. The example reports a failed reading instead of printing it as new data.

#include <Wire.h>
#include <Adafruit_SHT31.h>

Adafruit_SHT31 sht31 = Adafruit_SHT31();

void setup() {
  Serial.begin(115200);
  Wire.begin();
  if (!sht31.begin(0x44)) {
    Serial.println("SHT31 not found");
    while (true) delay(10);
  }
}

void loop() {
  const float temperature = sht31.readTemperature();
  const float humidity = sht31.readHumidity();

  if (!isnan(temperature) && !isnan(humidity)) {
    Serial.print("T: "); Serial.print(temperature, 2); Serial.print(" C | RH: "); Serial.print(humidity, 2); Serial.println(" %");
  } else {
    Serial.println("Read error");
  }
  delay(2000);
}

Direct ESP32 reading with Wire

This example sends 0x2400, waits 15 ms for high-repeatability conversion, reads six bytes and checks both CRC values. The output statements belong inside the success branch. Adapt the board's I2C pins before use. The snippet has been reviewed; no physical measurement is claimed here.

#include <Wire.h>

constexpr uint8_t SHT31_ADDRESS = 0x44;

uint8_t crc8(const uint8_t *data, size_t len) {
  uint8_t crc = 0xFF;
  for (size_t i = 0; i < len; ++i) {
    crc ^= data[i];
    for (uint8_t bit = 0; bit < 8; ++bit)
      crc = (crc & 0x80) ? (crc << 1) ^ 0x31 : (crc << 1);
  }
  return crc;
}

bool readSHT31(float &t, float &rh) {
  Wire.beginTransmission(SHT31_ADDRESS);
  Wire.write(0x24);
  Wire.write(0x00);
  if (Wire.endTransmission() != 0) return false;

  delay(15);
  if (Wire.requestFrom(SHT31_ADDRESS, (uint8_t)6) != 6) return false;
  uint8_t data[6];
  for (uint8_t &byte : data) byte = Wire.read();
  if (crc8(data, 2) != data[2] || crc8(data + 3, 2) != data[5]) return false;

  const uint16_t rawT = (uint16_t(data[0]) << 8) | data[1];
  const uint16_t rawRH = (uint16_t(data[3]) << 8) | data[4];
  t = -45.0f + 175.0f * rawT / 65535.0f;
  rh = 100.0f * rawRH / 65535.0f;
  return true;
}

void setup() {
  Serial.begin(115200);
  Wire.begin();
}

void loop() {
  float temperature, humidity;
  if (readSHT31(temperature, humidity)) {
    Serial.print("T: "); Serial.print(temperature, 2); Serial.print(" C | RH: "); Serial.print(humidity, 2); Serial.println(" %");
  } else {
    Serial.println("I2C or CRC error");
  }
  delay(2000);
}

Download the reviewed Arduino and ESP32 examples (2026-10-17). Older full-article ZIP downloads below retain their original Persian content.

Why readings differ from the room

Keep the sensing opening away from the processor, regulator, display and other heat sources. Allow ambient air to reach it; a closed box changes response time. Solvents, adhesives and contamination can affect the humidity element. The internal heater warms the sensor: readings taken while it is active should not be treated as undisturbed ambient conditions. It does not replace a sound enclosure design.

SymptomCheck first
No sensor foundSupply, common ground, swapped SDA/SCL, pull-ups and address.
Temperature consistently highBoard heat, heater state, mounting location and sample rate.
Humidity changes slowly or appears biasedAir exchange, condensation, contamination and reference conditions.
Random read failuresCRC, cable length, supply decoupling, bus waveform and pull-up loading.

For a comparison, place a suitable reference nearby, allow both to stabilize, and record their location and conditions. This is a proposed procedure, not a reported test. Follow troubleshooting temperature and humidity errors before applying a software offset.

Sources and further reading

These instructions do not certify the authenticity, waterproofing or performance of a third-party module.

Question and answer article

Ask your technical question

Questions and answers are published after moderation. Authors can see their own pending drafts.

No confirmed questions have been registered for this article yet.