赤外線リモコンの電源ON/OFF信号を送信する単純な回路を作成。
LED部分に赤外線LEDを使っています。
プッシュボタンを押すとデータを送信。
まずは、東芝TVの設定で電源ボタンのデータ(64, 191, 18, 237)を読み取る。
そのデータを単純に、1T=562μ秒として、NECフォーマットで送信するようにスケッチを作成。
さっそく、Arduino受信機で確認したらちゃんと認識した。
「なんだ、簡単じゃん」と実機(東芝のテレビ)に向かって送信すると、全然反応しない。
Arduino受信機はいろんなフォーマットに対応するようにタイミングを相対的に処理しているけど、実機は絶対値で処理していそうだから、Arduino受信機のスケッチを初期のタイミングが出るモノに切り替えて送信データのタイミングをチェック。
すると、かなり間延びした感じ。
リーダー部分が1.2倍くらい長くなっている。データ部分も若干長い。
タイミングを調整して再度実機で確認をすると反応するようになった。
しかし、実機での反応を良くするとArduino受信機でエラーになることが多くなった。
そこでArduino受信機側のスケッチを調整。
こうなってくるとArduino受信機でOKだからといって安心できないんだなぁと思った。
#define IRLED 2 #define IRSWITCH 3 void setup() { pinMode(IRLED, OUTPUT); pinMode(IRSWITCH, INPUT); } void loop() { if (digitalRead(IRSWITCH)==HIGH) { necTvPower(); } } void necTvPower() { leaderNEC(); // C0~C7 bit0(); bit0(); bit0(); bit0(); bit0(); bit0(); bit1(); bit0(); // ~C0~C7 bit1(); bit1(); bit1(); bit1(); bit1(); bit1(); bit0(); bit1(); // Data D0~D7 bit0(); bit1(); bit0(); bit0(); bit1(); bit0(); bit0(); bit0(); // ~Data D0~D7 bit1(); bit0(); bit1(); bit1(); bit0(); bit1(); bit1(); bit1(); // bit1(); } void bit0() { ledOn(); ledOff1T(); } void bit1() { ledOn(); ledOff3T(); } void leaderNEC() { int t=562*16; while (t >= 26) { digitalWrite(IRLED, HIGH); delayMicroseconds(9); digitalWrite(IRLED, LOW); delayMicroseconds(17); t-=33; } delayMicroseconds(562*8); } void ledOn() { int t=562; while (t >= 26) { digitalWrite(IRLED, HIGH); delayMicroseconds(9); digitalWrite(IRLED, LOW); delayMicroseconds(17); t-=30; } } void ledOff1T() { digitalWrite(IRLED, LOW); delayMicroseconds(562); } void ledOff3T() { digitalWrite(IRLED, LOW); delayMicroseconds(562); delayMicroseconds(562); delayMicroseconds(562); }
調整した送信スケッチ。
2013/08/27 「赤外線リモコンの製作 送信側」というページの送信キャリアの項を見たらデューティ比が1:3となていることがわかったので、ONの時を9μ秒、OFFの時を17μ秒に修正。
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x20 for a 16 chars and 2 line display #define BUFF_SIZE 256 #define NEC 1 #define AEHA 2 #define SONY 3 volatile int state = HIGH; unsigned long prev; unsigned long time; int index = 0; unsigned long buff[BUFF_SIZE]; unsigned char data[BUFF_SIZE/8]; unsigned char temp; int pos; char format = 0; int error = 0; void setup() { prev = micros(); lcd.init(); lcd.backlight(); lcd.print("Hello, world!"); //Serial.begin(9600); pinMode(13, OUTPUT); attachInterrupt(0, blink, CHANGE); } void loop() { digitalWrite(13, state); time=micros(); if ((index > 0) && (time-prev > 200000)) { error = 0; format = 0; pos = 0; lcd.clear(); analyzePass1(); analyzePass2(); lcd.setCursor(0,0); if (format==NEC) { lcd.print("NEC"); } else if (format==AEHA) { lcd.print("AEHA"); } else if (format==SONY) { lcd.print("SONY"); } else { lcd.print("UNKNOWN,"); lcd.print("Error="); lcd.print(error); } lcd.setCursor(0,1); for (int i = 0; i < pos; i++) { lcd.print(data[i]); if (i < pos-1) { lcd.print(","); } } /* Serial.println("****************"); if (format==NEC) { Serial.println("Format=NEC"); } else if (format==AEHA) { Serial.println("Format=AEHA"); } else if (format==SONY) { Serial.println("Format=SONY"); } else { Serial.println("Format=UNKNOWN"); Serial.print("Error="); Serial.println(error); } Serial.println(">>>>>>>>>>>>>>>>"); for (int i = 0; i < pos; i++) { Serial.println(data[i]); } if (error) { Serial.println("****************"); for (int i = 1; i < index; i++) { Serial.println(buff[i]); } }*/ index = 0; prev=time; } delay(10); } void blink() { state = !state; time = micros(); buff[index]=time-prev; prev=time; index++; if (index >= BUFF_SIZE) { index=0; } } void analyzePass1() { unsigned long minval = 10000000; for (int i = 0; i < index; i++) { if ((buff[i] > 350) && (buff[i] < minval)) { minval = buff[i]; } } //minval = (minval * 9) / 10; for (int i = 0; i < index; i++) { buff[i] = buff[i] / minval; } } void analyzePass2() { if (index < 20) { error = 1; return; } if (buff[2] == 0) { error = 2; return; } int leader; leader = buff[1] / buff[2]; if (leader == 2) { if ((buff[2] >= 8) && (buff[2] <= 11)) { // NEC format if (nec()) { format=NEC; } } else if ((buff[2] == 4) || (buff[2] == 5)) { // AEHA format if (aeha()) { format=AEHA; } } else { /* Serial.print("!!!buff[2]="); Serial.println(buff[2]); */ error = 3; return; } } else if ((buff[1] == 4) || (buff[1] == 5)) { // SONY format if (sony()) { format=SONY; } } else { error = 4; /* Serial.print("!!!leader="); Serial.println(leader); Serial.print("!!!buff[1]="); Serial.println(buff[1]); Serial.print("!!!buff[2]="); Serial.println(buff[2]); */ return; } } int nec() { int b = 0; temp = 0; for (int i = 3; i < index; i+=2) { if (buff[i]==1) { if (buff[i+1]==1) { // 0 } else if ((buff[i+1]==3) || (buff[i+1]==4)) { // 1 temp |= 1<<b; } else if (pos>=4) { return 1; } else { error = 5; /* Serial.print("!!!pos="); Serial.println(pos); Serial.print("!!!bit="); Serial.println(b); Serial.print("!!!buff[i+1]="); Serial.println(buff[i+1]); */ return 0; } } else if (pos>=4) { return 1; } else { error = 6; /* Serial.print("!!!pos="); Serial.println(pos); Serial.print("!!!bit="); Serial.println(b); Serial.print("!!!buff[i]="); Serial.println(buff[i]); */ return 0; } b++; if (b==8) { data[pos++]=temp; b=0; temp=0; if (pos >= BUFF_SIZE/8) { error = 7; return 0; } } } if (b > 0) { data[pos++]=temp; } return 1; } int aeha() { int b = 0; temp = 0; for (int i = 3; i < index; i+=2) { if (buff[i]==1) { if (buff[i+1]==1) { // 0 } else if ((buff[i+1]==3) || (buff[i+1]==4)) { // 1 temp |= 1<<b; } else if (pos >= 3) { return 1; } else { error = 5; /* Serial.print("!!!i="); Serial.println(i); Serial.print("!!!buff[i+1]="); Serial.println(buff[i+1]); */ return 0; } } else if (pos >= 3) { return 1; } else { error = 6; return 0; } b++; if (b==8) { data[pos++]=temp; b=0; temp=0; if (pos >= BUFF_SIZE/8) { error = 7; return 0; } } } if (b > 0) { data[pos++]=temp; } return 1; } int sony() { int b = 0; temp = 0; for (int i = 2; i < 16; i+=2) { if (buff[i]==1) { if (buff[i+1]==1) { // 0 } else if (buff[i+1]==2) { // 1 temp |= 1<<b; } else if (pos >= 3) { return 1; } else { error = 5; /* Serial.print("!!!i="); Serial.println(i); Serial.print("!!!buff[i+1]="); Serial.println(buff[i+1]); */ return 0; } } else { /* Serial.print("!!!i="); Serial.println(i); Serial.print("!!!buff[i]="); Serial.println(buff[i]); */ error = 6; return 0; } b++; } data[pos++]=temp; b=0; temp=0; for (int i = 16; i < index; i+=2) { if (buff[i]==1) { if (buff[i+1]==1) { // 0 } else if (buff[i+1]==2) { // 1 temp |= 1<<b; } else if (pos >= 1) { data[pos++]=temp; return 1; } else { error = 5; /* Serial.print("!!!i="); Serial.println(i); Serial.print("!!!buff[i+1]="); Serial.println(buff[i+1]); */ return 0; } } else { data[pos++]=temp; return 1; } b++; if (b==8) { data[pos++]=temp; b=0; temp=0; if (pos >= BUFF_SIZE/8) { error = 7; return 0; } } } return 1; }
調整した受信スケッチ。
I2C用LCD対応。