Repeated Start

秋月電子通商でI2C接続の温度センサーモジュールが発売されたので、入手してRaspberry Piに接続してみた。小型の基板にアナログ・デバイセズ社のADT7410とプルアップ抵抗が乗っていて、ピンヘッダで端子が出ているからブレッドボードで試すには最適。
R0012030

電源と信号線をつないでi2cdetectツールでチェックすると、デバイスアドレスは正しく読み出せる。

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

ところが、i2cdumpでレジスタを読み出すとこんな値になってしまう。

>$ i2cdump -y 1 0x48
No size specified (using byte-data access)
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e    ????????????????
10: 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e    ????????????????
20: 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 0e 00    ???????????????.
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

pythonでプログラムを書いて読み出してもやはり同じ。
色々と試してみると、どうやらどのアドレスを読んでも、レジスタ$00の値が帰ってきているように思える。

どうも良く分からないのでネットで調べてみると、Raspberry Piのフォーラムに該当すると思われるスレッドがあった。I2Cで通信を行うときの手順として、レジスタにアクセスする時にRepeated Start Conditionが必要なデバイスに、smbusモジュールが対応していないのが根本的な原因らしい。

ArduinoでI2Cデバイスにアクセスする場合は、読み書きするレジスタアドレスを最初に書き込んでから次に読み書きするという、低レベルなライブラリなので問題は生じなかったが、Raspberry Piの場合はsmbusモジュールの内部でその処理が行われているので簡単には対処できない。

Raspberry Pi用のPerlモジュールHiPiはその問題に対応済みという情報があったので、インストールして試してみる事にした。インストールはここの手順に従った。

モジュールのインストールと同時にインストールされるI2Cのコマンドラインツールで再度試すと、明らかに結果が違う。ADT7410のアドレス$00と$01は計測した温度の値が返ってくるレジスタで、i2cgetで読み出すと以下のようになる。

$ i2cget -y 1 0x48 0
0x0e
$ i2cget -y 1 0x48 1
0x0e

$00と$01が同じ値になっているが、hipi-i2cで読み出すと

$ hipi-i2c r 1 0x48 0 1
14
$ hipi-i2c r 1 0x48 1 1
224

となっていて明らかに違う値だ。16進に直すと$00の値は0x0e、$01の値は0xe0になる。
温度は$00のビット6~0と、$01のビット7~3をつないだ12ビットの値を16で割った数値になるので、0x1dc(476)を16で割って29.75度という事になる。これは部屋の温度計とほぼ一致している。

以上の事からADT7410を使ってRaspberry Piで温度を計測する場合、現時点ではsmbusを使うと上手く行かない事が判った。これ以外のI2Cデバイスでも、使用できないものがいくつかあるようなので注意が必要だ。

ハードウェア的な問題では無いので、近いうちに対応されるのではないかと思う。WiringPiにもI2Cの機能があるが、そちらはどうなっているのかは未確認。WiringPi2がリリースされているのでそちらと一緒に試してみる予定。

※6/22追記
smbusモジュールがRepeated Start Conditionに非対応なのではなく、Raspberry PiのコントローラBCM2835がハードウェア的に非対応という情報があった。HiPiモジュールはコントローラの機能を使用せずに、ソフトウェア的に行っているのかも知れない。
この件については引き続き調べてみる。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中