2012年3月7日水曜日

Arduinoで赤外線リモコンを受信、解析してみる



こちらもどうぞ
Arduinoで赤外線リモコンを受信、解析してみる(2)
Arduinoで赤外線リモコンの学習、送信(EEPROMに保存)2014/05/08

赤外線センサーPL-IRM0101-3を使い、リモコンの赤外線を解析してみましょう。

Arduinoへの接続は簡単なのですが、いざリモコンの赤外線を受信してデータ化しようとしてうまく行かないことが・・・調べながらの試行錯誤です。

リモコンの赤外線LEDが点滅して信号を送っているぐらいはわかっていたので、まずはLEDのON,OFFの時間を測定して、シリアルで送信する方向で。
点滅の長さで0/1の信号を送る方式をPPM信号というようです。



ちなみに赤外線LEDの点灯をセンサーが受信すると、センサーの出力はLOWになり、LEDが消灯するとセンサーの出力はHIGHになります。

ここでLEDの点灯と書きましたが、実際には38KHzで点滅しているんです。これをキャリア周波数と言うらしいです。
38KHzというと1サイクル=1秒/38,000≒0.0000263秒です。26.3μs、26.3マイクロ秒、26.3/100万秒とも書きます。
さらにデューティー比1/3で8.7μs秒の点灯、17.5μsの消灯を1セットにして38,000回繰り返して1秒になります。
わかりにくいですね。画像つきの丁寧な説明がされているサイトが沢山あるのでそちらを参考にしてください。

赤外線リモコンのフォーマットはだいたい家電製品協会フォーマット、NECフォーマット、SONYフォーマットに分けられるそうです。

家電製品協会フォーマットは0.4ms、NECフォーマットは0.56msを1Tとして
0 を 1TのON+1TのOFF
1 を 1TのON+3TのOFF
と、LEDの消灯時間で0/1の信号を送ります。
SONYフォーマットは点灯時間の違いで0/1を送ります。
参考:[PDF] リモコンフォーマット ※参考資料

フォーマットをきっちり守っていない信号を送るリモコンもあるようで注意。

と言うことは、上2つのフォーマットについてはONの時間を測らなくても、OFFの時間を測ればOKということでスケッチを書き換え。

実際に送信されるリモコンの信号は、
リーダーコード(送信が始まった合図)、
メーカーのコード、機能の信号、信号が乱れていないか確認するための信号、
ストップビット(信号の終わり) が送られ、他に連続して信号を送るリピートコードがあります。

ここまで来てpulseIn()という関数の存在に気づきましたが、スケッチの書き方が悪いのかうまく行かなかったので、今回は使わずに。

結局苦労してできたのは
◆Arduinoのスケッチ
int pin = 2;
unsigned long st,dur;
String val;
String sep=",";

void setup() {
  Serial.begin(115200);
  pinMode(pin, INPUT);
}

void loop() {
  st=micros();                      //計測開始の時間を記憶
  while(digitalRead(pin) == 1);     //HIGHのままならそのままループ 変化したら抜ける
  dur=micros()-st;                  //HIGHだった時間を計算
  if(dur > 100 && dur<100000){      //短すぎる,長すぎる場合は処理しない
    val=String(sep+dur);         //以下の条件で合わない場合は時間μs(リピートコードなど)
    if (dur >= 4000 && dur < 10000){     //スタートビットと判断
      Serial.println();
      val="";
    }
    if(dur < 1000){                      //0と判断
      val="0";
    }
    if(dur >= 1000 && dur < 2000){       //1と判断
      val="1";
    }
    Serial.print(val);
  }
}

シリアルモニターでみると・・・
東芝の古いテレビBAZOOKAの電源ボタンをキャプチャした結果。
手元にあったリモコンがこれしか無かったので、検証が不十分です。
32ビットの後の数字は、コードの間隔時間とリピートコードのようです。LED OFFの時間をマイクロ秒で表示しています。

スケッチの最後を
    Serial.print(val);
    Serial.print(" ");
    Serial.println(dur);
にして、HIGHの時間を計測した生データでグラフを書いてみましょう。
電源ボタンを間隔を開けて2回押しました。
縦軸はマイクロ秒。最初の4500μsはリーダーコード。

今回のスケッチ、時間を計測するのにmicros()を使っているので、リセットから時間が経つと正常に計測できないタイミングがあるかも。

近いうちに、キャプチャしたデータを元に送信できるようにしたいです。
SONYフォーマット、リピートコードなんかはスルーで。 

環境:Arduino Uno、Arduino1.0



0 件のコメント:

コメントを投稿