Source code for micropython_shtc3.shtc3
# SPDX-FileCopyrightText: Copyright (c) 2020 Bryan Siepert for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2023 Jose D. Montoya
#
# SPDX-License-Identifier: MIT
"""
`shtc3`
================================================================================
MicroPython Driver for the Sensirion SHTC3 Temperature and Humidity Sensor
* Author(s): Bryan Siepert, Jose D. Montoya
"""
import time
import struct
from micropython import const
try:
from typing import Tuple
except ImportError:
pass
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/jposada202020/MicroPython_SHTC3.git"
_DEVICE_ID = const(0xEFC8).to_bytes(2, "big")
_SOFTRESET = const(0x805D).to_bytes(2, "big")
SLEEP = const(0xB098)
WAKEUP = const(0x3517)
operation_mode_values = (SLEEP, WAKEUP)
NORMAL = const(0x7866)
LOW_POWER = const(0x609C)
power_mode_values = (NORMAL, LOW_POWER)
[docs]
class SHTC3:
"""Driver for the SHTC3 Sensor connected over I2C.
:param ~machine.I2C i2c: The I2C bus the SHTC3 is connected to.
:param int address: The I2C device address. Defaults to :const:`0x70`
:raises RuntimeError: if the sensor is not found
**Quickstart: Importing and using the device**
Here is an example of using the :class:`SHTC3` class.
First you will need to import the libraries to use the sensor
.. code-block:: python
from machine import Pin, I2C
from micropython_shtc3 import shtc3
Once this is done you can define your `machine.I2C` object and define your sensor object
.. code-block:: python
i2c = I2C(1, sda=Pin(2), scl=Pin(3))
sht = shtc3.SHTC3(i2c)
Now you have access to the attributes
.. code-block:: python
temperature, relative_humidity = sht.measurements
"""
def __init__(self, i2c, address: int = 0x70) -> None:
self._i2c = i2c
self._address = address
if self._get_device_id() != 0x87:
raise RuntimeError("Failed to find SHTC3")
self._time_operation = None
self.operation_mode = WAKEUP
self.power_mode = NORMAL
@property
def operation_mode(self) -> str:
"""
Sensor operation_mode
+--------------------------+--------------------+
| Mode | Value |
+==========================+====================+
| :py:const:`shtc3.SLEEP` | :py:const:`0xB098` |
+--------------------------+--------------------+
| :py:const:`shtc3.WAKEUP` | :py:const:`0x3517` |
+--------------------------+--------------------+
"""
values = {SLEEP: "SLEEP", WAKEUP: "WAKEUP"}
return values[self._operation_mode]
@operation_mode.setter
def operation_mode(self, value: int) -> None:
if value not in operation_mode_values:
raise ValueError("Value must be a valid operation_mode setting")
self._operation_mode = value
self._i2c.writeto(self._address, value.to_bytes(2, "big"), False)
time.sleep(0.001)
@property
def power_mode(self) -> str:
"""
Sensor power_mode
+-----------------------------+--------------------+
| Mode | Value |
+=============================+====================+
| :py:const:`shtc3.NORMAL` | :py:const:`0x7866` |
+-----------------------------+--------------------+
| :py:const:`shtc3.LOW_POWER` | :py:const:`0x609C` |
+-----------------------------+--------------------+
"""
values = {NORMAL: "NORMAL", LOW_POWER: "LOW_POWER"}
return values[self._power_mode]
@power_mode.setter
def power_mode(self, value: int) -> None:
if value not in power_mode_values:
raise ValueError("Value must be a valid power_mode setting")
self._power_mode = value
self._i2c.writeto(self._address, value.to_bytes(2, "big"), False)
time.sleep(0.001)
if value == LOW_POWER:
self._time_operation = 0.001
else:
self._time_operation = 0.013
def _get_device_id(self):
"""
Get the device ID
"""
data = bytearray(3)
self._i2c.writeto(self._address, _DEVICE_ID, False)
time.sleep(0.001)
self._i2c.readfrom_into(self._address, data, True)
return data[1]
@property
def measurements(self) -> Tuple[float, float]:
"""
Take sensor readings. Temperature and Relative Humidity
"""
self.operation_mode = WAKEUP
data = bytearray(6)
self._i2c.writeto(self._address, self._power_mode.to_bytes(2, "big"), False)
time.sleep(self._time_operation)
self._i2c.readfrom_into(self._address, data, False)
temp_data = data[0:2]
temp_crc = data[2]
humidity_data = data[3:5]
humidity_crc = data[5]
if temp_crc != self._crc8(temp_data) or humidity_crc != self._crc8(
humidity_data
):
raise RuntimeError("CRC Mismatched")
raw_temp = struct.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 = struct.unpack_from(">H", humidity_data)[0]
raw_humidity = (625 * raw_humidity) >> 12
humidity = raw_humidity / 100.0
self.operation_mode = SLEEP
return temperature, humidity
@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
@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]