【Arduino】Arduino同士をI2C通信でつないでみた話
つなぎ方
いろいろなサイトで調べたけどイマイチわからなかった。
とりあえず、こんな感じで各ArduinoのSDA同士、SCL同士、グラウンド同士をつないでみる。
Arduino IDEには最初からI2Cのライブラリが入っている。
それにはサンプルも付属している。
master_writerとslave_receiverの組み合わせで試したところうまくいったようだ。
ライブラリの解説
ぶっちゃけArduino 日本語リファレンスのWireの欄を一つずつ呼んだほうがいいと思う。
使用方法関係なく使う関数
Wire.begin(address)
まずはこれ。
基本的にはsetup関数内で動かす。
これがないとWireライブラリは動かない。
引数のaddressは複数機器をI2Cで使わない限りは、適当でいいと思う。
複数使う場合はmaster側とslave側で数値を合わせる必要がある。
Wire.write(value)
これは、データを送信をする関数...って考えていい。
正確には送信用に保管するって感じかな。
下で説明するWire.onRequest()やWire.endTransmission();で保管したデータを送信する。
Wire.read()
これは送られてきたでデータを読み出すもの。
戻り値がデータなので、変数に代入して使う。
送られてきたタイミングで実行しないと受け取れないのでWire.available()をうまく組み合わせるといい。
Wire.available()
送られてきたデータが何バイトかを戻り値とする。 送られてきていなければ0。5文字のアルファベットなら5。 こんな感じでバイト数がそのまま帰ってくる。
マスターからスレーブへのリクエスト
Wire.requestFrom(address, count)
これは、slave側にリクエストを送る関数。
masterのArduinoのプログラムに記述する。
addressにはbeginのaddressと同じものを書く。
countにはリクエストするバイト数を入れる。
サンプルではcountを6にして、"H" "e" "l" "l" "o" "(改行)"を受け取っていた。
1バイトは数字なら0~255、文字なら一文字だ。
複数バイトをリクエストしても送られてくるのは1バイトずつなので注意したい。
Wire.onRequest(handler)
上のrequestFromと対になる関数。
masterからリクエストが来た時に実行する関数を決める。
slaveのArduinoのプログラムに記述する。
handleにはリクエストされたときに実行する関数名を入れる。
リクエストされた瞬間に割り込み実行されるのでslave側で動かしているプログラムがある場合は注意が必要だ。
マスターからスレーブへのリクエスト
Wire.beginTransmission(address); Wire.write(value); Wire.endTransmission();
この3つはセットだと考えていいと思う。
それ以外の使い方をしたことがない。
これは、masterからslaveに数値や文字を送るものだ。
使い方は簡単。adressにbeginと同じものを入力。
valueに送りたい数値や文字を入れます。
文字の場合は""(ダブルクォーテーション)でくくる。
Wire.onReceive(handler)
これはmasterから何らかの値が送られてきた場合に作動する関数だ。
slaveで作用する。
handlerには送られてきた時に実行する関数名を入れる。
onRequest同様、割り込みによる動作なので気を付けたい。
ちょっとした応用例
Arduino(master)ーArduino(slave)ーセンサ
とつながっているとする。
ところがこのセンサ、値の取得に数秒かかるようだ。(超音波やRGBカラーセンサ)
その間masterには待機させる。
いろいろ書き方があるだろうけど私はこう書いた。
//master #include <Wire.h> void setup() { Wire.begin(); //I2C通信スタート! Serial.begin(9600); } void loop() { byte value = 0; Wire.requestFrom(8, 1, true);//アドレス8(適当)で1バイトのデータをリクエスト! while (Wire.available() != 1) {} //1バイトのデータが帰ってくるまで空ループ value = Wire.read(); //空ループ抜けたら値読み込み Serial.println(value); }
//slave #include <Wire.h> void setup() { Wire.begin(8); Wire.onRequest(Request); } void loop() { delay(100); } void Request() { byte value = Senser(); Wire.write(value); } byte Senser(){ //センサの起動と値の取得 }
間違ってたらコメントでもください