今回は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デバイスの通信は意外と簡単です。
仕様書さえ理解できれば、そんなに難しくありません。ぜひ試してみてください。
