バージョン情報
Arduino IDE 1.0.6 ,windows 8.1
3台のArduinoをI2Cで接続し通信してみた。
マスター側は赤外線リモコン。
Arduinoで赤外線リモコンとシリアル通信
スレーブ1は7セグ。
Arduino スレーブその1: 1桁7セグ
スレーブ2はサーボ。
Arduino スレーブその2:サーボ
I2C通信を使うに場合はArduino同士の以下のピンを接続する。
・A4 (SDA):データ送受信用
・A5 (SCL):通信用クロック
ソースコード
以前作ったプログラムはシリアル通信(UART)用につくったので、I2C用に書き換える。とはいえ、Wire.hを使うので少し変えるだけでできた。
・Wire.h を include
・Serial.begin(9600) >> Wire.begin()
・Serial.println(“0”) >> Wire.write(“0”)
・Wire.write()の前にWire.beginTransmission(スレーブのアドレス)
・Wire.write()の後にWire.endTransmission()
【マスター側】
//IRリモコンコントローラ I2C master
#include <Wire.h>
#define IR_IN 10
#define IR_DATA_SIZE 100//768
byte ir_data[IR_DATA_SIZE];
byte ir_code[32];
byte ir_result;
void setup() {
Wire.begin();
pinMode(IR_IN, INPUT_PULLUP);
}
void loop() {
ir_result = ir_read(IR_IN);
if (ir_result > 0){
print_comand(ir_result);
}
}
//データ受信
byte ir_read(byte ir_pin){
unsigned long now, last, start_at;
boolean stat;
start_at = micros();
//2.5秒以上入力がなかったら終了
while(stat = digitalRead(ir_pin)){
if(micros() - start_at > 2500000) return 0;
}
digitalWrite(13,HIGH);
for(int i = 0; i < IR_DATA_SIZE; i++){
ir_data[i] = 0;
}
start_at = last = micros();
for(int i = 0; i < IR_DATA_SIZE; i++){
//入力が反転するまで待ち(上限25ms)
while(1){
if(stat != digitalRead(ir_pin)) break;
//信号終了
if(micros() - last > 25000){
digitalWrite(13,LOW);
return ir_get_data();
}
}
now = micros();
ir_data[i] = (now - last)/100; //byteに格納するあため
last = now;
stat = !stat;
}
}
//データ解析
byte ir_get_data(){
int j = 0;
byte result = 0;
//1or0判定
for (int i = 3; i < 66; i+=2){
if(ir_data[i] > 10){
ir_code[j] = 1;
}else{
ir_code[j] = 0;
}
j++;
}
//データを数値化
for (int i = 0; i < 8; i++){
if(ir_code[i+16] == ir_code[i+24]){ //反転データチェック
result = 0;
break;
}else{
bitWrite(result,i,ir_code[i+16]);
}
}
return result;
}
//コマンド出力
void print_comand(byte ir){
switch (ir){
case 69:
//Wire.write("power");
break;
case 70:
//Wire.write("mode");
break;
case 71:
//Wire.write("mute");
break;
case 68:
Wire.beginTransmission(2);
Wire.write("play");
break;
case 64:
Wire.beginTransmission(2);
Wire.write("back");
break;
case 67:
Wire.beginTransmission(2);
Wire.write("forward");
break;
case 7:
//Wire.write("EQ");
break;
case 21:
//Wire.write("-");
break;
case 9:
//Wire.write("+");
break;
case 22:
Wire.beginTransmission(1);
Wire.write("0");
break;
case 25:
//Wire.write("repeat");
break;
case 13:
//Wire.write("SD");
break;
case 12:
Wire.beginTransmission(1);
Wire.write("1");
break;
case 24:
Wire.beginTransmission(1);
Wire.write("2");
break;
case 94:
Wire.beginTransmission(1);
Wire.write("3");
break;
case 8:
Wire.beginTransmission(1);
Wire.write("4");
break;
case 28:
Wire.beginTransmission(1);
Wire.write("5");
break;
case 90:
Wire.beginTransmission(1);
Wire.write("6");
break;
case 66:
Wire.beginTransmission(1);
Wire.write("7");
break;
case 82:
Wire.beginTransmission(1);
Wire.write("8");
break;
case 74:
Wire.beginTransmission(1);
Wire.write("9");
break;
default:
;
}
Wire.endTransmission();
}
【スレーブ1】
こちらもシリアル通信(UART)用の部分を、I2C用に書き換える。
・Wire.h を include
・Serial.begin(9600) >> Wire.begin(スレーブのアドレス)
・Wire.begin の後に Wire.onReceive(関数名);
・Serial.available() >> Wire.available()
・Serial.read() >> Wire.read()
Wire.onReceiveで呼ぶ関数は『void 関数名(int 変数名)』でないとエラーになるようだ。
//7seg I2c
#include <Wire.h>
#define BUZZER 5
#define P_a 6
#define P_b 7
#define P_c 13
#define P_d 10
#define P_e 11
#define P_f 9
#define P_g 8
#define P_dp 12
char charA_out[80];
int freq;
void setup() {
pinMode(BUZZER,OUTPUT);
pinMode(P_a,OUTPUT);
pinMode(P_b,OUTPUT);
pinMode(P_c,OUTPUT);
pinMode(P_d,OUTPUT);
pinMode(P_e,OUTPUT);
pinMode(P_f,OUTPUT);
pinMode(P_g,OUTPUT);
pinMode(P_dp,OUTPUT);
Wire.begin(1);
Wire.onReceive(myReadLine);
}
void loop() {
delay(100);
}
void myReadLine(int a){
int cnt_buf = 0;
//受信したら
if(Wire.available() > 0){
delay(100);
cnt_buf = max(79,Wire.available()); //受信文字数 最大79文字
for (int iii = 0; iii < cnt_buf; iii++){
charA_out[iii] = Wire.read();
}
charA_out[cnt_buf] = '\0'; //終端文字
}
seg_num(atoi(charA_out));
}
void seg_num(int num){
//7セグに数字を出力
byte out_seg;
switch (num){
case 0:
out_seg = B11111100;
break;
case 1:
out_seg = B01100000;
break;
case 2:
out_seg = B11011010;
break;
case 3:
out_seg = B11110010;
break;
case 4:
out_seg = B01100110;
break;
case 5:
out_seg = B10110110;
break;
case 6:
out_seg = B10111110;
break;
case 7:
out_seg = B11100000;
break;
case 8:
out_seg = B11111110;
break;
case 9:
out_seg = B11110110;
break;
default:
out_seg = B00000001;
}
seg_disp(out_seg);
}
void seg_disp(byte out){
digitalWrite(P_a,bitRead(out,7));
digitalWrite(P_b,bitRead(out,6));
digitalWrite(P_c,bitRead(out,5));
digitalWrite(P_d,bitRead(out,4));
digitalWrite(P_e,bitRead(out,3));
digitalWrite(P_f,bitRead(out,2));
digitalWrite(P_g,bitRead(out,1));
digitalWrite(P_dp,bitRead(out,0));
}
【スレーブ2】
//スレーブ:サーボ
#include <Servo.h>
#include <Wire.h>
#define servo_1 9
#define button_1 11
#define button_2 12
String str_cmd = "";
Servo myservo_1;
int angle = 90;
void setup() {
myservo_1.attach(servo_1);
pinMode(button_1, INPUT_PULLUP);
pinMode(button_2, INPUT_PULLUP);
Wire.begin(2);
Wire.onReceive(myReadLine);
}
void loop() {
//ボタンで手動操作
if (digitalRead(button_1) == 0){
angle = min(angle + 10,180);
myservo_1.write(angle);
}
if (digitalRead(button_2) == 0){
angle = max(angle - 10,10);
myservo_1.write(angle);
}
delay(20);
}
void myReadLine(int a){
int cnt_buf = 0;
str_cmd = "";
char ch;
//受信したら
if(Wire.available() > 0){
delay(100);
cnt_buf = Wire.available();
for (int iii = 0; iii < cnt_buf; iii++){
ch = Wire.read();
str_cmd.concat(ch);
}
}
action_servo();
}
//サーボアクション
void action_servo(void){
if(str_cmd.endsWith("action")){
char chA[5];
str_cmd.toCharArray(chA,4);
myservo_1.write(constrain(atoi(chA),10,180));
}else if(str_cmd == "play"){
myservo_1.write(90);
}else if(str_cmd == "back"){
myservo_1.write(10);
}else if(str_cmd == "forward"){
myservo_1.write(180);
}
delay(20);
}





