他の方のサイトでも、赤外線LEDを買ってきてArduinoで便利なリモコンを作る、ということをやっているので、私も真似したく、赤外線LEDを買ってきた。
10個も入っていて100円である。
受信機はこの前800円で買ったリモコンと受信モジュールのセットがあるから、これでよい。
この赤外線LEDは50mA流す規格なので、20mAしか流せないArduinoで光らせるには少し大き過ぎる。1kΩばかり抵抗をつけて5mAくらいにする。暗くてリモコンが反応しないのじゃないかな、とも思ったが、受光部に近づければ大丈夫だ。しかし、デジカメで観察するとかなり暗い。もし、ちゃんとしたものを組み立てるのなら、FETなどでリレーして、他の電源から50mA流したほうがいいだろう。
今回は遊びなので、5mAで光らせる。
先達のサイトでは、スクラッチビルドのコードで市販のリモコンの信号を受信し、ミリ秒単位でオンオフ時間を計測して記録し、その通りに赤外線LEDを光らせてうまく行っている方が多いようだ。
一方、Arduinoには、「IRremote」というライブラリをGitHubで公開しておられる方がいるので、これを使えば簡単である。
GitHubのページからzip玉をもらって解凍し、できたディレクトリ(IRremote)をArduinoのインストールディレクトリの「libraries」の下にコピーすればよい。
今日は私の家のリビングの扇風機のリモコンで試してみよう。
リビングの扇風機のリモコン信号をコピーしてテストするには、ライブラリをインストールするとできるサンプルスケッチのうち、「IRrecord」というのを使う。コマンドメニューは「ファイル→スケッチの例→IRremote→IRrecord」と辿る。
これは、「1回こっきりの学習リモコン」のスケッチだと思えばよい。市販のリモコンを受信して記憶し、次いでボタンを押すとそのままそっくり信号のコピーを赤外線LEDから送出するスケッチだ。
赤外線LEDは1kΩの抵抗と直列にしてデジタル3番ピンに、受信機は11番ピンに、タクトボタンを12番ピンにつなぐ。タクトボタンの入力側は10kΩの抵抗できちんとプルダウンしておくのが行儀がいい。そうしないと、手を触れたくらいのことでスイッチが入ってしまう。
ブレッドボードが出来たら、使いたいリモコンを受信機に近づけ、ボタンを押す。
それから今度は、ブレッドボード上の赤外線LEDを電気製品に近づけ、タクトボタンを押す。
そっくりコピーされた信号が送出され、扇風機が動く。
これで、ハードウェアは正しく動くことが分かったので、今度は単純にデータをハードコーディングで配列に書き出し、これを送出して扇風機のスイッチをオンオフさせる。
まず、データを記録する。それにはサンプルスケッチの「IRrecvDumpV2」を使う。今度は受信機を6番ピンにつなぎ換え、シリアルモニタを起動してデータを観測する。そうすると、そのまま使える形の配列の初期化定義の格好でダンプが出てくる。
これをクリップボードにコピーして、今度はサンプルスケッチの「IRSendDemo」にペーストし、送出してやればよい。
ところが、ここでハマッた、ハマッた。そのままではうまくいかないのである。
はじめ、私の扇風機では、「IRrecvDumpV2」のダンプはこうなった。
Encoding : UNKNOWN
Code : 1FB3782D (32 bits)
Timing[68]:
-22598
+4500, -2150 + 650, - 500 + 600, - 500 + 500, - 600
+ 550, - 550 + 650, -1600 + 600, -1600 + 550, -1700
+ 600, - 500 + 550, -1700 + 600, -1600 + 600, -1650
+ 550, - 550 + 600, -1600 + 600, - 500 + 650, - 500
+ 600, - 500 + 600, -1600 + 650, - 500 + 600, - 500
+ 600, - 500 + 600, - 500 + 600, - 500 + 650, -1600
+ 600, - 500 + 600, - 500 + 550, - 600 + 600, -1600
+ 600, -1600 + 550, -1700 + 600, -1600 + 650, - 500
+ 500, - 600 + 550,
unsigned int rawData[69] = {9627, 90,43, 13,10, 12,10, 10,12, 11,11, 13,32, 12,32, 11,34, 12,10, 11,34, 12,32, 12,33, 11,11, 12,32, 12,10, 13,10, 12,10, 12,32, 13,10, 12,10, 12,10, 12,10, 12,10, 13,32, 12,10, 12,10, 11,12, 12,32, 12,32, 11,34, 12,32, 13,10, 10,12, 11,0}; // UNKNOWN 1FB3782D
そこで私は、この「rawData[69]」をコピペし、次のようにした。
#include <IRremote.h>
IRsend irsend;
void setup()
{
Serial.begin(9600);
}
void loop() {
static unsigned int rawData[] = {9627, 90,43, 13,10, 12,10, 10,12, 11,11, 13,32, 12,32, 11,34, 12,10, 11,34, 12,32, 12,33, 11,11, 12,32, 12,10, 13,10, 12,10, 12,32, 13,10, 12,10, 12,10, 12,10, 12,10, 13,32, 12,10, 12,10, 11,12, 12,32, 12,32, 11,34, 12,32, 13,10, 10,12, 11,0}; // UNKNOWN 1FB3782D
if (Serial.read() != -1) {
for (int i = 0; i < 3; i++) {
irsend.sendRaw(rawData,sizeof(rawData) / sizeof(rawData[0]), 38); // Sony TV power code
delay(40);
}
}
}
ところが、これではまったくダメなのである。
最初は赤外線LEDの電流が足りないのかなあ、などと思い、半日ほどあっちこっちをいじくりまわして、ダメだった。
「IRrecord」での丸ごと信号コピーはうまく行っているのだから、電流が足りないわけではないらしい。
そこで、「IRrecord」のダンプ部分にコードを書き足し、「sendRaw()」関数にどんな値を渡しているかを見てみた。
else if (codeType == UNKNOWN /* i.e. raw */) {
// Assume 38 KHz
irsend.sendRaw(rawCodes, codeLen, 38);
Serial.println("Sent raw");
Serial.println(codeLen);
for(int cnt = 0; cnt <= codeLen; cnt++){
Serial.print(rawCodes[cnt]);
Serial.print(",");
}
Serial.println("\n");
}
そうしたら、どうも、ダンプされた値の50倍が渡されているらしい。
4400,2250,550,600,500,600,500,600,500,600,550,1700,500,1700,500,1750,500,600,400,1800,550,1700,500,1650,550,600,550,1700,500,600,500,600,550,600,500,1700,550,550,450,650,550,600,500,600,500,600,450,1800,550,550,550,550,550,600,500,1700,550,1650,550,1700,500,1700,650,500,500,600,500,0,
そこで、「IRrecvDumpV2」のダンプ出力部分を次のようにカスタマイズした。
// Dump data
for (int i = 0; i < results->rawlen; i++) {
// Serial.print(results->rawbuf[i], DEC);
Serial.print(results->rawbuf[i] * 50, DEC);
Serial.print(",");
if (!(i&1)) Serial.print(" ");
}
そうすると、ダンプは……
ncoding : UNKNOWN
Code : FBB100E8 (32 bits)
Timing[68]:
-24324
+4550, -2150 + 650, - 450 + 650, - 450 + 650, - 500
+ 650, - 450 + 650, -1550 + 650, -1600 + 650, -1550
+ 650, - 450 + 650, -1600 + 650, -1550 + 700, -1550
+ 650, - 450 + 650, -1550 + 650, - 500 + 650, - 450
+ 650, - 450 + 650, -1600 + 600, - 500 + 650, - 450
+ 650, - 500 + 600, - 450 + 700, - 450 + 650, -1550
+ 650, - 500 + 650, - 450 + 650, - 450 + 650, -1600
+ 600, -1600 + 650, -1550 + 650, -1600 + 650, - 450
+ 650, - 450 + 650,
unsigned int rawData[69] = {24324, 4550,2150, 650,450, 650,450, 650,500, 650,450, 650,1550, 650,1600, 650,1550, 650,450, 650,1600, 650,1550, 700,1550, 650,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,500, 650,450, 650,500, 600,450, 700,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,1600, 650,1550, 650,1600, 650,450, 650,450, 650,0}; // UNKNOWN FBB100E8
……となる。
で、この先頭の「24324」は送信前の空き時間なので、捨ててよいようだ。「IRsendDemo」のほうにこれをコピペし、先頭の24324は消す。
#include <IRremote.h>
IRsend irsend;
void setup()
{
Serial.begin(9600);
}
void loop() {
static unsigned int rawData[] = {4550,2150, 650,450, 650,450, 650,500, 650,450, 650,1550, 650,1600, 650,1550, 650,450, 650,1600, 650,1550, 700,1550, 650,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,500, 650,450, 650,500, 600,450, 700,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,1600, 650,1550, 650,1600, 650,450, 650,450, 650,0}; // UNKNOWN 1FB3782D
if (Serial.read() != -1) {
for (int i = 0; i < 3; i++) {
irsend.sendRaw(rawData,sizeof(rawData) / sizeof(rawData[0]), 38); // Sony TV power code
delay(40);
}
}
}
これで、赤外線LEDを扇風機に近づけ、シリアルモニタの「送信」ボタンをクリックすると、扇風機がオン・オフされる。
ブレッドボードは結局、最後はこんな感じ。