5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (17) ディジタル温度センサ2 I2C LM75B

分解能0.125℃の温度センサ

 LM75Bは複数の会社で製造されていますが、テキサス・インスツルメンツとマキシムのLM75/LM75Bは読み出すデータ長は9ビットです。NXPのLM75Bは11ビットです。ここではNXPのLM75Bを使うので、最小分解能は0.125℃です。I2Cのスレーブ・アドレスは8通り設定できるので、複数のLM75Bを同時に利用できます。

LM75Bの特徴

  • インターフェース;I2C。スレーブ・アドレスは三つのピンが用意されている(8アドレス)
  • 温度データフォーマット;11ビット。データの最上位ビットは符号で、左詰め。2の補数形式
  • 測定温度範囲;-55~125℃
  • 温度の確度;±2℃(-25~+100℃)
  • 電源電圧;2.8~5.5V
  • データ転送速度;400kHz

ブレークアウト・ボードの仕様

 スイッチサイエンスからボードを購入しました。スレーブ・アドレスは、10kΩの抵抗でプルアップしていますが、デフォルトで、いずれもGNDの接続されています(0x48)。パターンをカットして、0x49、0x4A、0x4B、0x4C、0x4D、0x4E、0x4Fのいずれかのアドレスを変更できます。

 同時に利用するキャラクタ表示LCDのAQM0802のスレーブ・アドレスは0x3eと異なるため、LM75Bはデフォルトで使えますが、0x49に変更しました。

 I2CのSDAとSCLには10kΩのプルアップ抵抗が入っているので、削除します。今回利用しないOS端子はプルアップされています。

データのフォーマット

 最上位ビットから読み出されます。11ビットなので2バイトのデータとして読み出されます。D10は符号ビットです。1だとマイナスの温度です。

 11ビットのデータを読み出した後、右に5ビット・シフトし、その値に0.125℃を乗ずれば、温度が求まります。

上位バイト 下位バイト
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 x x x x x

接続

 AQM0802のソケットのピン配置は、I2Cの信号に合わせています。しかし、GPIOに挿すと、LM75Bが接続できません。回路図ではAQM0802をGPIOに挿すように書きましたが、実際は、ラズパイのGPIOにあるI2C信号の3番ピンSDA、5番ピンSCL、1番ピンの3.3V、6番ピンのGNDをブレッドボードに持ってきて配線しました。

(※)I2Cの有効化は、前回の1-Wireの説明を参照ください。1-Wireと同じく、I2CもEnableにチェックを入れています。

  i2cdetect -y 1 で配線が正しいかを確認します。3eと49にデバイスが見えているはずです。

プログラム

 LM75BとI2C接続のキャラクタLCD表示器はsmbusライブラリを利用します。変換待ちをするsleep()用にtimeライブラリを使います。

 LCDcommand()とwriteLCD()はLCD用の関数です。LCDcommand()は、LCDへ直接命令を送信します。writeLCD()は、引数に入っている文字列を表示します。initLCD()はLCDの初期化コードを送信します。

 sign16()関数は2の補数のデータから、符号のついた数字に変換します。

 LCDへは、最初は1行目、2回目は2行目、3回目は1行目のように、表示を繰り返します。

 プログラム・リストは、表示の関係でTabキーが無視されるのでスペース8個に代えてあります。また、リスト中を2回クリックすると、全選択になるので、CTRL-Cでコピーし、テキスト・エディタにCTRL-Vで貼り付けて利用してください。ラズパイに持っていくと、リターン・コードなどが化けていることがあるので、一度消して、ラズパイのテキスト・エディタで改行してください。

 プログラムを仮にlm75.pyとすると、sudo chmod 755 lm75.py で実行権を付け、ターミナルから、python lm75.pyで実行します。i2cやSPIのグループにpiユーザが属しているので、sudoは不要です。

#!/usr/bin/env python
import smbus
import time
i2c = smbus.SMBus(1)
addr=0x49 #LM75B NXP. TI is 9bit
addr02=0x3e #lcd
_command=0x00;_data=0x40;_clear=0x01;_home=0x02;display_On=0x0f;LCD_2ndline=0x40+0x80

#LCD AQM0802/1602
def LCDcommand( code ):
i2c.write_byte_data(addr02, _command, code)
time.sleep(0.1)

def writeLCD( message ):
mojilist=[]
for moji in message:
mojilist.append(ord(moji))
i2c.write_i2c_block_data(addr02, _data, mojilist)
time.sleep(0.1)

def initLCD():
LCDcommand(0x38);LCDcommand(0x39);LCDcommand(0x14);LCDcommand(0x73);LCDcommand(0x56);LCDcommand(0x6c);LCDcommand(0x38);LCDcommand(_clear);LCDcommand(display_On)
 
def sign16(x):
return ( -(x & 0b1000000000000000) |
(x & 0b0111111111111111) )
#main
initLCD()
counter = 0
while 1:
data = i2c.read_i2c_block_data(addr, 0)
raw = ((data[0]) << 8) | (data[1])
# print (hex(data[0]));print(hex(data[1]));print(hex(raw))
raw_s = sign16(int(hex(raw),16))
temp = (raw_s >> 5 ) * 0.125
print (str(temp) +"C")
counter += 1
if counter % 2 == True :
LCDcommand( _home )
else:
LCDcommand(LCD_2ndline)
writeLCD("T=" + str(temp) )
time.sleep(1)

実行例

 零度付近、マイナスの温度はテストしていません。読み出したディジタル・データの0.125℃単位の表示をしていますが、確度自体は±2℃と大きいので、絶対精度として小数点以下の意味はありません。データシートによれば、常温付近のTypicalな確度は+0.25℃しかずれていません。