Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

SHT40 with Raspberry Pi Pico 2 W — MicroPython humidity with heater

Read an SHT40 on Pico 2 W I2C0 (GP4/GP5) in MicroPython with CRC checks, and use its built-in heater to dry condensation in monsoon humidity.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The SHT40 is Sensirion’s small, accurate temperature and humidity sensor (±0.2 °C, ±1.8 % RH) and a step up from the SHT31 at a similar price. On a Pico 2 W it sits on I2C0 (GP4/GP5) at 3V3 and needs no library.

The script prints a CRC-checked reading every two seconds and uses the sensor’s own heater when monsoon humidity leaves it soaked.

Wiring

Raspberry Pi Pico 2 WOnly the pins used are shown · 3.3 V logicSHT40 temperature and humidity sensorGNDGP4GP53V3VCCGNDSCLSDA
Every connection
Raspberry Pi Pico 2 WSHT40 temperature and humidity sensorWireNotes
3V3VCCred3V3 is pin 36. Plain 4-pin SHT40 boards have no regulator — 3.3 V only.
GNDGNDblack
GP5SCLyellowGP5 is physical pin 7 (I2C0 SCL).
GP4SDAblueGP4 is physical pin 6 (I2C0 SDA).

3.3 V (boards with a regulator: 3.3–5 V) part, 3.3 V board. The chip is 1.08–3.6 V only. Boards with a regulator and level shifting (Adafruit-style, with a VIN pin) accept 5 V. Plain 4-pin clones often have neither — power them from 3.3 V and keep SDA/SCL at 3.3 V; on an Uno use a level shifter.

Board quirks

  • The SHT40 takes one-byte commands: 0xFD measures with high precision in about 9 ms, and six bytes come back with two CRCs.
  • Humidity uses the SHT4x formula −6 + 125 × raw/65535, which can stray just outside 0–100 %; the script clamps it.
  • After a minute at ~100 % RH the script fires the built-in heater (0x39: 200 mW for 1 s) to drive off condensation, then waits for it to cool. Don’t run the heater continuously.
  • Clone boards without a regulator are 3.3 V-only. The Pico 2 W’s inputs tolerate 5 V while powered, but the sensor itself does not.

Code

main.pyMicroPython
# SHT40 temperature + humidity on a Raspberry Pi Pico 2 W (MicroPython, no library).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, SCL -> GP5 (pin 7), SDA -> GP4 (pin 6). I2C0.
# Address 0x44 (SHT40-AD1B, most boards) or 0x45 (SHT40-BD1B).
# In monsoon humidity the sensor can stay wet with condensation; the built-in heater dries it.
from machine import Pin, I2C
import time

i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400_000)
found = i2c.scan()
addr = 0x44 if 0x44 in found else (0x45 if 0x45 in found else None)
if addr is None:
    raise SystemExit("No SHT40 at 0x44/0x45 - found {}".format([hex(a) for a in found]))


def crc8(data):  # Sensirion CRC-8: polynomial 0x31, init 0xFF
    crc = 0xFF
    for b in data:
        crc ^= b
        for _ in range(8):
            crc = ((crc << 1) ^ 0x31) & 0xFF if crc & 0x80 else (crc << 1) & 0xFF
    return crc


def measure(cmd=0xFD, wait_ms=10):
    """0xFD = high precision (~9 ms). 0x39 = heater 200 mW for 1 s, then measure."""
    i2c.writeto(addr, bytes([cmd]))
    time.sleep_ms(wait_ms)
    d = i2c.readfrom(addr, 6)
    if crc8(d[0:2]) != d[2] or crc8(d[3:5]) != d[5]:
        raise OSError("CRC mismatch")
    t = -45 + 175 * ((d[0] << 8) | d[1]) / 65535
    rh = -6 + 125 * ((d[3] << 8) | d[4]) / 65535
    return t, min(max(rh, 0.0), 100.0)


i2c.writeto(addr, b"\x94")  # soft reset
time.sleep_ms(2)
i2c.writeto(addr, b"\x89")  # read serial number
time.sleep_ms(2)
s = i2c.readfrom(addr, 6)
print("SHT40 at {}  serial {:02X}{:02X}{:02X}{:02X}".format(hex(addr), s[0], s[1], s[3], s[4]))

wet_count = 0
while True:
    try:
        t, rh = measure()
        print("Temp {:.2f} C  Humidity {:.1f} %".format(t, rh))
        wet_count = wet_count + 1 if rh > 95 else 0
        if wet_count >= 30:  # a minute of ~100 % RH: probably condensation on the sensor
            print("Running the heater for 1 s to dry the sensor...")
            measure(0x39, 1100)
            time.sleep(10)  # let it cool before trusting the next reading
            wet_count = 0
    except OSError as e:
        print("Read failed:", e)
    time.sleep(2)

Expected serial output

REPL / Thonny shellOutput
SHT40 at 0x44  serial 0F3A9C12
Temp 27.86 C  Humidity 71.4 %
Temp 27.85 C  Humidity 71.3 %

Common errors

No SHT40 at 0x44/0x45

Check the wiring and 3V3. Some boards mark SDA/SCL in the opposite order to the photo — follow the silkscreen.

Humidity stuck at 100 %

Water on the sensor. Let the heater cycle run, and mount it with the opening facing down, out of rain.

↑↓ to move · Enter to open