IoTで使うPython入門Step1-I2C LM75Bで温度測定 (3) read_word_data

 ラズパイとI2CインターフェースのLM75Bをつないで温度を読み出すプログラムをPythonで記述しています。前回、変数の型、n進数変換などの確認しているとプログラムのまずいところも見つかりました。

修正

 前回のsmbusライブラリを使ったLM75Bのプログラムの中で無駄に変換しているところなどを修正しました。

import smbus
import time
i2c = smbus.SMBus(1)
addr = 0x4c # LM75B NXP. TI is 9bit

def sign16(x):
return (-(x & 0b1000000000000000) | (x & 0b0111111111111111))

# main
while 1:
data = i2c.read_i2c_block_data(addr, 0, 2)
raw = ((data[0]) << 8) | (data[1])
print(hex(data[0])),
print(hex(data[1])),
print(hex(raw))
raw_s = sign16(raw)
temp = (raw_s >> 5) * 0.125
print(str(temp) + "C")
time.sleep(1)

2バイトの読み出しは

read_word_data(アドレス, コマンド)

でも可能です。ブロック・データの読み出しのプログラムを修正して動かし、波形を見ます。

import smbus
import time
i2c = smbus.SMBus(1)
addr = 0x4c # LM75B NXP. TI is 9bit

def sign16(x):
return (-(x & 0b1000000000000000) | (x & 0b0111111111111111))

def swap16(x):
return (((x << 8) & 0xFF00) | ((x >> 8) & 0x00FF))

# main
while 1:
data = i2c.read_word_data(addr, 0)
print("data ", type(data))
print(data, hex(data))
data_h = swap16(data)
print (data_h, hex(data_h))
raw_s = sign16(data_h)
temp = (raw_s >> 5) * 0.125
print("temp ", type(temp))
print(str(temp) + "C")
time.sleep(1)

 実行します。sshでPCからつないでいます。

 波形です。下位バイト、上位バイトの順でword=2バイト・データを読み取っています。このままでは扱えないので、swap16()関数で上位と下位バイトを入れ替えます。

 デバイスによっては、下位バイト、上位バイトの順で収納されている製品もいくつもあります。けれど、

data = i2c.read_i2c_block_data(addr, 0, 2)

で読み取ったデータは、8ビット単位のリスト形式で保存されているので、

raw = ((data[1]) << 8) | (data[0])

 入れ替えて処理をすればよいので、スワップをする手間の増えるread_word_dataは使わなくてもよいと感じています。この2年間の間、read_word_data()をたくさん使っています。これは、何らかの理由でread_i2c_block_data()がうまくデータを読んでこなかったことがあったのかもしれないですが、記憶は定かではありません。
 上記のように、下位バイト、上位バイトの逆転は、「5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (38) ディジタル光センサ3 I2C AMG8833」で実際に使っています。