I2C通信のしくみについてはここがとてもわかりやすかったです。
用意するもの
・Arduino UNO 2個
・抵抗(4.7kΩ) 2個
・測距モジュール GP2Y0A21YK
・タクトスイッチ
今回はI2C通信を使って、スレーブのArduinoに繋いだ測距センサーで計測した値をマスター側で確認することと、同じくスレーブ側のスイッチのON/OFFをマスター側で確認するということをします。
余談ですがこの測距モジュール、GNDがオレンジでVccが黒というトラップがあるので注意。
センサーから値を得る
Analog inの4がSDA、5がSCLでそれぞれを5Vからプルアップ抵抗をはさんだところに繋ぎます。手持ちの4.7kΩを繋いだのですが、どうもここによると今回使う「Wire.h」のほうで内部プルアップ抵抗をONにする設定をしてくれているそうなので、いらないと言えばいらないです。
ちなみに上がスレーブで下がマスターです。
先述したとおり、「Wire.h」を利用するのですが、使い方はArduinoのリファレンスでWireのところを参照してください。
「スレーブ側」↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <Wire.h> #define dist_PIN 1 void setup() { Serial.begin(9600); Wire.begin(8); // スレーブのアドレスを8に設定 Wire.onRequest(psd); // マスターに呼ばれたときに呼び出す関数 } void loop() { delay(100); } void psd() { // 以下は距離[cm]を求める近似計算 int temp,distance; temp = analogRead(dist_PIN); if (temp<4) temp = 4; // 0除算を回避 distance = (6787 / (temp - 3) ); Wire.write(distance); // 1バイト送信 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <Wire.h> void setup() { Serial.begin(9600); Wire.begin(); // マスターに設定 } void loop() { // スレーブの8番に接続されているデバイスから1バイトのデータを取得 // 送られてくる値は10進数で255以下、つまり1バイト以内であるため Wire.requestFrom(8, 1); // Wire.available()がfalseになるまでループ // 要求より短いデータがくる可能性あり while (Wire.available()) { int c = Wire.read(); // 1バイト受信 Serial.print(c); } Serial.println( " cm" ); delay(500); } |
スイッチのON/OFF (文字列の送信)
配線例 同じく上がスレーブで下がマスターです。
「スレーブ側」↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <Wire.h> int pullup =1; void setup() { Serial.begin(9600); Wire.begin(8); // スレーブのアドレスを8に設定 Wire.onRequest(on_off); // マスターに呼ばれたときに呼び出す関数 pinMode(12,INPUT_PULLUP); //内部プルアップ抵抗を使う } void loop() { delay(100); } void on_off() { pullup = digitalRead(12); if (pullup == 0){ Wire.write( "ON " ); // 3バイト送信 } else { Wire.write( "OFF" ); // 3バイト送信 } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <Wire.h> void setup() { Serial.begin(9600); Wire.begin(); // マスターに設定 } void loop() { // スレーブの8番に接続されているデバイスから3バイトのデータを取得 // 送られてくるのは3バイトの文字列であるため Wire.requestFrom(8, 3); while (Wire.available()) { char c = Wire.read(); // 1バイト受信 Serial.print(c); } Serial.println( "" ); delay(500); } |
結果
Wire.hを使って思ってたよりも簡単にI2C通信をすることができました。
今回はスレーブから値を読み取るだけでしたが、他にもマスターからスレーブへの命令を飛ばしたり、以前作った量産型Arduinoを複数台繋げたり、Raspberry Piを購入したのでそれとも繋げたりしたいです。
次回→Arduino同士でI2C通信(2)
※2015/04/16 追記
I2C通信するシリーズに記事を追加しました
→【Ruby】 Raspberry Pi とArduinoでI2C通信
参考ページ
Arduino Duemilanoveを2個I2C接続
2台のarduinoをI2Cバスで接続して通信を行う実験
参考書籍
Arduinoで電子工作をはじめよう!
0 件のコメント:
コメントを投稿