RaspberryPiで簡単にI2Cデバイスを使う方法(HTU21D)

段々夏らしい気温になってきた.そこで,今回は RaspberryPi を使って持て余していた湿度センサを例にI2Cデバイスを使う方法を書く.

必要なもの

手元にあったこの赤いセンサは既に販売終了しているようだが,こっちの青いセンサでも使い方は同じ.

Adafruit HTU21D-F 温度/湿度センサ(I2C通信) - スイッチサイエンス
HTU21D-F 温度/湿度センサのピッチ変換基板です。I2C通信。

RaspberryPiを設定する

raspi-configでI2Cを有効にする

$ sudo raspi-config

設定箇所は Interfacing Options > I2C .

必要なパッケージをインストールする

$ sudo apt install i2c-tools bc

I2Cを使う方法はC言語やPythonなど色々あるけれど,今回はあくまで簡単に使うだけなのでi2cget/i2csetコマンドを使ってモジュールを操作していく.加えてモジュールから取得した値を計算するためにbcコマンドもインストールしておく.

ここまでの状態でカーネルモジュールも読み込まれ,1番のI2Cバスが生成されている.

$ lsmod | grep i2c
i2c_bcm2835 16384 0
i2c_dev 20480 0
$ ls /dev/i2c*
/dev/i2c-1

I2Cモジュールの使い方

RaspberryPiとモジュールを接続

接続図

RaspberryPiとモジュールを図のような形で接続する.どのピンが何なのかわからないときは公式の情報を参照する.公式情報に記載のある通り,Pinout Leafを使うとわかりやすい.

モジュールを操作する

仕様書を読んでI2Cのスレーブアドレスとコマンドの仕様を確認する.

アドレス:0x40

I2Cのアドレスは先頭から7bit部分で,残りの1bitはコマンドを送る際のread/writeを表すのに使う.これはどのモジュールでも共通.

I2Cバスの状態を確認するとモジュールが認識されていることがわかる.

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

仕様書から抜粋したコマンドは以下の通りで,湿度と気温の測定が出来る.各コマンドRead/Writeどちらで使うかは仕様書を読んで確認する.慣れてくると感覚で判別出来るようになるかもしれない.

CommandCodeComment
Trigger Temperature Measurement0xE3Hold master
Trigger Humidity Measurement0xE5Hold master
Trigger Temperature Measurement0xF3No Hold master
Trigger Humidity Measurement0xF5No Hold master
Write user register0xE6
Read user register0xE7
Soft Reset0xFE
コマンド一覧(仕様書より抜粋)

例えば設定を読み取る(0xE7)場合,シーケンス図は次のようになっている.2列目の部分までが設定を読み取っている部分で,0xE7をwriteで送信した後にreadで結果を待っている.

Read/Write user register sequence(仕様書より抜粋)

これはi2cgetコマンドを使って次のようになる.今回はデフォルトのままで問題ないので,どのビットが何を表しているのかは説明しない.詳細は仕様書の「User register」の項目を参照のこと.ついでに設定を変更する場合はi2csetコマンドを使って書き込む.

$ i2cget -y 1 0x40 0xE7
0x02
$ i2cset -y 1 0x40 0xE6 0x02 i

i2cget/i2csetコマンドの挙動についてはこのページがよく検証されているので参考にするといい.

RasberryPIのI2Cコマンド詳解 — かないノート

ここまででコマンドの使い方がわかってきたと思うので,いよいよ気温を測定してみる.気温の計算には応答の先頭16bitが必要なので,コマンド末尾にオプションwをつける.

$ i2cget -y 1 0x40 0xE3 w
0x3870

ここでRaspberryPiはリトルエンディアンなので,i2cgetコマンドの結果は 0x7038 として処理する必要がある.

$ lscpu | grep 'Byte Order'
Byte Order: Little Endian

また,末尾2bitは測定したデータが気温か湿度のどちらなのか判別する部分であり,仕様書にある通り計算前に0にしておく必要がある.

The two status bits, the last bits of LSB, must be set to ‘0’before calculating physical values.

ここまでの情報を整理して,仕様書の変換式に当てはめて計算すると次のようになる.bashだけでは複雑な計算は難しいので,計算出来るのは気温と湿度くらい.C言語やPythonなどなど計算しやすい言語を使えば他の変換式も使えるが,今回の目的は簡単にI2Cモジュールを使うことなので,気温と湿度が計算できれば良しとする.

$ RET=$(i2cget -y 1 $ADDRESS $CMD_mTemp_HM w)
$ RAW=$(( ($RET & 0xfc00)>>8 | ($RET & 0x00ff)<<8 ))
$ TEMP=$(echo "scale=2; -46.85+175.72*$RAW/65536" | bc ) # 65536 = 2^16
$ echo $TEMP
30.17

簡単に使えるように簡単なスクリプトを書いた.需要があれば参考にどうぞ.

$ ./htu21d.sh help          # HELP
Usage: htu21d.sh [OPTION]
 t    measure temperature
 h    measure relative humidity
 help show this message

おわりに

HTU21Dを例にRaspberryPiで簡単にI2Cデバイスを使う方法を書いた.bashだけではあまり複雑な計算は出来ないので,変換式が複雑なものは別の言語も使う必要がある.

$ echo -e "temp=$(./htu21d.sh t)\nhumi=$(./htu21d.sh h)"
temp=33.66
humi=57.94

そろそろ暑い...

コメント

タイトルとURLをコピーしました