Files
mcp_screen/shtc3_util.py
T

86 lines
2.7 KiB
Python

import time
from machine import I2C, Pin
class SHTC3:
"""Utility class for Sensirion SHTC3 Temperature and Humidity Sensor."""
ADDR = 0x70
# Commands
WAKE = b'\x35\x17'
SLEEP = b'\xB0\x98'
MEASURE = b'\x78\x66' # High precision, T first, clock stretching disabled
def __init__(self, i2c=None):
if i2c is None:
# Default to ESP32-S3-RLCD-4.2 onboard I2C pins
self.i2c = I2C(0, sda=Pin(13), scl=Pin(14))
else:
self.i2c = i2c
def _crc8(self, data):
"""Sensirion CRC-8 checksum calculation (polynom 0x31, init 0xFF)."""
crc = 0xFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x80:
crc = (crc << 1) ^ 0x31
else:
crc <<= 1
crc &= 0xFF
return crc
def read_sensor(self):
"""Wakes up the sensor, reads temp and humidity, validates CRC, and sleeps.
Returns:
tuple: (temperature_c, relative_humidity_pct) or (None, None) on error.
"""
try:
# 1. Wakeup
self.i2c.writeto(self.ADDR, self.WAKE)
time.sleep_ms(1)
# 2. Trigger Measurement
self.i2c.writeto(self.ADDR, self.MEASURE)
time.sleep_ms(15) # High precision measurement takes up to 12.1ms
# 3. Read 6 bytes of data
# bytes 0, 1: Temp, byte 2: Temp CRC
# bytes 3, 4: Hum, byte 5: Hum CRC
data = self.i2c.readfrom(self.ADDR, 6)
# 4. Enter low-power sleep mode
self.i2c.writeto(self.ADDR, self.SLEEP)
# Verify CRC
t_data = data[0:2]
t_crc = data[2]
h_data = data[3:5]
h_crc = data[5]
if self._crc8(t_data) != t_crc:
print("SHTC3 Temp CRC error")
return None, None
if self._crc8(h_data) != h_crc:
print("SHTC3 Hum CRC error")
return None, None
raw_t = (data[0] << 8) | data[1]
raw_h = (data[3] << 8) | data[4]
# Formula from datasheet
temp = -45.0 + 175.0 * (raw_t / 65536.0)
hum = 100.0 * (raw_h / 65536.0)
return round(temp, 2), round(hum, 2)
except Exception as e:
print(f"Error reading SHTC3 sensor: {e}")
# Try to send sleep command anyway to save power
try:
self.i2c.writeto(self.ADDR, self.SLEEP)
except:
pass
return None, None