LoginSignup
1
0

More than 5 years have passed since last update.

micro:bit / MicroPython / I2C デバイス (温湿度センサー HTU21D) を外づけする

Last updated at Posted at 2018-06-15

概要

I2C デバイス (温湿度センサー HTU21D) を micro:bit に外づけしてみる。I2C バスは micro:bit の標準端子 (P19 が SCL、P20 が SDA) をそのまま使った。プログラミング言語には MicroPython を使った。

I2C の write 操作 (マスターからスレーブへのデータ転送)

構文: microbit.i2c.write(スレーブアドレス, バイト列 [, repeat=False])

  • repeat= はオプション (False がデフォルト)。repeat=True を指定すれば Repeated Start となる。
  • スレーブアドレスは 7 ビットで指定する。
  • バイト列は以下の例では bytes() で作ったが bytearray() でもよい。bytes() で作った場合は tuple と同じで変更はできない。

I2C の read 操作 (スレーブからマスターへのデータ転送)

構文: microbit.i2c.read(スレーブアドレス, バイト数 [, repeat=False])

  • repeat= はオプション (False がデフォルト)。repeat=True を指定すれば Repeated Start となる。
  • スレーブアドレスは 7 ビットで指定する。

温度、湿度を読む出すための MicroPython スクリプト

温度、湿度の取得のほか、ソフトリセット、ユーザーレジスタの読み出し、測定分解能の変更もできるようにした。中身は前回 mbed 用に作ったコードと同じである。最新版は GitHub にある。

HTU21D.py
from microbit import *

class HTU21D:
    def __init__(self):
        self.HTDU21D_ADDRESS           = 0x40
        self.TRIGGER_TEMP_MEASURE_HOLD = 0xE3
        self.TRIGGER_HUMD_MEASURE_HOLD = 0xE5
        self.SHIFTED_DIVISOR           = (2**8 + 2**5 + 2**4 + 1)<<15
        self.READ_USER_REG             = 0xE7
        self.WRITE_USER_REG            = 0xE6
        self.SOFT_RESET                = 0xFE

        self.RH12_TEMP14 = 0b00000000
        self.RH08_TEMP12 = 0b00000001
        self.RH10_TEMP13 = 0b10000000
        self.RH11_TEMP11 = 0b10000001

    def readTemp(self):
        buf = bytes([self.TRIGGER_TEMP_MEASURE_HOLD])
        i2c.write(self.HTDU21D_ADDRESS, buf) 

        msb, lsb, crc = i2c.read(self.HTDU21D_ADDRESS, 3)
        crcResult     = self.__check_crc(msb, lsb, crc)
        raw           = (msb<<8 | lsb) & 0xfffc
        temp          = -46.85 + 175.72 * raw / 65536.0

        return temp if crcResult == 0 else crcResult

    def readHumid(self):
        buf = bytes([self.TRIGGER_HUMD_MEASURE_HOLD])
        i2c.write(self.HTDU21D_ADDRESS, buf) 

        msb, lsb, crc = i2c.read(self.HTDU21D_ADDRESS, 3)
        crcResult     = self.__check_crc(msb, lsb, crc)
        raw           = (msb<<8 | lsb) & 0xfffc
        humid         = -6.0 + 125.0 * raw / 65536.0

        return humid if crcResult == 0 else crcResult

    def __check_crc(self, msb, lsb, crc):
        divisor   = self.SHIFTED_DIVISOR
        remainder = msb<<16 | lsb<<8 | crc

        for i in range(23, 7, -1):
            if remainder & 1<<i:
                remainder ^= divisor

            divisor >>= 1

        return 0 if remainder == 0 else 999

    def readUserRegister(self):
        buf = bytes([self.READ_USER_REG])
        i2c.write(self.HTDU21D_ADDRESS, buf)

        return i2c.read(self.HTDU21D_ADDRESS, 1)

    def setResolution(self, resolution):
        userRegister = self.readUserRegister()[0]
        userRegister &= 0b01111110
        resolution   &= 0b10000001
        userRegister |= resolution

        buf = bytes([self.WRITE_USER_REG, userRegister])
        i2c.write(self.HTDU21D_ADDRESS, buf)

    def softReset(self):
        buf = bytes([self.SOFT_RESET])
        i2c.write(self.HTDU21D_ADDRESS, buf)

##############
# how to use #
##############
if __name__ == "__main__":
    HTU = HTU21D()

    #HTU.softReset() # To soft-reset the HTU21D, uncomment this line.

    #HTU.setResolution(HTU.RH12_TEMP14) # You can select one of the four resolutions.
    #HTU.setResolution(HTU.RH08_TEMP12)
    #HTU.setResolution(HTU.RH10_TEMP13)
    #HTU.setResolution(HTU.RH11_TEMP11)
    while True:
        #print(HTU.readUserRegister()) # To serial.print the user register, uncomment this line.

        temp  = HTU.readTemp()
        humid = HTU.readHumid()
        print("%.1f C, %.1f %%" % (temp, humid))
        sleep(1000)

実行結果

参考

関連

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0