稼働中

Raspberry Pi Pico(d_22)HTU21D CRC計算

HTU21D CRC計算

HTU21Dモジュールで温度、湿度を測定するとエラー検出用のChecksumも返ります。
HTU21DのデータシートにCRC Checksumの項目があります。
※CRC(Cyclic Redundancy Check:巡回冗長検査)
私は素人レベルなのでCRCの詳しい説明はできません。他のサイトで確認ください。
送受信が正常ならChecksum値とデータ値をCRC計算した値と同じになるそうです。
そのため、データの伝送誤を判断できるそうです。

HTU21Dでは以下の多項式(polynomial)を使うそうです。
polynomial

CRC examlpes

以下のスクリプトで下の「CRC examples」を確認してみます。
examlpesでは0xdcのデータならCRC計算結果が0x79、0x683Aなら結果は0x7c、0x4e85なら0x6bです。
HTU21D CRC examlpes
※HTU21Dのデータシートから抜粋
以下のスクリプトで計算確認しました。


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# polynomial  X8+X5+X4+1 ---次数は8 9bit
def HTU_CRC(dat):
    div=2**8 + 2**5 + 2**4 +2**0  # bin(305)='0b100110001'
    zisu=8

    dat_len=len(bin(dat))-2
    msg = dat << zisu
    div = div<<(dat_len-1)
    
    for i in range((dat_len+zisu-1), (zisu-1), -1):
        if msg & (1<>1
    return msg

スクリプト実行後にThonnyのshellで確認しました。
HTU_CRC(dat)にCRC examplesのmessage値を入れて確認して見ました。
「CRC examples」と同じになっているので問題なさそうです。


>>> hex(HTU_CRC(0xdc))
'0x79'
>>> hex(HTU_CRC(0x683A))
'0x7c'
>>> hex(HTU_CRC(0x4E85))
'0x6b'
>>> 

受信値と比較

実際に受信値と比較してみます。
受信値は計算に使用する前のStatusを含んだData (MSB)とData (LSB)の16bitの生データです。
受信した16bitの生データをCRC計算して受信したchecksum値と比較してみます。
送受信が正常なら同じ値になります。もし異なるなら誤伝送なので再測定(再送信)が必要になります。ここではCRC計算の確認だけを行います。

スクリプトは以下のようにしました。
HTU_raw(cmd)で温度、湿度測定時の16bitデータとChecksumを返します。
16bitデータをCRC計算して表示します。Checksumと同じなら正常です。


#!/usr/bin/env python
# -*- coding: utf-8 -*
from machine import I2C,Pin
# HTU21D Device digital humidity sensor with temperature output by MEAS
# HTU21D slave address hex(64)='0x40'
i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=400_000)
addr=0x40

## soft reset    
def HTU_reset():
    buf=bytearray(1)
    buf[0]=0xfe      # cmd 0xfe soft reset
    i2c.writeto(addr,buf)
    
def HTU_raw(cmd=0xe5):
    buf=bytearray(1)
    buf[0]=cmd      # # cmd 0xe3(temp) 0xe5(humi)
    i2c.writeto(addr,buf)    
    r_dat=i2c.readfrom(addr,3)    #msb,lsb,crc
    raw=(r_dat[0]<<8 | r_dat[1])  # 16bit_raw_data
    crc=r_dat[2]
    return raw,crc

def HTU_CRC(dat):
    div=2**8 + 2**5 + 2**4 +2**0  # bin(305)='0b100110001'
    zisu=8
    #message data
    dat_len=len(bin(dat))-2
    msg = dat << zisu
    
    div = div<<(dat_len-1)
    
    for i in range((dat_len+zisu-1), (zisu-1), -1):
        if msg & (1<>1
    return msg

## main
HTU_reset()
#Temperature 
r_dat,c_sum=HTU_raw(0xe3)   #0xe3(temp) 
print('raw_data=',r_dat,'checksum=',c_sum)
print('CRC',HTU_CRC(r_dat))

#Humidity
r_dat,c_sum=HTU_raw(0xe5)   #0xe5(humi)
print('raw_data=',r_dat,'checksum=',c_sum)
print('CRC',HTU_CRC(r_dat))

■実行結果
Thonnyのshellに表示されます。以下のように受信したデータが正しいことが確認できました。


>>> %Run -c $EDITOR_CONTENT
raw_data= 24996 checksum= 153
CRC 153
raw_data= 31222 checksum= 220
CRC 220
>>> 

まとめ

HTU21Dの受信データをCRC計算して受信したChecksumと比較しました。一致を確認し、正常な伝送を確認ができました。