-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathadafruit_shtc3.py
257 lines (199 loc) · 7.93 KB
/
adafruit_shtc3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2020 Bryan Siepert for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_shtc3`
================================================================================
A helper library for using the Sensirion SHTC3 Humidity and Temperature Sensor
* Author(s): Bryan Siepert
Implementation Notes
--------------------
**Hardware:**
* `Adafruit SHTC3 Temperature & Humidity Sensor
<https://www.adafruit.com/product/4636>`_ (Product ID: 4636)
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
* Adafruit's Bus Device library:
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
* Adafruit's Register library:
https://github.com/adafruit/Adafruit_CircuitPython_Register
"""
# imports
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SHTC3.git"
from struct import unpack_from
import time
from adafruit_bus_device import i2c_device
try:
from typing import Tuple
from busio import I2C
except ImportError:
pass
# include "Arduino.h"
# include <Adafruit_I2CDevice.h>
# include <Adafruit_Sensor.h>
_SHTC3_DEFAULT_ADDR = 0x70 # SHTC3 I2C Address
_SHTC3_NORMAL_MEAS_TFIRST_STRETCH = (
0x7CA2 # Normal measurement, temp first with Clock Stretch Enabled
)
_SHTC3_LOWPOW_MEAS_TFIRST_STRETCH = (
0x6458 # Low power measurement, temp first with Clock Stretch Enabled
)
_SHTC3_NORMAL_MEAS_HFIRST_STRETCH = (
0x5C24 # Normal measurement, hum first with Clock Stretch Enabled
)
_SHTC3_LOWPOW_MEAS_HFIRST_STRETCH = (
0x44DE # Low power measurement, hum first with Clock Stretch Enabled
)
_SHTC3_NORMAL_MEAS_TFIRST = (
0x7866 # Normal measurement, temp first with Clock Stretch disabled
)
_SHTC3_LOWPOW_MEAS_TFIRST = (
0x609C # Low power measurement, temp first with Clock Stretch disabled
)
_SHTC3_NORMAL_MEAS_HFIRST = (
0x58E0 # Normal measurement, hum first with Clock Stretch disabled
)
_SHTC3_LOWPOW_MEAS_HFIRST = (
0x401A # Low power measurement, hum first with Clock Stretch disabled
)
_SHTC3_READID = 0xEFC8 # Read Out of ID Register
_SHTC3_SOFTRESET = 0x805D # Soft Reset
_SHTC3_SLEEP = 0xB098 # Enter sleep mode
_SHTC3_WAKEUP = 0x3517 # Wakeup mode
_SHTC3_CHIP_ID = 0x807
class SHTC3:
"""
A driver for the SHTC3 temperature and humidity sensor.
:param ~busio.I2C i2c_bus: The I2C bus the SHTC3 is connected to.
**Quickstart: Importing and using the SHTC3 temperature and humidity sensor**
Here is an example of using the :class:`SHTC3`.
First you will need to import the libraries to use the sensor
.. code-block:: python
import board
import adafruit_shtc3
Once this is done, you can define your `board.I2C` object and define your sensor
.. code-block:: python
i2c = board.I2C() # uses board.SCL and board.SDA
sht = adafruit_shtc3.SHTC3(i2c)
Now you have access to the temperature and humidity using the :attr:`measurements`.
it will return a tuple with the :attr:`temperature` and :attr:`relative_humidity`
measurements
.. code-block:: python
temperature, relative_humidity = sht.measurements
"""
def __init__(self, i2c_bus: I2C) -> None:
self.i2c_device = i2c_device.I2CDevice(i2c_bus, _SHTC3_DEFAULT_ADDR)
self._buffer = bytearray(6)
self.low_power = False
self.sleeping = False
self.reset()
self._chip_id = self._get_chip_id()
if self._chip_id != _SHTC3_CHIP_ID:
raise RuntimeError("Failed to find an SHTC3 sensor - check your wiring!")
def _write_command(self, command: int) -> None:
"""helper function to write a command to the i2c device"""
self._buffer[0] = command >> 8
self._buffer[1] = command & 0xFF
with self.i2c_device as i2c:
i2c.write(self._buffer, start=0, end=2)
def _get_chip_id(self) -> int: # readCommand(SHTC3_READID, data, 3);
"""Determines the chip id of the sensor"""
self._write_command(_SHTC3_READID)
time.sleep(0.001)
with self.i2c_device as i2c:
i2c.readinto(self._buffer)
return unpack_from(">H", self._buffer)[0] & 0x083F
def reset(self) -> None:
"""Perform a soft reset of the sensor, resetting all settings to their power-on defaults"""
self.sleeping = False
try:
self._write_command(_SHTC3_SOFTRESET)
except RuntimeError as run_err:
if run_err.args and run_err.args[0] != "I2C device address was NACK'd":
raise run_err
time.sleep(0.001)
@property
def sleeping(self) -> bool:
"""Determines the sleep state of the sensor"""
return self._cached_sleep
@sleeping.setter
def sleeping(self, sleep_enabled: bool) -> None:
if sleep_enabled:
self._write_command(_SHTC3_SLEEP)
else:
self._write_command(_SHTC3_WAKEUP)
time.sleep(0.001)
self._cached_sleep = sleep_enabled
# lowPowerMode(bool readmode) { _lpMode = readmode
@property
def low_power(self) -> bool:
"""Enables the less accurate low power mode, trading accuracy for power consumption"""
return self._low_power
@low_power.setter
def low_power(self, low_power_enabled: bool) -> None:
self._low_power = low_power_enabled
@property
def relative_humidity(self) -> float:
"""The current relative humidity in % rH. This is a value from 0-100%."""
return self.measurements[1]
@property
def temperature(self) -> float:
"""The current temperature in degrees Celsius"""
return self.measurements[0]
@property
def measurements(self) -> Tuple[float, float]:
"""both `temperature` and `relative_humidity`, read simultaneously"""
self.sleeping = False
temperature = None
humidity = None
# send correct command for the current power state
if self.low_power:
self._write_command(_SHTC3_LOWPOW_MEAS_TFIRST)
time.sleep(0.001)
else:
self._write_command(_SHTC3_NORMAL_MEAS_TFIRST)
time.sleep(0.013)
# self._buffer = bytearray(6)
# read the measured data into our buffer
with self.i2c_device as i2c:
i2c.readinto(self._buffer)
# separate the read data
temp_data = self._buffer[0:2]
temp_crc = self._buffer[2]
humidity_data = self._buffer[3:5]
humidity_crc = self._buffer[5]
# check CRC of bytes
if temp_crc != self._crc8(temp_data) or humidity_crc != self._crc8(
humidity_data
):
return (temperature, humidity)
# decode data into human values:
# convert bytes into 16-bit signed integer
# convert the LSB value to a human value according to the datasheet
raw_temp = unpack_from(">H", temp_data)[0]
raw_temp = ((4375 * raw_temp) >> 14) - 4500
temperature = raw_temp / 100.0
# repeat above steps for humidity data
raw_humidity = unpack_from(">H", humidity_data)[0]
raw_humidity = (625 * raw_humidity) >> 12
humidity = raw_humidity / 100.0
self.sleeping = True
return (temperature, humidity)
## CRC-8 formula from page 14 of SHTC3 datasheet
# https://media.digikey.com/pdf/Data%20Sheets/Sensirion%20PDFs/HT_DS_SHTC3_D1.pdf
# Test data [0xBE, 0xEF] should yield 0x92
@staticmethod
def _crc8(buffer: bytearray) -> int:
"""verify the crc8 checksum"""
crc = 0xFF
for byte in buffer:
crc ^= byte
for _ in range(8):
if crc & 0x80:
crc = (crc << 1) ^ 0x31
else:
crc = crc << 1
return crc & 0xFF # return the bottom 8 bits