Arduinoでリモコン


以前書いたように、PC-OP-RS1は簡単に使えて楽なのですが動かない機器も存在します。そこで、少し動作をいじれるものを作ってみることにします。

ここではArduinoにIrの受光モジュールとLEDをつないで、学習リモコンを作ってみました。まずはPC-OP-RS1互換の動作にして、同じソフトで扱えるように作ってみます。互換と言っても自作のlemon_cornで大体同じように動く、というだけでPC-OP-RS1付属のWindowsアプリがそのまま動くというわけではありませんので誤解なきよう。

使った部品は

  • Arduino UNO (R2)
  • ブレッドボード

以上はスイッチサイエンスのはじめようキットとして購入

以上は秋月の店頭で適当に拾って買ったものです。

接続はこんなんで、入力は8pin,出力は12pinを使っています。
一応宣言しておきますが、電子回路は詳しくないので適当に調べて組んだだけです。そのあたりよろしくお願いします。

  • LEDの直列抵抗は計算値で36Ωですが、もっと小さくするとかなり飛ぶようになります。でもLEDが壊れるかもしれません。(笑)

→2013.12.23訂正:電流100mAで計算してましたが、これは最大電流でした。半分の50mAとして計算すると73Ωなので、70〜100Ω程度が良さそうです。
あと意味のないプルアップ/プルダウン回路削除しました。

  • トランジスタも直列抵抗も省略して、信号線(12pin)で直接LEDをドライブしてもとりあえずは動きます。

Arduinoのソフトは、スケッチをgithubに置いておきました。
(4/15 追記:センサーなんかを統合したlemon_squashの方で発展させて行く予定です)
ステートマシンはかなり省略したので、キャンセルコマンドとかは実装していません。
とくに気をつけないといけないのは38kHzの変調信号を作る所です。正確に38kHz、duty=1/3の信号を作ろうとするとHIGH=8.77us, LOW=17.54usのパターンを繰り返す必要がありますが、μs単位でしか制御できないので正確な38kHzは出せません。ここではHIGH=9us, LOW=17usで約38.5kHzの変調信号を生成します。
またdigitalWrite()は意外と重い処理で数usかかってしまうみたいなので、レジスタを直接扱うPORT操作の方を使用した方が良さそうです。

#define PIN_IR_OUT	12

#define HI_DUR_US	9
#define LO_DUR_US	17

uint8_t d0 = PORTB;
uint8_t d1 = d0 | (val << (PIN_IR_OUT - 8));

end_us += 100;	// repeat below for 100us
for (; cur_us < end_us; cur_us += HI_DUR_US + LO_DUR_US) {
	PORTB = d1;
	delayMicroseconds(HI_DUR_US);
	PORTB = d0;
	delayMicroseconds(LO_DUR_US);
}

またPC-OP-RS1との動作上の違いとしては、シリアルデバイスをオープンしてからデータを送信できるようになるまで2秒ほど待たなくてはならないという点があります。lemon_cornの方も-arduinoオプションでこれに合わせていますが、リモコンとして使うにはこれはきつい。気持ち良く使うには、デーモン化する必要がありそうです。そのうちやります。

(2012/4/3 追記


Arduinoのシリアルデバイスは/dev/ttyACM0なので、必要に応じてudevのruleに追加して

KERNEL=="ttyUSB[0-9]", MODE="0666"
KERNEL=="ttyACM[0-9]", MODE="0666"

あとはこんな感じで動きます。

% lemon_corn -arduino -r tv_pwr (受信)
% lemon_corn -arduino tv_pwr (送信)

ここまでだとPC-OP-RS1と同じ機能なので、別にありがたくもありません。(変調周波数をいじれたりはしますが)
これをベースに、もっと長い信号も記録できるように改良していこうと思います。