RaspberryPi と各種センサ モジュールを接続する際の接続方法について覚書き。
I2C
- 同じ基盤上くらい近距離でデバイス同士が kbps オーダーの速度でシリアル通信を行う目的で開発されたもので、装置間のような遠距離通信には向いていない。おそらく通信エラー訂正などはない。
- データ線(SDA)、クロック線(SCL)、GND 線のたった 3 本で通信できるシリアル バス。
- 実際はセンサ モジュールなどの電源が必要になるので、実質 4 本の結線が必要なことが多い。
- バス型トポロジで、複数の機器を接続する際は、同じバス上にどんどん並列に追加すればよい。
- 1 つのマスタ機器(RaspberryPi)が、バスに接続された複数のスレーブ機器(センサ モジュール)を制御する。
- マスタ機器が送信するクロック信号に合わせて、データ線にデータが流れる。スレーブ機器は、クロック線のクロック信号に合わせて、データ線上にデータを読み書きする。
- それぞれのスレーブ機器がアドレスを持っており、また、データ線を流れるデータにもアドレスが含まれる。このアドレスを指定することで、バスにつながれた複数のスレーブの中から、目的のスレーブとデータの送受信が行える。
- このアドレスの仕様上、最大 112 個ものスレーブを同じバスに接続できるが、センサ モジュールなどでは数種類のアドレスから選択できる程度だったり、そもそもアドレスが固定だったりと、バスに同一製品を複数接続するには工夫が必要なものがある。
- RaspberryPi では、ピン番号 3 が SDA、ピン番号 5 が SCL に割り当てられており、そのすぐ近くに、5V、3.3V、GND もある。
### I2C バスがあるか?
$ ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 1 2月 3 17:11 /dev/i2c-1
### バスに接続されたスレーブを探す
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e --
...
### デバイスからデータを読み出す
$ i2cget -y 1 0x1e 0xa
0x48
### デバイスにデータを書き込む
$ i2cset -y 1 0x1e 0x02 0 b
リンク
SPI; Serial Peripheral Interface
- コンピュータ内部などにおいて、周辺 IC 同士をシリアル接続して同期通信を行う目的で開発された。
- RaspberryPi や Arduino 関係の接続では I2C の方がメジャーで、SPI 接続の機器はあまり見かけない感じ。
- マスタとスレーブが 1 対 1 で通信するスター型トポロジ。
- 信号線は、クロック(SCLK)、2 本のデータ線入力(MISO、MOSI)、スレーブ選択(SS)と GND 線の高々 5 本で済む。一つのデバイスに限って通信するのであれば、SS が不要になるので 4 本の信号線で済む。
- 実際はセンサ モジュールなどの電源のために、追加でもう 1 本必要だったりする。
- RaspberryPi では、ピン番号 21 (GPIO10) が MOSI、ピン番号 23 (GPIO9) が MISO、ピン番号 25 (GPIO11) が SCLK に割り当てられている。また、ピン番号 24 (GPIO8) とピン番号 25 (GPIO7) が SS で、最大 2 台の SPI デバイスと通信できる。
- 更に多くのデバイスを扱いたい場合には、GPIO と 74x138 や 74x139 などの n-to-m ライン デコーダを利用して、SS をスイッチするなどの工夫が必要になる。
リンク
GPIO
- I2C や SPI のような通信規格に乗っていない独自規格の通信プロトコルを持つセンサ類の場合、GPIO に接続して、自前で通信内容を解析するプログラムを書く必要がある。
- 例えば、超音波距離センサモジュール HC-SR04 を使う場合、GPIO に計測開始トリガを出力してから、反射波を検知してセンサの出力ポートが H⇒L と変化するのを監視するようなプログラムを書く必要がある。
- 例えば、温度湿度センサモジュール DHT11 を使う場合、センサが出力する独自プロトコルのシリアル データを読み出すプログラムを自前で書く必要がある。