Skip to content

Commit c0ae251

Browse files
committed
drivers/sensor/sht: Add driver for SHT3x/SHT4x sensors
1 parent 66fa62b commit c0ae251

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
metadata(description="SHT3x/SHT4x temperature/humidity sensor driver.", version="0.1.0")
2+
3+
module("sht.py", opt=3)

micropython/drivers/sensor/sht/sht.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Micropython driver for temperature/humidity sensors SHT3x/SHT4x
2+
#
3+
# Example usage on picoboard:
4+
# @code{.py}
5+
# from machine import Pin, I2C
6+
# from sht import SHT
7+
# import time
8+
# i2c = I2C(0, scl=Pin(5), sda=Pin(4))
9+
# sensor = SHT(i2c)
10+
# sensor.start_measure(2)
11+
# while True:
12+
# time.sleep(0.01)
13+
# t_raw, t_val, h_raw, h_val, isvalid = sensor.get_measure_results()
14+
# if isvalid is not None:
15+
# break
16+
# print(f'{t_raw}, {t_val} °C, {h_raw}, {h_val} %RH, isvalid')
17+
# @endcode
18+
#
19+
20+
from machine import I2C
21+
import time
22+
23+
24+
class SHT:
25+
26+
SHT3x = (0x30)
27+
SHT4x = (0x40)
28+
29+
# Init SHT
30+
# @param i2c I2C interface
31+
# @param addr I2C addr (default = 0x44)
32+
# @param sht SHT type
33+
# 0x00 (autodetect SHT type)
34+
# self.SHT3x
35+
# self.SHT4x
36+
def __init__(self, i2c, addr=0x44, sht=0x00):
37+
self.i2c = i2c
38+
self.i2c_addr = addr
39+
self.sht = sht
40+
if self.sht == 0x00:
41+
self.sht = self.detect_sht_type()
42+
else:
43+
self.sht = sht
44+
45+
# Verify checksum
46+
# @param data data bytes
47+
# @param checksum received crc
48+
# @return crc status
49+
# 0 = crc does not match
50+
# 1 = crc ok
51+
def _check_crc(self, data, checksum):
52+
crc = 0xFF
53+
for byte in data:
54+
crc ^= byte
55+
for _ in range(8):
56+
if crc & 0x80:
57+
crc = (crc << 1) ^ 0x31
58+
else:
59+
crc = crc << 1
60+
crc = crc & 0xFF
61+
return checksum == crc
62+
63+
# Autodetect SHT type
64+
# @return SHT type
65+
# self.SHT3x = SHT30/31/35
66+
# self.SHT4x = SHT40/41/45
67+
# 0xFF = unknown
68+
def detect_sht_type(self):
69+
sht = 0xFF
70+
# try reading status of SHT3x
71+
try:
72+
self.i2c.writeto(self.i2c_addr, b'\xF3\x2D', False)
73+
time.sleep(0.01)
74+
response = self.i2c.readfrom(self.i2c_addr, 3)
75+
if self._check_crc(response[0:2],response[2]):
76+
sht = self.SHT3x
77+
except OSError as error :
78+
pass
79+
if sht == 0xFF:
80+
# try reading serial number of SHT4x
81+
try:
82+
self.i2c.writeto(self.i2c_addr, b'\x89', False)
83+
time.sleep(0.01)
84+
response = self.i2c.readfrom(self.i2c_addr, 6)
85+
if self._check_crc(response[3:5],response[5]):
86+
sht = self.SHT4x
87+
except OSError as error :
88+
pass
89+
return sht
90+
91+
# Start measurement
92+
# @param precision 0..2 [Low, Medlium, High]
93+
# @return None
94+
def start_measure(self, precision):
95+
if self.sht == self.SHT3x:
96+
p_byte = [b'\x16',b'\x0B',b'\x00']
97+
self.i2c.writeto(self.i2c_addr, b'\x24' + p_byte[precision], False)
98+
if self.sht == self.SHT4x:
99+
cmd = [b'\xE0',b'\xF6',b'\xFD']
100+
self.i2c.writeto(self.i2c_addr, cmd[precision], False)
101+
102+
# Get the measurement values
103+
# @details
104+
# As long as no values available all return parameter are None.
105+
# If values not equal None are returned the measurement has been completed
106+
# and needs to be restarted again for a new measurement.
107+
# @return temperature[raw], temperature[°C], humidity[raw], humidity[%RH]
108+
def get_measure_results(self):
109+
try:
110+
response = self.i2c.readfrom(self.i2c_addr, 6)
111+
t_bytes = response[0:2]
112+
t_raw = int.from_bytes(t_bytes, "big")
113+
t_val = (175 * t_raw) / 0xFFFF - 45
114+
isvalid = self._check_crc(t_bytes,response[2])
115+
h_bytes = response[3:5]
116+
h_raw = int.from_bytes(h_bytes, "big")
117+
h_val = (100 * h_raw) / 0xFFFF
118+
isvalid &= self._check_crc(h_bytes,response[5])
119+
return t_raw, round(t_val,2), h_raw, round(h_val,2), bool(isvalid)
120+
except OSError as error :
121+
# OSError: [Errno 5] EIO as long as measurement has not completed
122+
return None, None, None, None, None

0 commit comments

Comments
 (0)