定期ルーチンとて、秋月電子通商殿の新製品(新規取り扱い開始)ページを眺めていて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チエックを追加しないと。(追加済:こちら)