部品屋根性(76) AHT21B、I2C温湿度センサをラズパイPythonで動作確認

Joseph Halfmoon

定期ルーチンとて、秋月電子通商殿の新製品(新規取り扱い開始)ページを眺めていてAHT21BというI2C接続の温湿度センサを見つけました。2022年7月12日より取扱い開始とな。つい買ってしまいました。とりあえずラズパイ3から引き出してあるI2Cバスに接続して温度、湿度が読み取れることを確認してみました。

※「部品屋根性」投稿順Indexはこちら

AHT21Bは、中国のAosong Electronic社(ASAIRと略称)の製品です。製品ページへのリンクが以下に。

AHT21B Temperature and humidity sensor

購入したのは、秋月殿の以下のページからです。

温湿度センサ AHT21B

なお、このセンサには standard と Shield model の2つがあるようですが、上記ページから買えるのは Shield model の方です。シールドについての説明を引用すると

Waterproof, dustproof and pollution proof

だそうです。しかしシールドが覆っているセンサ本体は良いですが、センサが搭載されている小基板はむき出しなので、そこは「自分でやってね」という感じでしょう。

精度的には温度±0.5℃、湿度±3%RHとそこそこ良い感じです。分解能は0.01℃、0.024%RHとかなり細かいです。レンジによる詳細はデータシートに詳しく書かれてます。

Raspberry Pi 3 model B+への接続

センサそのものは、3.3V電源でも5V電源でも動作します。ラズパイの拡張端子から引き出したI2Cバスへの直接接続であれば3.3V電源でOKだと思います。当方は、ラズパイのI2Cを5Vに変換して引き出してテストしているので電源は5Vです。I2Cのアドレスは 0x38です。以下のように i2cdetectコマンドで接続を確認できます。

i2cAddr

動作確認用のPython3スクリプト

動作確認用のスクリプトは以下です。I2Cバスの制御は前回からsmbus2を使っています。smbus2は快調、さっさと切り替えれば良かったです。

一応以下のスクリプトでは、温度、湿度とも人間可読な十進数値に変換して表示してますが、CRCは読み取りだけして検査はしてません。CRC8といっても生成多項式はいろいろあるみたいです。このAHT21Bが使っているCRC8はMaxim(現在はアナデバ傘下の筈)式みたいです。Python用のCRCモジュールもいろいろあるのですが、どれ使えばMaxim式できるのか不明。良い機会なので後で調べてMaxim式のCRC8の処理を追加してみる予定です。

※CRCによる検査を追加した版のスクリプトはこちら

またデータシート通りに電源投入後の設定確認のためのinitAHT21B()という関数を作ってみましたが、有効なのは本当に「電源投入後1回だけ」みたいです。何度もやるとエラーになります。とりあえず無しでも温湿度の読み取りは出来るみたいなので、下記ではコメントアウトしてあります。

#! /usr/bin/python3
# coding: utf-8
from smbus2 import SMBus, i2c_msg
import sys
import time

addr = 0x38

def triggerAHT21B(bus):
    """Triger measurement
    
    send 0xAC, 0x33, 0x00
    """
    time.sleep(0.01)
    write = i2c_msg.write(addr, [0xAC, 0x33, 0x00])
    bus.i2c_rdwr(write)

def readMeasurementResult(bus):
    """Read 7 bytes
    
    status 8bit, Humidity 20bit, Temparature 20bit, CRC 8bit 
    """
    time.sleep(0.08)
    msg = i2c_msg.read(addr, 7)
    bus.i2c_rdwr(msg)
    return list(msg)

def initAHT21B(bus):
    time.sleep(0.1)
    write = i2c_msg.write(addr, [0x71])
    read = i2c_msg.read(addr, 1)
    bus.i2c_rdwr(write, read)
    res = list(read)
    if len(res) == 1:
        if res[0] == 0x18:
            return True
    return False

def calcHumidity(buf):
    humInt = (buf[1]<<12) + (buf[2]<<4) + ((buf[3] & 0xF0)>>4)
    return (humInt / 2**20) * 100

def calcTemp(buf):
    tempInt = ((buf[3] & 0x0F)<<16) + (buf[4]<<8) + buf[5]
    return (tempInt / 2**20) * 200 - 50

def main():
    print("AHT21B test")
#    with SMBus(1) as bus:
#        if not initAHT21B(bus):
#            print("ERROR: init!")
#            sys.exit(1)
    cnt = 3
    while (cnt > 0):
        with SMBus(1) as bus:
            triggerAHT21B(bus)
            buf = readMeasurementResult(bus)
        if len(buf)==7:
            print("Status: 0x{0:02x}".format(buf[0]))
            print("Humidity [RH%]: {0:3.1f}".format(calcHumidity(buf)))
            print("Temperature[C]: {0:3.1f}".format(calcTemp(buf)))
            #print("Data: {0:02x} {1:02x} {2:02x} {3:02x} {4:02x}".format(buf[1],buf[2],buf[3],buf[4],buf[5]))
            print("CRC: 0x{0:02x}".format(buf[6]))
        else:
            print("ERROR!")
        cnt -= 1
        time.sleep(3)
    # Normal End
    sys.exit(0)

if __name__ == "__main__":
    main()
動作確認結果

上記のスクリプトで温湿度を読み取った結果が以下に。Results

それらしく読み取れています。CRC8チエックを追加しないと。(追加済:こちら

部品屋根性(75) MCP3421、ADCのラズパイI2C接続、Pythonで制御の続き へ戻る

部品屋根性(77) AHT21B、CRC8でのデータ検査を追加。ラズパイPython へ進む