|
34 | 34 | __version__ = "0.0.0-auto.0"
|
35 | 35 | __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_SHTC3.git"
|
36 | 36 |
|
37 |
| -# Common imports remove if unused or pylint will complain |
38 |
| -from time import sleep as delay_seconds |
39 |
| -from time import monotonic |
40 |
| -import adafruit_bus_device.i2c_device as i2c_device |
41 |
| - |
42 |
| -from adafruit_register.i2c_struct import UnaryStruct, ROUnaryStruct, Struct |
43 |
| -from adafruit_register.i2c_bit import RWBit, ROBit |
44 |
| -from adafruit_register.i2c_bits import RWBits |
45 | 37 | from struct import unpack_from
|
46 |
| -#include "Arduino.h" |
47 |
| -#include <Adafruit_I2CDevice.h> |
48 |
| -#include <Adafruit_Sensor.h> |
49 |
| - |
50 |
| -_SHTC3_DEFAULT_ADDR = 0x70 # SHTC3 I2C Address |
51 |
| -_SHTC3_NORMAL_MEAS_TFIRST_STRETCH = 0x7CA2 # Normal measurement, temp first with Clock Stretch Enabled |
52 |
| -_SHTC3_LOWPOW_MEAS_TFIRST_STRETCH = 0x6458 # Low power measurement, temp first with Clock Stretch Enabled |
53 |
| -_SHTC3_NORMAL_MEAS_HFIRST_STRETCH = 0x5C24 # Normal measurement, hum first with Clock Stretch Enabled |
54 |
| -_SHTC3_LOWPOW_MEAS_HFIRST_STRETCH = 0x44DE # Low power measurement, hum first with Clock Stretch Enabled |
55 |
| - |
56 |
| -_SHTC3_NORMAL_MEAS_TFIRST = 0x7866 # Normal measurement, temp first with Clock Stretch disabled |
57 |
| -_SHTC3_LOWPOW_MEAS_TFIRST = 0x609C # Low power measurement, temp first with Clock Stretch disabled |
58 |
| -_SHTC3_NORMAL_MEAS_HFIRST = 0x58E0 # Normal measurement, hum first with Clock Stretch disabled |
59 |
| -_SHTC3_LOWPOW_MEAS_HFIRST = 0x401A # Low power measurement, hum first with Clock Stretch disabled |
60 |
| - |
61 |
| -_SHTC3_READID = 0xEFC8 # Read Out of ID Register |
62 |
| -_SHTC3_SOFTRESET = 0x805D # Soft Reset |
63 |
| -_SHTC3_SLEEP = 0xB098 # Enter sleep mode |
64 |
| -_SHTC3_WAKEUP = 0x3517 # Wakeup mode |
65 |
| -_SHTC3_CHIP_ID = 0x807 |
66 |
| -def pb(buffer): |
67 |
| - print("buf:", [hex(i) for i in buffer]) |
68 |
| - |
69 |
| -class SHTC3: |
70 |
| - def __init__(self, i2c_bus, address = _SHTC3_DEFAULT_ADDR): |
71 |
| - self.i2c_device = i2c_device.I2CDevice(i2c_bus, address) |
72 |
| - |
73 |
| - self._buffer = bytearray(6) |
74 |
| - self.reset() |
75 |
| - self.sleep = False |
76 |
| - if (self._chip_id & 0x083F != _SHTC3_CHIP_ID): |
77 |
| - raise RuntimeError("Failed to find an ICM20X sensor - check your wiring!") |
78 |
| - |
| 38 | +import time |
| 39 | +import adafruit_bus_device.i2c_device as i2c_device |
79 | 40 |
|
80 |
| - def _write_command(self, command): |
81 |
| - self._buffer[0] = command >> 8 |
82 |
| - self._buffer[1] = command & 0xFF |
83 |
| - |
84 |
| - with self.i2c_device as i2c: |
85 |
| - i2c.write(self._buffer, start=0, end=2) |
86 |
| - |
87 |
| - @property |
88 |
| - def _chip_id(self): # readCommand(SHTC3_READID, data, 3); |
89 |
| - self._buffer[0] = _SHTC3_READID >> 8 |
90 |
| - self._buffer[1] = _SHTC3_READID & 0xFF |
91 |
| - |
92 |
| - with self.i2c_device as i2c: |
93 |
| - i2c.write_then_readinto(self._buffer, self._buffer, out_start=0, out_end=2, in_start=0, in_end=2) |
94 |
| - |
95 |
| - return unpack_from(">H", self._buffer)[0] |
96 |
| - |
97 |
| - def reset(self): |
98 |
| - try: |
99 |
| - self._write_command(_SHTC3_SOFTRESET) |
100 |
| - |
101 |
| - except RuntimeError as run_err: |
102 |
| - if run_err.args and run_err.args[0] != "I2C slave address was NACK'd": |
103 |
| - raise run_err |
104 |
| - delay_seconds(0.001) |
105 |
| - |
106 |
| - @property |
107 |
| - def sleep(self): |
108 |
| - """Determines the sleep state of the sensor""" |
109 |
| - return self._cached_sleep |
110 |
| - |
111 |
| - @sleep.setter |
112 |
| - def sleep(self, sleep_enabled): |
113 |
| - if sleep_enabled: |
114 |
| - self._write_command(_SHTC3_SLEEP) |
115 |
| - else: |
116 |
| - self._write_command(_SHTC3_WAKEUP) |
117 |
| - delay_seconds(0.001) |
118 |
| - self._cached_sleep = sleep_enabled |
119 |
| - |
120 |
| -# lowPowerMode(bool readmode) { _lpMode = readmode |
121 |
| - |
122 |
| - @property |
123 |
| - def relative_humidity(self): |
124 |
| - """Current relative humidity in % rH""" |
125 |
| - self.measurements[1] |
126 |
| - return self._humidity |
127 |
| - |
128 |
| - @property |
129 |
| - def temperature(self): |
130 |
| - """Current temperature in degrees celcius""" |
131 |
| - self.measurements[0] |
132 |
| - |
133 |
| - @property |
134 |
| - def measurements(self): |
135 |
| - """both `temperature` and `relative_humidity`, read simultaneously""" |
136 |
| - |
137 |
| - self.sleep = False |
138 |
| - raw_readings = [] |
139 |
| - |
140 |
| - if False: # check for lowPower |
141 |
| - self._write_command(_SHTC3_LOWPOW_MEAS_TFIRST) |
142 |
| - delay_seconds(0.001) |
143 |
| - else: |
144 |
| - self._write_command(_SHTC3_NORMAL_MEAS_TFIRST) |
145 |
| - delay_seconds(0.013) |
146 |
| - |
147 |
| - self._buffer = bytearray(6) |
148 |
| - with self.i2c_device as i2c: |
149 |
| - i2c.readinto(self._buffer) |
150 |
| - raw_readings = unpack_from(">hbh", self._buffer) |
151 |
| - |
152 |
| - |
153 |
| - # check CRC of bytes |
154 |
| - # if (self._buffer[2] != crc8(self._buffer, 2) or |
155 |
| - # self._buffer[5] != crc8(self._buffer + 3, 2)): |
156 |
| - # print("NOT CHECKING") |
157 |
| - |
158 |
| - raw_temp = raw_readings[0] |
159 |
| - raw_temp = ((4375 * raw_temp) >> 14) - 4500 |
160 |
| - temperature = raw_temp / 100.0 |
161 |
| - |
162 |
| - raw_humidity = raw_readings[2] |
163 |
| - raw_humidity = (625 * raw_humidity) >> 12 |
164 |
| - humidity = raw_humidity / 100.0 |
165 |
| - |
166 |
| - self.sleep = True |
167 |
| - return (temperature, humidity) |
168 |
| - |
169 |
| - |
170 |
| - |
171 |
| - |
172 |
| -# /** |
173 |
| -# * Performs a CRC8 calculation on the supplied values. |
174 |
| -# * |
175 |
| -# * @param data Pointer to the data to use when calculating the CRC8. |
176 |
| -# * @param len The number of bytes in 'data'. |
177 |
| -# * |
178 |
| -# * @return The computed CRC8 value. |
179 |
| -# */ |
180 |
| -# static uint8_t crc8(const uint8_t *data, int len) { |
181 |
| -# /* |
182 |
| -# * |
183 |
| -# * CRC-8 formula from page 14 of SHT spec pdf |
184 |
| -# * |
185 |
| -# * Test data 0xBE, 0xEF should yield 0x92 |
186 |
| -# * |
187 |
| -# * Initialization data 0xFF |
188 |
| -# * Polynomial 0x31 (x8 + x5 +x4 +1) |
189 |
| -# * Final XOR 0x00 |
190 |
| -# */ |
191 | 41 |
|
| 42 | +# include "Arduino.h" |
| 43 | +# include <Adafruit_I2CDevice.h> |
| 44 | +# include <Adafruit_Sensor.h> |
| 45 | + |
| 46 | +_SHTC3_DEFAULT_ADDR = 0x70 # SHTC3 I2C Address |
| 47 | +_SHTC3_NORMAL_MEAS_TFIRST_STRETCH = ( |
| 48 | + 0x7CA2 # Normal measurement, temp first with Clock Stretch Enabled |
| 49 | +) |
| 50 | +_SHTC3_LOWPOW_MEAS_TFIRST_STRETCH = ( |
| 51 | + 0x6458 # Low power measurement, temp first with Clock Stretch Enabled |
| 52 | +) |
| 53 | +_SHTC3_NORMAL_MEAS_HFIRST_STRETCH = ( |
| 54 | + 0x5C24 # Normal measurement, hum first with Clock Stretch Enabled |
| 55 | +) |
| 56 | +_SHTC3_LOWPOW_MEAS_HFIRST_STRETCH = ( |
| 57 | + 0x44DE # Low power measurement, hum first with Clock Stretch Enabled |
| 58 | +) |
| 59 | + |
| 60 | +_SHTC3_NORMAL_MEAS_TFIRST = ( |
| 61 | + 0x7866 # Normal measurement, temp first with Clock Stretch disabled |
| 62 | +) |
| 63 | +_SHTC3_LOWPOW_MEAS_TFIRST = ( |
| 64 | + 0x609C # Low power measurement, temp first with Clock Stretch disabled |
| 65 | +) |
| 66 | +_SHTC3_NORMAL_MEAS_HFIRST = ( |
| 67 | + 0x58E0 # Normal measurement, hum first with Clock Stretch disabled |
| 68 | +) |
| 69 | +_SHTC3_LOWPOW_MEAS_HFIRST = ( |
| 70 | + 0x401A # Low power measurement, hum first with Clock Stretch disabled |
| 71 | +) |
| 72 | + |
| 73 | +_SHTC3_READID = 0xEFC8 # Read Out of ID Register |
| 74 | +_SHTC3_SOFTRESET = 0x805D # Soft Reset |
| 75 | +_SHTC3_SLEEP = 0xB098 # Enter sleep mode |
| 76 | +_SHTC3_WAKEUP = 0x3517 # Wakeup mode |
| 77 | +_SHTC3_CHIP_ID = 0x807 |
192 | 78 | # const uint8_t POLYNOMIAL(0x31)
|
193 |
| -# uint8_t crc(0xFF) |
| 79 | +_POLYNOMIAL = 0x31 |
194 | 80 |
|
195 |
| -# for (int j = len j --j) { |
196 |
| -# crc ^= *data++ |
197 | 81 |
|
198 |
| -# for (int i = 8 i --i) { |
199 |
| -# crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1) |
200 |
| -# |
201 |
| -# |
202 |
| -# return crc |
203 |
| -# |
| 82 | +class SHTC3: |
| 83 | + """ |
| 84 | + A driver for the SHTC3 temperature and humidity sensor. |
| 85 | + :param i2c_bus: The `busio.I2C` object to use. This is the only required parameter. |
| 86 | + :param int address: (optional) The I2C address of the device. |
| 87 | + """ |
| 88 | + |
| 89 | + def __init__(self, i2c_bus): |
| 90 | + self.i2c_device = i2c_device.I2CDevice(i2c_bus, _SHTC3_DEFAULT_ADDR) |
| 91 | + |
| 92 | + self._buffer = bytearray(6) |
| 93 | + self.low_power = False |
| 94 | + self.reset() |
| 95 | + self.sleep = False |
| 96 | + if self._chip_id & 0x083F != _SHTC3_CHIP_ID: |
| 97 | + raise RuntimeError("Failed to find an ICM20X sensor - check your wiring!") |
| 98 | + |
| 99 | + def _write_command(self, command): |
| 100 | + self._buffer[0] = command >> 8 |
| 101 | + self._buffer[1] = command & 0xFF |
| 102 | + |
| 103 | + with self.i2c_device as i2c: |
| 104 | + i2c.write(self._buffer, start=0, end=2) |
| 105 | + |
| 106 | + @property |
| 107 | + def _chip_id(self): # readCommand(SHTC3_READID, data, 3); |
| 108 | + self._buffer[0] = _SHTC3_READID >> 8 |
| 109 | + self._buffer[1] = _SHTC3_READID & 0xFF |
| 110 | + |
| 111 | + with self.i2c_device as i2c: |
| 112 | + i2c.write_then_readinto( |
| 113 | + self._buffer, self._buffer, out_start=0, out_end=2, in_start=0, in_end=2 |
| 114 | + ) |
| 115 | + |
| 116 | + return unpack_from(">H", self._buffer)[0] |
| 117 | + |
| 118 | + def reset(self): |
| 119 | + """Perform a soft reset of the sensor, resetting all settings to their power-on defaults""" |
| 120 | + try: |
| 121 | + self._write_command(_SHTC3_SOFTRESET) |
| 122 | + |
| 123 | + except RuntimeError as run_err: |
| 124 | + if run_err.args and run_err.args[0] != "I2C slave address was NACK'd": |
| 125 | + raise run_err |
| 126 | + time.sleep(0.001) |
| 127 | + |
| 128 | + @property |
| 129 | + def sleep(self): |
| 130 | + """Determines the sleep state of the sensor""" |
| 131 | + return self._cached_sleep |
| 132 | + |
| 133 | + @sleep.setter |
| 134 | + def sleep(self, sleep_enabled): |
| 135 | + if sleep_enabled: |
| 136 | + self._write_command(_SHTC3_SLEEP) |
| 137 | + else: |
| 138 | + self._write_command(_SHTC3_WAKEUP) |
| 139 | + time.sleep(0.001) |
| 140 | + self._cached_sleep = sleep_enabled |
| 141 | + |
| 142 | + # lowPowerMode(bool readmode) { _lpMode = readmode |
| 143 | + |
| 144 | + @property |
| 145 | + def low_power(self): |
| 146 | + """Enables the less accurate low power mode, trading accuracy for power consumption""" |
| 147 | + return self._low_power |
| 148 | + |
| 149 | + @low_power.setter |
| 150 | + def low_power(self, low_power_enabled): |
| 151 | + self._low_power = low_power_enabled |
| 152 | + |
| 153 | + @property |
| 154 | + def relative_humidity(self): |
| 155 | + """Current relative humidity in % rH""" |
| 156 | + return self.measurements[1] |
| 157 | + |
| 158 | + @property |
| 159 | + def temperature(self): |
| 160 | + """Current temperature in degrees celcius""" |
| 161 | + return self.measurements[0] |
| 162 | + |
| 163 | + @property |
| 164 | + def measurements(self): |
| 165 | + """both `temperature` and `relative_humidity`, read simultaneously""" |
| 166 | + |
| 167 | + self.sleep = False |
| 168 | + raw_readings = [] |
| 169 | + |
| 170 | + if self.low_power: |
| 171 | + self._write_command(_SHTC3_LOWPOW_MEAS_TFIRST) |
| 172 | + time.sleep(0.001) |
| 173 | + else: |
| 174 | + self._write_command(_SHTC3_NORMAL_MEAS_TFIRST) |
| 175 | + time.sleep(0.013) |
| 176 | + |
| 177 | + self._buffer = bytearray(6) |
| 178 | + with self.i2c_device as i2c: |
| 179 | + i2c.readinto(self._buffer) |
| 180 | + raw_readings = unpack_from(">hbh", self._buffer) |
| 181 | + |
| 182 | + # print("CRC8-ing some beef:", hex(self._crc8(bytearray([0xBE, 0xEF]), 2))) |
| 183 | + # check CRC of bytes |
| 184 | + # if (self._buffer[2] != crc8(self._buffer, 2) or |
| 185 | + # self._buffer[5] != crc8(self._buffer + 3, 2)): |
| 186 | + # print("NOT CHECKING") |
| 187 | + |
| 188 | + raw_temp = raw_readings[0] |
| 189 | + raw_temp = ((4375 * raw_temp) >> 14) - 4500 |
| 190 | + temperature = raw_temp / 100.0 |
| 191 | + |
| 192 | + raw_humidity = raw_readings[2] |
| 193 | + raw_humidity = (625 * raw_humidity) >> 12 |
| 194 | + humidity = raw_humidity / 100.0 |
| 195 | + |
| 196 | + self.sleep = True |
| 197 | + return (temperature, humidity) |
| 198 | + |
| 199 | + ## CRC-8 formula from page 14 of SHT spec pdf |
| 200 | + # |
| 201 | + # Test data 0xBE, 0xEF should yield 0x92 |
| 202 | + # |
| 203 | + # Initialization data 0xFF |
| 204 | + # Polynomial 0x31 (x8 + x5 +x4 +1) |
| 205 | + # Final XOR 0x00 |
| 206 | + |
| 207 | + # @staticmethod |
| 208 | + # def _crc8(buffer, length): |
| 209 | + # print("buffer:", buffer) |
| 210 | + # crc = 0xFF |
| 211 | + # print("0: crc = ", format(crc, "#010b")) |
| 212 | + |
| 213 | + # buff_index = 0 |
| 214 | + # for i in range(length): |
| 215 | + # curr_buff = buffer[i] |
| 216 | + # print("buffer[%d]" % i, hex(curr_buff), format(curr_buff, "#010b")) |
| 217 | + # crc ^= curr_buff |
| 218 | + # print("1 crc = ", format(crc, "#010b")) |
| 219 | + |
| 220 | + # for i in range(8): |
| 221 | + # print("crc & 0x80: ", format(crc & 0x80, "#010b")) |
| 222 | + # crc_shift_one = (crc << 1) |
| 223 | + # if crc & 0x80: # if crc top bit is set |
| 224 | + # print("yes") |
| 225 | + # crc = crc_shift_one ^ _POLYNOMIAL |
| 226 | + # else: |
| 227 | + # print("no") |
| 228 | + # crc = crc_shift_one |
| 229 | + # print("3 crc = crc << 1", format(crc, "#010b")) |
| 230 | + # print("\t*** NEXT BIT **") |
| 231 | + # print("*** NEXT BYTE **") |
| 232 | + # return crc |
0 commit comments