バージョン情報
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); }