Raspberry pi2でI2C通信をやってみる

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

タイトルとURLをコピーしました