
定期ルーチンとて、秋月電子通商殿の新製品(新規取り扱い開始)ページを眺めていてAHT21BというI2C接続の温湿度センサを見つけました。2022年7月12日より取扱い開始とな。つい買ってしまいました。とりあえずラズパイ3から引き出してあるI2Cバスに接続して温度、湿度が読み取れることを確認してみました。
※「部品屋根性」投稿順Indexはこちら
AHT21Bは、中国のAosong Electronic社(ASAIRと略称)の製品です。製品ページへのリンクが以下に。
AHT21B Temperature and humidity sensor
購入したのは、秋月殿の以下のページからです。
なお、このセンサには 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コマンドで接続を確認できます。
動作確認用の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()
動作確認結果
それらしく読み取れています。CRC8チエックを追加しないと。(追加済:こちら)


