2012年8月20日月曜日

Arduinoから赤外線信号を送信

エアコンのリモコンとか作った そのよん。

ひとつ前のエントリで読み取ったリモコンの信号を、自前で赤外線LEDをコントロールして発信してみます。
受信のときとは異なり、キャリア周波数の変調 (38kHzで点滅させる処理) を自分でプログラムする必要があります。
…受信はセンサーが高機能なお陰で楽できました。

赤外線LEDには OSI5LA5113A を使いました。

送信ビットデータの生成


受信のときの逆処理を行うだけなので詳細は割愛。

信号データはArduino内に持つことにします。
#define SIGNAL_LEN 7

typedef struct _SignalMap {
  char chr;
  byte signal[SIGNAL_LEN];
} SignalMap;

SignalMap signalMap[] = {
  // 電源ON 冷房 風量自動 28℃
  {'C', { 0x28, 0x61, 0x3d, 0x10, 0xef, 0xbc, 0x43 } },
  // 電源OFF 冷房 風量自動 28℃
  {'c', { 0x28, 0x61, 0x3d, 0x10, 0xef, 0xac, 0x53 } },
  // terminator
  {'\0', { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
};
シリアルへ送られてきた文字に反応して、対応する信号を発信する仕様です。

キャリア周波数の変調


38kHzで点滅ということは、1周期 26.32マイクロ秒。
そんな厳密ではないと思うのですが、ON/OFFが半々だとしてもそれぞれ13マイクロ秒程度ということです。
unsigned long endTime = micros() + highTimeSpan;
while (endTime > micros()) {
  digitalWrite(PIN_IR_OUT, HIGH);
  delayMicroseconds(9);  // ※a
  digitalWrite(PIN_IR_OUT, LOW);
  delayMicroseconds(6);  // ※b
}
delayMicroseconds(lowTimeSpan);
待ち時間 (delayMicroseconds) は手探り。
各命令がどれぐらいの時間を使うのか調べるのが正しい方法かもしれません。。。
とりあえずこれでうちのエアコンは受け付けてくれました。

なお事前に友人が作った赤外線送信のスケッチを見せてもらっていたのですが、それと同じ時間(上記の a=9, b=7)ではうちのエアコンは反応しませんでした。ここらへん機器によって微妙に差がありそうです。

OSI5LA5113Aの指向性


かなり狭い角度にしか信号が届きません。
データシートを見ると ±3°ぐらい。体感でも 10°ずらすとダメな感じ。
これに気付かずハマったorz

テスト


このままでは実際に発信している信号が元のリモコンと同じものなのか、確認する手段がありません。このまま手探りのテストははっきり言って現実的ではありません。ここまでそれに気付かなかった私って。。。
どうしようもないのでもう一つ Arduino を買って、前回のエントリと同じ受信モジュールを組んでしまいました。

完成


シリアルモニタから 'C' を入力したらエアコンがぴぴっと動き出す!
エアコン斜め横に配置。奥側はつけっぱだった温度センサー

3 件のコメント:

  1. Thank you so much for your tutorial !!
    Would you please also upload the sender source code for this tutorial?

    返信削除
    返信
    1. Here is sender code.
      https://gist.github.com/taqpan/e84bcc72ef9b81ddb6fc
      Thanks.

      削除
    2. Thanks again!!

      I tried to received signal with IRRemote library and your code.
      Your code is definitely faster and generated more precise result.

      In the case of emitting IR signal,
      IRRemote acts strange and I can not figure it out. The reason is I lack a working example.
      Thanks for your share. I will try it with your code and make another reply later.

      削除