トホホな疑問(16) Raspberry Pi、i2cdetect

JosephHalfmoon

この間、ラズパイのI2Cの先にセンサを付けたりしていて思ったです。いわゆるマイコンのシリアルインタフェースにセンサなどを付けた場合、デバックしようとすると「結局、信号に聞くのが一番早道」だったりします。けれどもRaspberry Piのようなシステムの場合、i2ctoolsという便利なツールがあるので、それにお任せで済ませてしまう。でもね、ツールの出力も見れば疑問が湧いてくる。やはり一度、「信号に聞いて」おいた方が安心かも。

さて、i2ctoolsの最初に取り上げさせていただくのは、i2cバスにつながるデバイスを網羅してくれる、すごーく便利なツール i2cdetectであります。

使ってみたところは以下のようです。

引数にある、-y 1 は i2c-1の方を調べてね、というオプションです。Raspberry Pi 3 model B+で、存在するi2c-0とi2c-1の2つのI2Cインタフェースの端子と使用の条件についてはこの回で調べているのでそちらをご覧くだされ。さてi2c-1の方のアドレス0x40(7ビットアドレス)にシャープ製GP2Y0E03が接続されており、i2cdetectコマンドはこれを見つけて40と健気に教えてくれてます。まず、これはどうやっているのか、信号に問うて確認しておきたい。確認のお道具はこれまた便利なDigilent社のAnalog Discovery 2です。Analogといいながら、ロジアナ機能の中にはI2Cバスをデコードして表示してくれる機能がふくまれとります。ごらんあれ、

I2Cと左に書かれている欄が、SCLとSDAをデコードした結果を表すものです。見れば、h40WR、ACK、Stopなどと書かれており、便利。16進で40番地に書き込み、その結果 ACKを受け取ったということが一目瞭然。なお、I2Cの欄に赤字でTみたいな記号が書かれているところをクリックするとトリガの条件が現れます。StartとかStopとかいろいろ設定できますが、今回は、0x40番地を見たいと分かっていたので、

アドレス0x40に書き込んだらトリガね、

と設定してあります。なお、その前に、サンプリング速度くらいは指定しておかないとちょうど良い大きさで表示されないので何だか分からなくなります。何も設定しないとRaspberry Pi 3 model B+のI2Cは 100kHz 62.5kHz(理由は次回)で動作するようなので、上記図ではサンプリング2MHz(実際にはBaseという欄で1divあたりの時間で指定)にしてみました。

こうしてみると、Clockが最初にロウに落ちた時、Dataも0で、これでStart。8発クロックが入っていて、そのときのデータを読めば10000000、頭から7ビットがアドレスなので0x40、最後の1ビットは書き込みを示す0(読み出しなら1)。そして、次のクロックでスレーブのセンサがデータ線をロウに引いてACKと。よくわかりますねえ。

相手が不在で、ACKが返ってこないときも一応確認しておきます。0x40の次は0x41に書いてみるので、そこです。

0x41番地に書き込むと、9発目のクロックのところで誰もデータ線を引くデバイスが居ないので、プルアップによってハイに吊り上がり、結果NAKになっていることが確認できました。i2cdetectコマンドは

端からI2Cの各番地のアドレスを書き込んでみて、ACKが返れば、その番地にデバイスがいると判断

しているようです。ここまでは予想どおり。しかしね、疑問に思ったのは、スキャンする対象番地を何も指定しないと、

0x03番地から0x77番地

までスキャンして、最初の3個の番地と、後の8個の番地は除かれること。朧げな記憶によれば、

I2Cの0番地はブロードキャストだっけ?

というくらい。後の番地はなんだったっけ?

たまには仕様書を読み返して記憶をリフレッシュしなければ駄目よ

ということで、復習してみました。すばらしいことに、ご本家フィリップス社の流れをくむ、NXP社のホームページには日本語ドキュメントも置いてありました。ありがたし。

UM10204 I2C バス仕様およびユーザーマニュアル

0番地、これは書き込むときはゼネラルコールアドレス、読み出すときはスタートバイトでした。ゼネラルコールアドレスは、つながっているデバイス全てに対する書き込み(ただし、仕様書読むと不要なスレーブはサポートする必要はない)なので、ブロードキャストみたいなものかな。ソフトリセットなどが定義されているので、i2cdetectコマンドがここを避けているのは当然か。

なお、読み出し時のスタートバイトというのは、I2Cのハードが無いマイコンなどでソフトで処理しようなどというときのための仕組み。今時まず使わなさそう。大抵のマイコンにはI2Cのハード積んでるし。

1番地、これはCBUSアドレスという、I2Cとは「また別」なものらしい。私は使ったことがない。また、どうも今ではもう使われなくなっている雰囲気もあります。でも、仕様書曰く(引用させていただきます)

I2C バスデバイスがこのアドレスに応答することは認められていません。

なので、i2cdetectコマンドは、触らないのでしょうか。

2番地、これは異なるバスフォーマット用に予約、だそうです。予約と言われたら、使わないのが常識人のふるまい(ときどきそうじゃない人もおられるようだが。)i2cdetecコマンドも触らない。

おっと、ところが、仕様書では3番地も「将来の仕様のため予約」、そこから4番地から7番地まではHs-modマスタコードとある。どうもHs-modマスタコードは使われなくなっているみたいですが、3番地は「予約」踏みつぶしているじゃない。さっきは常識人のホメたのですがね。もしかするとこの辺を使ってしまっている何かがあるのかな?

上位の0x78番地以降は、ちゃんと除かれているのは、使い道が決まっていて、実際、使われているからでありましょう。

0x78番地から4個、10ビットのスレーブアドレス指定用。I2Cは標準7ビットですが、アドレスに2バイト目をまるまる使って10ビットに拡張できる。そのとき残りの2ビットはここからとられる。i2cdetectは、ここは触らないようですが、10ビットアドレスには対応していないのかな?manみても書いてないように思うのですが。残り0x7C以降の4個はデバイスID、ここはNXP社以下、限られた会社の製品がユニークなIDを確保している領域。今回参照しているマニュアルには、NXP社のご担当者様にメールで「ID登録」のお願いできるようなこと書いてあります。実際には12ビットのメーカID空間に11社のみ(NXP社はご本家なので1社で4個持っているみたいだが)。ちょっと登録の条件とか興味はあるけれど。。。

トホホな疑問(15) Python、lxml、複数xsdファイル

トホホな疑問(17) ラズパイ、I2Cの速度