Raspberry Pi で温度センサ LM75B を使う

[投稿日] 2015年8月25日
[最終更新] 2016年7月25日

Raspberry Pi(以下RPi)で温度センサ LM75B を使用します。日本ではスイッチサイエンスから、本記事作成時点378円でbreakoutが売られています(「LM75B温度センサ(I2C接続) – スイッチサイエンス」)。スイッチサイエンスはAmazonでも販売しています。Amazonにもあります。

スポンサーリンク

手軽に使える

RPiはUSBも備えているので、単純に温度を測りたいだけならば、「USB温度センサーで室温をモニタリングしてみた(on Ubuntu Server 12.04) : 或る阿呆の記」にあるものも使えます。こちらは送料込みで1,500円程度でしょうか。USBに差して、既にあるソフトウェアを利用するだけなのでたいへんお手軽です。

しかしこのLM75Bもたいへん気軽に試すことができます。このセンサのインタフェースはI2Cなのですが、これをRPiでは非常に簡単に利用できるからです。また、温度分解能は0.125度で、-55度から+125度まで計測することができます。データシートによれば、精度は-25度から+100度で±2度と書かれていますが、私の環境だと、常温であれば他の温度センサともだいたい±0.1か0.2度くらいの差でした。普通に使う分には十分だと思います。安いしねぇ。

Raspberry Pi でI2Cを有効化

I2Cの有効化および、必要なソフトウェアのインストールについては、「Raspberry Pi で I2C を使用する準備 – 或る阿呆の記」を参照とします。

接続

センサのSDA、SCL、Vcc、GNDを、RPiの対応するピンと接続します。接続については「RPi Low-level peripherals – eLinux.org」を参照。センサは2.8 – 5 V対応なので、電圧は3.3Vでも5Vでもよいと思いますが、できるだけ電圧が低いほうがよかろうと思い3.3Vに繋ぎました。

接続したら、以下のコマンドで 0x48 のところに出力があることを確認します。

$ i2cdetect -y 1

i2cは複数機器繋げられるので、各機器にアドレスを割り当てます。i2cdetectは、接続されている機器のアドレスを検知するものです(また、-yは対話モードでないこと、1は1chであることを示します。古いRPiの基板だと、0chであるようです)。このセンサはデフォルト設定で0x48なので、0x48に出力があることを確認します。確認できたら、接続はOKです。

温度が正の時

準備が整ったら、いよいよ温度を出力します。ここの手順は「nyaruratoの製作記録 ラズベリーパイで温度センサ(ADT7410)を触った」を参考にさせていただきました。センサは違いますが、まぁI2Cで温度センサとなればだいたいどれも同じようなものではないでしょうか。

下記コマンドを実行します。

$ i2cget -y 1 0x48 0x00 w

0x48は温度センサのアドレスで、0x00はセンサの中の温度にアクセスするアドレスです。

0xc019などと表示されますが、まずこれはエンディアンが逆になっているので、なおします。この場合0x19c0になります。エンディアンがわからない人は、ビッグエンディアン、リトルエンディアンで調べてください(投げっぱなし)。また、上位11bitしか使わないので、5bitはシフト演算で右にシフトして捨てます。また、分解能0.125度であることから、ここまでに得られた数値に0.125をかけます。小数の演算でbcを使うので、ない人はまずインストールしてください(小数点の演算は$(( ))やexprではできない)。

$ sudo apt-get install bc

では、ちょっとゴチャゴチャしますが、ワンライナーで書きます。

$ echo "$(($(i2cget -y 1 0x48 0x00 w | sed -e 's/0x\(..\)\(..\)/0x\2\1/g') >> 5)) * 0.125" | bc

少し解説すると、まずi2cgetで得られた16進数を、sedでエンディアン変換します。11bitなので、あまりの5bit分は右シフトで捨てます。分解能が0.125度なので、得られた値 * 0.125 という式を、echoでbcに渡して計算。

温度が負の時

温度が正の時であれば以上でよいのですが、温度が負の時は2の補数を求める必要があります。0度のとき 000 0000 0000 、そこからは0.125度刻みで、+127度で 011 1111 1000 で+127度と表現されるので、正のときはそのまま計算して問題ないのですが、-0.125度は 111 1111 1111 と表現されます。-55度で 110 0100 1000 です。つまり、温度が負の時は、いったん2の補数を求めて、その値に0.125をかけたものをマイナスにする、という手順が必要になります。計算的には、1000 0000 0000、つまり2048から値を引いてやればOKで、上述した式をいじるなら、マイナス限定ですけれど以下のようには書けます。

$ echo "$((2048 - ($(i2cget -y 1 0x48 0x00 w | sed -e 's/0x\(..\)\(..\)/0x\2\1/g') >> 5))) * -0.125" | bc

さすがに若干カオス感が。if文使って真面目に書いたほうがわかりやすくあんりそうですね。その場合、簡単に考えると0.125をかける前の値が1024より大きいかどうかで分岐すればよしです。1024より大きければ、2048から引いて-0.125をかける…または2048を引いて0.125をかける。

シェルスクリプトのサンプル

以上の諸々を考慮して、シェルスクリプトのサンプルをのっけます。

#!/bin/bash

set -eu

# lm75b
chip_addr=0x48
data_addr=0x00
use_bits=11
resolution=0.125

# little endian
temp_str=$(i2cget -y 1 ${chip_addr} ${data_addr} w | sed -e 's/0x\(..\)\(..\)/0x\2\1/g')
# use upper bits
shift_bits=$((16 - use_bits))
temp_num=$((temp_str >> shift_bits))

if [ ${temp_num} -ge 1024 ]; then
  # two's compliment
  temp_num=$((temp_num - 2048))
fi

echo "${temp_num} * ${resolution}" | bc

よければどうぞ。

関連コンテンツ

関連記事

スポンサーリンク

コメントを残す

メールアドレスが公開されることはありません。