今回はRaspberrypi2でSPI通信をやってみることにします。
GPIOでは1つのポートはON/OFFの1ビットのデータしか表現できません。
これではいくつポートがあっても足りません。
そこで、I2CやSPIなどのシリアル通信バスを使って複数の機器を同時に接続すれば、多数の機器を接続できるようになります。
今回は、秋月電子の3軸地磁気センサモジュールAE-HMC5883Lを使ってみたいと思います。
raspberry piの設定
まずは、コンフィグレーションからI2Cを使用する設定に変更する必要があります。
#sudo raspi-config
「8 Advanced Options」 → 「A7 SPI」 → 「I2C enable」
/etc/modulesに下記の1行を追記(書いてあれば不要)
i2c-dev
/etc/modprobe.d/raspi-blacklist.conf の
#blacklist i2c-bcm2708
を
blacklist i2c-bcm2708
に変更する。
一旦再起動して
下記のツールをインストール
#sudo apt-get install i2c-tools
接続と確認
デバイスの接続については簡単です
デバイスのVDDを3.3V、GNDをグランドに、SDAとSCLをそれぞれ接続するだけでOK。
本来プルダウン抵抗がいるらしいが、どうもすでに入っているらしいのでそのまま接続しました。
接続確認コマンドは以下の通り
# i2cdetect 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1. I will probe address range 0x03-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
このデバイスのアドレスは0x1Eなので、ちゃんと認識されたようです。
では、さっそく通信を行ってみましょう
内部アドレス0x0a~0x0cの値が動作確認用のレジスタのようです。
i2cgetコマンドでデータの取得が行えます。
root@raspberrypi:~# i2cget -y 1 0x1E 0x0a 0x48 root@raspberrypi:~# i2cget -y 1 0x1E 0x0b 0x34 root@raspberrypi:~# i2cget -y 1 0x1E 0x0c 0x33
のような値が返ってくれば成功です。
電源投入後はアイドルモードになっているので計測されないようです。
モードレジスタ(0x02)に0x00を書き込むと計測開始になります。
その後、ステータスレジスタ(0x09)の1bit目が立ったらデータが取得可能になります。
データは0x03-0x08でXZY軸の順でMSB/LSBの順に入ります。
root@raspberrypi:~# i2cset -y 1 0x1E 0x02 0x00 ##計測開始コマンド root@raspberrypi:~# i2cget -y 1 0x1E 0x09 ##ステータス取得 0x11 ##第1bitが1なので測定している root@raspberrypi:~# i2cget -y 1 0x1E 0x03 #X軸取得(上位) 0x00 root@raspberrypi:~# i2cget -y 1 0x1E 0x04 #X軸取得(下位) 0xcc
なんだかよくわかりませんので、プログラムで連続取得してみます。
#include <stdio.h> #include <string.h> #include <errno.h> #include <wiringPi.h> #include <wiringPiI2C.h> int main(void){ int ID; int fd,ret; int LSB,MSB,data; ID = 0x1E; fd = wiringPiI2CSetup(ID);//I2Cオープン printf("setup return : 0x%x\n",fd); /* start senser */ if((wiringPiI2CWriteReg8(fd,0x02,0x00))<0){ //測定開始 printf("write error register 0x2"); } while(1){ while(1){ ret = wiringPiI2CReadReg8(fd,0x09); //取得可能状態になるまで待機 if(ret && 0x01){ //printf("start:0x%x\r\n",ret); break; } } //各軸の値を取得 MSB = wiringPiI2CReadReg8(fd,0x03); LSB = wiringPiI2CReadReg8(fd,0x04); printf("X:0x%02x%02x ",MSB,LSB); MSB = wiringPiI2CReadReg8(fd,0x05); LSB = wiringPiI2CReadReg8(fd,0x06); printf("Z:0x%02x%02x ",MSB,LSB); MSB = wiringPiI2CReadReg8(fd,0x07); LSB = wiringPiI2CReadReg8(fd,0x08); printf("Y:0x%02x%02x ",MSB,LSB); printf("\r"); delay(100); } return 0; }
実行すると以下のように表示されます。
root@raspberrypi:~# ./compas
setup return : 0x3
X:0x00a9 Z:0xff80 Y:0xffb5
センサーを傾けると、それに伴って数値が変化ことが確認できるかと思います。
いかがでしょうか?専用ポートがあればI2Cデバイスの通信は意外と簡単です。
仕様書さえ理解できれば、そんなに難しくありません。ぜひ試してみてください。