MicroPython Driver for SHT40 / SHT45

SHT40, SHT45 Driver Code for micro:bit

Download as zip file

'''
SHT40, SHT41, SHT43, SHT45
MicroPython driver for micro:bit

AUTHOR: fredscave.com
DATE  : 2024/10
VERSION : 1.00
'''

from microbit import i2c, sleep
from micropython import const

ADDR = const(0x44)
CMD_HI_PREC = const(0xFD)
TIME_HI_PREC = const(10)
CMD_MED_PREC = const(0xF6)
TIME_MED_PREC = const(5)
CMD_LO_PREC = const(0xE0)
TIME_LO_PREC = const(2)
HIGH = const(0)
MEDIUM = const(1)
LOW = const(2)
prec_cmd_list = [CMD_HI_PREC,
                 CMD_MED_PREC,
                 CMD_LO_PREC]

prec_wait_list = [TIME_HI_PREC,
                  TIME_MED_PREC,
                  TIME_LO_PREC]

CMD_HEAT0 = const(0x39) #200mw, 1s
CMD_HEAT1 = const(0x32) #200mw, 0.1s
CMD_HEAT2 = const(0x2F) #110mw, 1s
CMD_HEAT3 = const(0x24) #110mw, 0.1s
CMD_HEAT4 = const(0x1E) #20mw, 1s
CMD_HEAT5 = const(0x15) #20mw, 0.1s
heat_cmd_list = [CMD_HEAT0, CMD_HEAT1, CMD_HEAT2,
             CMD_HEAT3, CMD_HEAT4, CMD_HEAT5]

heat_wait_list = [1000 + TIME_HI_PREC + 2,
                  100 + TIME_HI_PREC + 2,
                  1000 + TIME_HI_PREC + 2,
                  100 + TIME_HI_PREC + 2,
                  1000 + TIME_HI_PREC + 2,
                  100 + TIME_HI_PREC + 2]

CMD_SERIAL = const(0x89)
CMD_RESET = const(0x94)
CRC_INITIAL = const(0xFF)
CRC_POLY = const(0x31)

class SHT4X():

    def Read(self, precision=HIGH):
        if precision not in [HIGH, MEDIUM, LOW]:
            precision = HIGH
        cmd = prec_cmd_list[precision]
        wait = prec_wait_list[precision]
        i2c.write(ADDR, bytes([cmd]))
        sleep(wait)
        buf = i2c.read(ADDR, 6)
        return SHT4X.convert(buf)

    def T(self, precision=HIGH):
        results = self.Read(precision)
        return round(results[0], 1)

    def T_f(self, precision=HIGH):
        results = self.Read(precision)
        return round(results[1], 1)

    def RH(self, precision=HIGH):
        results = self.Read(precision)
        rh = results[2]
        if rh > 100:
            rh = 100
        elif rh < 0:
            rh = 0
        return int(rh + 0.5)

    def Heater(self, setting=5):
        if setting not in range(6):
            setting = 5
        cmd = heat_cmd_list[setting]
        wait = heat_wait_list[setting]
        i2c.write(ADDR, bytes([cmd]))
        sleep(wait)
        buf = i2c.read(ADDR, 6)
        return SHT4X.convert(buf)

    def Serial(self):
        i2c.write(ADDR, bytes([CMD_SERIAL]))
        sleep(5)
        buf = i2c.read(ADDR, 6)
        upper = buf[0] * 256 + buf[1]
        lower = buf[3] * 256 + buf[4]
        return str(upper) + '-' + str(lower)

    def Reset(self):
        i2c.write(ADDR, bytes([CMD_RESET]))
        sleep(1)

    @staticmethod
    def checksum(buf):
        crc = CRC_INITIAL
        for byte in buf:
            crc ^= byte
            for bit in range(8):
                if crc & 0x80:
                    crc = (crc << 1) ^ CRC_POLY
                else:
                    crc = crc << 1
        return crc & 0xFF

    @staticmethod
    def convert(buf):
        t_ticks = buf[0] * 256 + buf[1]
        t_c = -45 + 175 * t_ticks/65535
        t_f = -49 + 315 * t_ticks/65535
        t_buf = bytearray([buf[0], buf[1]])
        t_check = SHT4X.checksum(t_buf)
        rh_ticks = buf[3] * 256 + buf[4]
        rh_p = -6 + 125 * rh_ticks/65535
        rh_buf = bytearray([buf[3], buf[4]])
        rh_check = SHT4X.checksum(rh_buf)
        return (t_c,
                t_f,
                rh_p,
                t_check == buf[2],
                rh_check == buf[5])