RaspberryPiとArduinoでI2C通信
RaspberryPiとArduinoを併用したいことがあると思います。通信方法としてはいくつかあると思うのですが、今回はI2C通信の方法に関して今回はご紹介したいと思います。
尚、Arduino同士のI2C通信の記事も書いているので興味のある方は是非こちらの記事もご覧ください。
また、今回はラズパイ側のコードはC言語を利用しています。PythonでのI2Cの方法は改めて記載したいと思います。RaspberryPiのバージョンに関しては最新のRaspberryPi4は勿論、RaspberryPi3でも動作可能です。
1. I2Cの有効化
まずはデフォルトで無効化されているI2Cを有効化します。
過去にI2Cを利用したことのある方は設定されていると思いますので、必要がないかもしれません。
尚、今回はヘッドレス(CLI)での設定方法を紹介します。
1-1. 設定を開く
これはI2Cに限らずラズパイの設定全般に使えるコマンドなので、覚えておくといいです。
1 |
$ sudo raspi-config |
開くとこのように設定の一覧が表示されます。
この中から 5. Interface Options を選択してください。
尚、設定一覧の内容はバージョンによって増えたり減ったりしていることがあるので、5番目ではないかもしれないです。
1-2. I2Cの有効化
I2Cを選択します。
「I2C有効化しますか?(要約)」と質問されるので元気よく「Yes」と答えてください。
これで有効化は完了です。
2. I2Cの確認方法
ラズパイはI2Cで接続しているスレーブのアドレス一覧を取得するコマンドがあります。
その使い方をまずは紹介しています。
2-1. スレーブ一覧の取得方法
まずは接続されているスレーブの一覧を取得します。
1 2 3 4 5 6 7 8 9 10 |
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
このように 0x03 ~ 0x77 までの接続されているスレーブのアドレスを一覧で取得し表示します。未接続の場合は上のように何も表示されません。
2-2. 試しにArduinoをスレーブにする
ArduinoにI2Cのスレーブ用のコードを書き込んでください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <Wire.h> void setup() { // 自身のアドレスを指定 Wire.begin(0x31); } void loop() { delay(100); } |
指定方法は他にもあるそうですが、今回は Wire.begin(); に自信のアドレスを指定しています。 #include <Wire.h> でI2Cに必要なライブラリもインクルードしておきます。
2-3. ラズパイとArduinoの配線
基本的にI2Cは
- SDA(データ用)
- SCL(クロック用)
- GND
を接続する必要があります。
今回の配線図は以下の通り。
Arduino UNOの場合は、以下のような配線になります。
- A4(Arduino)- GPIO2(RaspberryPi) =SDA
- A5(Arduino)- GPIO3(RaspberryPi) =SCL
- GND(Arduino)- GND(RaspberryPi)
GNDに関しては両方ともどこを使ってもOKです!
2-4. 再度スレーブ一覧の取得
再度取得します。
1 2 3 4 5 6 7 8 9 10 |
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- 31 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
先程指定したスレーブのアドレス 0x31 が認識されていればOKです。
3. I2Cしてみる
お待たせしました、本題のArduinoとラズパイでI2Cを行います!
3-1. Arduino側コード
Arduino側はスレーブになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <Wire.h> void setup() { // 自身のアドレスを指定 Wire.begin(0x31); // マスターからのリクエスト時の処理 Wire.onRequest(send_count); } void loop() { delay(100); } byte count = 0; void send_count () { // カウント数を送信 Wire.write(count++); } |
3-2. RaspberryPi側のコード
Raspberry Pi 側のI2Cのマスター用のコードはこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <stdio.h> #include <wiringPiI2C.h> int main (void) { // I2C接続 int fd = wiringPiI2CSetup(0x31); // 接続の確認 if (fd == -1) { printf("I2C接続に失敗しました。\n"); return 1; } // I2Cでスレーブからデータ取得 for (int i = 0; i < 3; i++) { printf("%d回目\n", wiringPiI2CRead(fd)); } return 0; } |
3-3. ビルドと実行
ビルドの際には今回使用するライブラリ wiringPi を指定してください。
1 |
$ gcc -o i2c main.c -lwiringPi |
実行結果はこちら
1 2 3 4 5 6 7 8 |
$ ./i2c 0回目 1回目 2回目 $ ./i2c 3回目 4回目 5回目 |
処理内容としては、スレーブ側は呼び出されるたびに変数の中身をインクリメントして返しています。
この変数の値はラズパイ側の挙動に関係なく、Arduino自体が再起動・書き込みされるまでは基本的に保持されます。
最後に
wiringPiの使い方に関しては公式リファレンスを見てみたのですが、情報量が少ないように感じました。公式のDiscordチャンネルがあるので、技術的な不明点があるという方はそこで質問して見るといいと思います(英語のみですが)
私のTwitterでも質問可能ですので、質問がありましたら @reerishun までご質問ください。
参考にした記事
- Raspberry PiでI2Cの設定と使い方 – Indoor Corgi
- Raspberry PiでI2C接続キャラクターディスプレイを制御する/CPU温度の表示 – 雑記帳
- I2C Library – Wiring Pi
今回のブログ曲
今回投稿中に聴いていた曲はこちら