Arduinoを2つ使ってI2C通信を試してみました
I2C通信は2本の線のみで通信を出来ると分かっていましたが少々思っていた相互通信とは違うようでした
MasterとSlaveの関係
I2C通信する端末は親(Master)と子(Slave)のの関係になり通信を行っているようです(わかりにくい. . .)
Masterからの命令に対してSlaveが応答する形で動作するというものでした
なのでSlave同士での通信やSlaveからMasterにリクエスト(命令)することはできません
ちょっと違いがありますが、Webサーバーみたいなものです
ブラウザはWebサーバー(例えばこのブログ)にアクセスしてWebサーバーはブラウザに表示するデータを返す
もう一つの例なら仕事です
お客さんからの要求に対してプログラマは製品を作りますが、お客さんに仕事ちょうだいよとかプログラマは言いませんね
(これ以上説明はむずいので参考にしたサイト見てください。。。)
参考にしたサイトのプログラムをぱっk. . . 参考にして試してみました
とりまやってみる
(Arduino NANOは関係ありません)
Master(奥のArduino UNO)
ID8番のSlaveに1Byteのデータを要求してその値をシリアル通信で表示します
Slave(手前のArduino UNO)
Masterからの要求ごと1ずつカウントアップしてその値をMasterに渡します
(それぞれのArduinoはUSBでPCに繋いでいます)
結果
できてるっぽいね
ちょっくら応用してみる
ただ要求して1ずつ増えていくのを見てもあまり面白くないのでボタンを付けてみます
MasterからSlaveに要求した時にボタンを押している状態を返すようにします
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Wire.h> | |
int cnt = 0; | |
void setup() { | |
Wire.begin(); //Masterで起動 | |
Serial.begin(9600); | |
Serial.println(""); | |
} | |
void loop() { | |
Wire.requestFrom(8, 1); //ID:8のSlaveに1Byteリクエスト | |
while (Wire.available()) { | |
char c = Wire.read(); | |
Serial.print(c); | |
if( cnt == 4 ) //4文字出力したら「 」(スペース)を入れる | |
Serial.print(' '); | |
else if( cnt == 8 ) { //8文字分出力したら改行 | |
Serial.println(""); | |
cnt = 0; | |
} | |
cnt++; | |
} | |
delay(500); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Wire.h> | |
#define BTNPIN 5 //ボタンのPIN番号 | |
char list[] = {'-','o'}; //押された時、押されていない時 | |
char output; //送信用 | |
int btn = 0; //ボタンの状態保存用 | |
void setup() { | |
pinMode(BTNPIN, INPUT); | |
Wire.begin(8); //ID:8のSlaveで起動 | |
Wire.onRequest(requestEvent); | |
} | |
void loop() { | |
btn = digitalRead(5); //ボタンの状態を取得 | |
} | |
void requestEvent() { //ボタンの状態から返す値を決定 | |
if( btn == HIGH ) | |
output = list[1]; | |
else | |
output = list[0]; | |
Wire.write(output); //送信 | |
} |
Master
参考にしたところとほぼ同じです
Slave
ボタンを押していない状態を「o」、押している状態を「-」を返すようにしています
loop関数内で常にボタンの状態を変数に確保しておき、Masterからの要求があった時変数の値を返すようにしています
ここは要求があったときにボタンの状態を返すようにしてもよかたのですが、なんでやったんだろ(オイ)
更に改良点
どうもボタンを押してなくても押していると信号が出てることがありました
スイッチにプルアップ抵抗を入れてみました
コレならしっかり出てくれます
(oが押していない時、-が押している時)
結構面白いものですが、制御が一方通行なのがあれですね. . .
それとDHT11(温湿度センサ)で取得した温度を送ろうとしましたができなかったのも気になります
I2C接続のLCDがあるので試してみたいです。
回路、プログラム参考:
参考:
<
p class=”entry-header”>2台のarduinoをI2Cバスで接続して通信を行う実験 – 猫にコ・ン・バ・ン・ワ
コメント