赤外線リモコン受信モジュール (110円) をRaspberry Piに取り付けて、赤外線パターンを取得・復号できるようにしました。天井照明リモコンの点滅パターンをこれで取得して、ESP32に組み込んで、HomeKitから点灯・消灯できました。
これまでのあらすじ
前回、HomeKitからパナソニックのエアコンをコントロールするスマート赤外線リモコンが完成しました。
エアコンをコントロールするスマートリモコンとして、Nature Remoを使っていたのですが、これをDIYしたことでほぼ使わなくなってしまいました。唯一使用している機能が、赤外線リモコンの生データをローカルAPIで取得する機能です。
Nature Remoにリモコンを向けてボタンを押すと、Nature Remoがパターンを取得してくれます。そのパターンはhttpアクセスで知ることができます。パターン取得機能のためだけにNature Remoを使うのは勿体無いので、今回はこれをDIYします。赤外線リモコン受信モジュールをRaspberry Piに取り付けて、赤外線パターンを取得することにしました。
赤外線リモコン受信モジュール
使用した赤外線リモコン受信モジュールは、秋月電子で110円で売られているPL-IRM0101-3という製品です。
これ1個を、3本のワイヤでRaspberry Piに取り付けるだけで、赤外線パターンが得られます。この部品のことは、赤外線リモコン自作ページでよく見かけていたので、以前から知ってました。発売日が2004年だそうですので、18年も続くロングセラーです。秋月電子のサイトには、他にも半額くらいで類似の製品がいくつかありますので、そちらでも良かったかもしれません。
サイトには電源が5Vと書いてありましたが、リンクされていたデータシートによると3Vにも対応しているようです。ただ古いロットの製品(Rev B/1)は5V限定だったようです。Raspberry PiのGPIOは3Vなので、現行のRev B/2が必要です。
Raspberry Piに取り付ける
PL-IRM0101-3のピンは3本で、左から、(1)信号、(2)GND、(3)Vccです。
これらの1, 2, 3番ピンをRaspberry PiのGPIOの 7, 9, 1番ピンに接続しました。
温度湿度センサの時と同様に、フラットケーブルになったジャンパ線を割いて使用しました。
そして受信モジュールを、Raspberry Piケースにテープで止めしました。
生データ取得プログラム
GPIOピンの7番はGPIO 4です。データシートによると、受信モジュールは通常は1で、赤外線信号があると0になるようです。下図の上段がモジュールが受け取る赤外線強度、下段がモジュールの出力です。
GPIOをreadしたところ、やはり通常は1で、赤外線が照射されると0になりました。そこで、
- GPIOが10秒間1のままならば終了する
- GPIOが1ms以上0になったら以下の測定を開始する
- GPIOが変化するたびにその間隔をマイクロ秒単位で記録する
- GPIOが20ms以上変化しなくなるまで3を繰り返す
- 結果を表示する
というプログラムを、Raspberry Pi上のPython3で作成しました。以下です。
#!/usr/bin/python3 import RPi.GPIO as GPIO import time import sys PIN=4 GPIO.setmode(GPIO.BCM) GPIO.setup(PIN,GPIO.IN) raw=[] print("Waiting for IR signal (for 10sec)...") time_now=time.time() time_start=time_now while (time_now - time_start) < 10 : time_now=time.time() if GPIO.input(PIN)==0: time.sleep(0.001) #1ms delay if GPIO.input(PIN)==0: #still 0 break if (time_now - time_start) >= 10 : print("Time out.") sys.exit() time_start=time_now gpio_last=0 while (time_now - time_start) < 0.02 : time_now=time.time() gpio_now=GPIO.input(PIN) if(gpio_last != gpio_now): raw.append(round((time_now - time_start)*1000000)) time_start=time_now gpio_last=gpio_now print(raw)
天井照明リモコンパターンを取得する
簡単な例として、毎回登場している天井照明のリモコンを試します。これのon/offボタンのパターンを取得してみます。上記のプログラムを動かすと(irreceive.pyという名前をつけました)、
$ ./irreceive.py Waiting for IR signal (for 10sec)... [6929, 4539, 371, 1316, 369, 494, 342, 1345, 344, 514, 368, 1319, 369, 492, 345, 1342, 345, 518, 367, 490, 366, 1324, 371, 485, 371, 490, 370, 1318, 345, 1343, 371, 1314, 372, 1323, 345]
という結果が得られました。グラフにすると以下のようです。横軸が時間で縦軸が赤外線出力です。開始のパルスは長めですし、0, 1に相当するパルス幅も広く、一般的なフォーマットとは少し違う特殊なリモコンのようです。
ESP32で作るDIYスマートリモコンに組み込む
ESP32で、エアコン用のスマートリモコンを作りましたが、
今ここで得られた生データを送出する機能を、このESP32に追加して、天井照明もコントロールするように設定します。
エアコンのリモコンとして動作していたプログラムに、この天井照明のパターンを送出する部分を以下のように追加しました。赤外線点滅の生データを送出するためには、IRsendクラスのインスタンス(下記プログラムではirsend)を作って、これのsendRawというメソッドを使えば良いようです。このメソッドでon/offの生データを以下のように送ります。
#include <Arduino.h> #include <ArduinoOTA.h> //IR Remote #include <IRremoteESP8266.h> const uint16_t kIrLed = 4; //GPIO for IR LED. Recommended: 4. const char SUBTOPIC[] = "mqttthing/irOffice/set/#"; (略) IRsend irsend(kIrLed); //for sending raw IR data //ceiling light on/off pattern const uint16_t kCeilingOnOff[35]= { 6929, 4539, 371, 1316, 369, 494, 342, 1345, 344, 514, 368, 1319, 369, 492, 345, 1342, 345, 518, 367, 490, 366, 1324, 371, 485, 371, 490, 370, 1318, 345, 1343, 371, 1314, 372, 1323, 345 }; void setup() { (略) } //MQTT: subtopic call back void onMessageReceived(const String& topic, const String& message) { String command = topic.substring(topic.lastIndexOf("/") + 1); if (command.equals("Active")) { (略) }else if(command.equals("CeilingOnOff")){ if(message.equalsIgnoreCase("true")) irsend.sendRaw(kCeilingOnOff, 35, 38); } } //MQTT: connection callback void onConnectionEstablished() { ArduinoOTA.setHostname("irOffice"); ArduinoOTA.setPasswordHash("xxxxxxxxxxxxxxx"); ArduinoOTA.begin(); client->subscribe(SUBTOPIC, onMessageReceived); //set callback function } (略) void loop() { ArduinoOTA.handle(); client->loop(); }
これで、mqttthing/irOffice/set/CeilingOnOffにtrueというメッセージが送られると、この生データを送出します。
一方、HomebridgeのMqttthingの設定部分には、以下のように追記して、このMQTTメッセージに対応するスイッチを作成しました。
{ "type": "switch", "name": "Ceiling Toggle", "topics": { "setOn": "mqttthing/irOffice/set/CeilingOnOff" }, "turnOffAfterms": 300, "accessory": "mqttthing" }
この結果、iPhone, Macのホーム.appに、以下のように赤外線信号を送出するスイッチが追加されました。turnOffAfterms (turn off after ms) を300msに設定したので、通常はoffの状態で、
クリックすると0.3秒だけonの状態になり、またoffに戻ります。
これをクリックするたびに、上記の赤外線パターンが送出され、天井照明はon/off状態を交互に繰り返します。
デコード機能
前後しますが、上述のPythonプログラムに、赤外線パターンのデコード機能を追加しました。上記のプログラムの末尾に、以下を追加します。
T=400.0 isOn=False evaluateNext=False count=0 aByte=0 for x in raw: isOn = not isOn width=round(x/T) if(width > 3) and (isOn == False): count=0 aByte=0 print() if(width == 1) and (isOn == True): evaluateNext=True elif(evaluateNext): evaluateNext=False if(width == 1): aByte = aByte >> 1 count += 1 elif(width == 3): aByte = (aByte >> 1) + 0x80 count += 1 if(count >= 8): print(format(aByte,'02X'),end='') aByte=0 count=0 print()
かなり手抜きです。Tで、短いパルス幅を指定しておきます。T幅の赤外線Onパルスが見つかったら、その次のOff幅を測定して、Tならば0、3Tならば1としています。また、それぞれのバイトのLSBから順番に送信されていると仮定してます。NECと家製協のフォーマットがこの方式なので、汎用性は高いです。
例えば、上記の天井照明リモコン (これは独自フォーマットですが0, 1 がほぼ1T, 3Tです) ならば、
$ ./irreceive.py 55F2
となります(生データのprint文はコメントアウトしました)。エアコン用スマートリモコンで使用したパナソニックのエアコンならば、
$ ./irreceive.py 0220E00400000006 0220E00400412C80AF0000066000008000068E
と表示されます。 (これは22度暖房のパターンです)
まとめ
秋月電子などで一般的に売られている赤外線リモコン受信モジュールを、Raspberry Piに取り付けて、赤外線を取得しデコードもできるようにしました。これを用いて、天井照明のリモコンのon/offパターンを測定し、ESP32から送出するようにして、HomeKitから使えるようにしました。この手順で、HomeKit対応スマート学習リモコンをDIYできます。
コメント