前回、I2C接続の温湿度センサ AHT21B をラズパイのI2Cバスに接続し、Python3のスクリプトで温度、湿度を読み取ってみました。まあ動いているみたいではあるのですが、データの伝送に誤りがあるや否やを確かめるためのCRCを検査しておりませなんだ。今回は、CRCの検査を追加しただけ。
※「部品屋根性」投稿順Indexはこちら
バイト・リストを引数に与えるとCRC8を計算する関数 calcCRC8を前回コードに付け加えました。CRC8にもいろいろある、ということでAHT21Bの場合、
-
- 特性多項式を表す poly = 0x31
- 初期値 opt = 0xFF
として、読み取った7バイトのうちステータスと湿度、温度の合計6バイト分のデータに対してCRC8を計算すると、末尾の7バイト目のCRC値と一致する(伝送誤りなければ)と。
改訂版のPython3スクリプトが以下に。
#! /usr/bin/python3 # coding: utf-8 from smbus2 import SMBus, i2c_msg import sys import time def calcCRC8(bytLis, poly=0x31, opt=0): """Caluculate CRC8 for byte List poly=0x31 for the AHT21b. """ crc = opt for item in bytLis: crc ^= item for idx in range(8): if crc & 0x80: crc = ((crc << 1) & 0xFF) ^ poly else: crc = ((crc << 1) & 0xFF) return crc addr = 0x38 def triggerAHT21B(bus): """Triger measurement send 0xAC, 0x33, 0x00 """ time.sleep(0.01) #bus.write_block_data(addr, 0xAC, [0x33, 0x00]) 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") 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))) crcVerify = False if buf[6] == calcCRC8(buf[0:6], opt=0xFF): crcVerify = True print("CRC Verify: {0}".format(crcVerify)) else: print("ERROR!") cnt -= 1 time.sleep(3) # Normal End sys.exit(0) if __name__ == "__main__": main()
実機実行結果のアップデート
実機にて実行した結果が以下に。Verifyが成功したか否かをTrue、Falseで返すだけ。
温湿度に加えて伝送結果の検証もできたと。一件落着か。今日は「涼しくて」良かったけれども(センサとは関係ない。)