M5Stack Atomシリーズを使って赤外線リモコン信号を送信する方法について解説します。
Atomに内蔵されている赤外線信号送信用のLED
Atom MatrixとAtom Liteには赤外線信号送信用のLEDが搭載されています。USB Tpye-Cソケットと反対側の側面にラベルが貼られていて、その横に小さな穴があります。穴の奥にLEDが配置されています。信号を送信するときは、この穴を制御する機器に向けてください。
赤外線送信のサンプルプログラムを解読してみる
M5Stack Atomで赤外線リモコンを作る(2)受信編で紹介したIRremoteESP8266ライブラリを使って赤外線信号を送信します。
Arduino IDEにIRremoteESP8266ライブラリをインストールすると、サンプルプログラムも一緒にインストールされます。その中にIRsendDemoというプログラムがあります。これを見ると、送信方法の概略がわかります。
35行目は赤外線送信用LEDのGPIOのピン番号です。Atom MatrixとAtom Liteでのピン番号を裏側ラベルで調べてみると、12であることがわかります。Atomでこのプログラムを動かすには4を12に変更する必要があります。
37行目は送信を司るIRsend型のオブジェクトを作成しています。引数として35行目で定義したピン番号を渡しています。
40〜46行目はIRrecvDumpV2を使って解析した赤外線信号の生データです。IRrecvDumpV2がシリアルモニターにrawData[ ]配列を出力するので、送信プログラムのこの部分にコピペして使います。
setup()内にある53行目はirsendオブジェクトのbegin()を呼び出して起動しています。
62〜63行目は赤外線信号をNECプロトコルで送信する例です。irsend.sendNEC()を使い、引数にはuint64_t型のデータを渡します(注:実際に送信されるのは下位32bitだけです)。このデータはIRrecvDumpV2の出力結果からコピペできます。例えば、このような出力だった場合、
Protocol行を見るとプロトコルがNECだとわかり、data = の行を見るとsendNEC()に渡す引数が0x419F58A7であることがわかります。プログラムの63行目の例ではsendNEC()に引数として数値リテラルを直接渡しているので、ビット長を合わせる為に最後に「UL」が付け足されています。
プロトコルがSONYである場合は、66行目のようにsendSONY()を使います。引数は3つ必要です。HITACHやTOSHIBAといった代表的プロトコルにはそれ専用の関数が用意されています。引数の数や内容はそれぞれ異なるのでIRremoteESP8266のソースコードをGITHUBで見て引数として何が必要かを判断する必要があります。
68〜69行目はrawData[]を送る例です。sendRaw()という関数が使われています。この関数の引数は、
- 第1引数:rawData配列へのポインタ
- 第2引数:rawData配列の要素数
- 第3引数:赤外線LEDのOn/Offの周波数(khz)
です。67行目の例では irsend.sendRaw(rawData, 67, 38)となっていますが、67は40行目の配列要素数を指定します。38は通常いつもこの値を使います。赤外線リモコンの仕様が38khzになっているためです。
Atom用の赤外線送信プログラムを作ってみる
IRremoteESP8266の例題を改造して、Atom用の赤外線送信プログラムを作ってみます。送信する信号は、私が持っているオーディのリモコン信号をIRrecvDumpV2で受信したデータを使います。IRrecvDumpV2の出力結果はこちらです。
プログラムの主な改造ポイントは次の通りです。
- Atom用のヘッダーファイルを読み込む。
- 赤外線LEDのピン番号を12に変更する。
- IRrecvDumpV2の出力結果から、rawData[ ]とdataの行をコピペする。
- setup()内でAtomを初期化する。
- ボタンが押されたときに、sendRaw()かsendNEC()のどちらかを呼び出す。
改造後のプログラムはこうなります。
#include <M5Atom.h> #include <IRremoteESP8266.h> #include <IRsend.h> const uint16_t kIrLed = 12; // M5Atom IR LED GPIO pin IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. // Example of data captured by IRrecvDumpV2.ino uint16_t rawData[67] = {9030, 4480, 588, 536, 584, 1628, 612, 536, 586, 536, 586, 538, 562, 564, 560, 562, 560, 1652, 610, 1652, 564, 560, 584, 540, 564, 1672, 584, 1652, 586, 1626, 610, 1628, 610, 1632, 606, 538, 562, 1654, 586, 560, 562, 1674, 586, 1652, 586, 538, 560, 562, 586, 538, 562, 1676, 586, 538, 566, 1672, 584, 540, 584, 538, 586, 1628, 610, 1626, 612, 1642, 588}; // NEC 419F58A7 uint64_t data = 0x419F58A7; void setup() { M5.begin(true, false, false); irsend.begin(); } void loop() { M5.update(); if (M5.Btn.wasReleased()) { Serial.println("Button pressed"); Serial.println("sendRaw"); irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. // Serial.println("sendNEC()"); // irsend.sendNEC(data); } }
このプログラムではsendRaw()を呼び出すようになっています。sendNEC()を試したいときは、32,33行目をコメントアウトし、35,36行目の//を外してください。
IRrecvDumpV2を使って自分で受信した信号を送信する場合は、下記の変更が必要です。
- 10〜20行目を自分のデータに入れ替える。
- 33行目の67をrawData[]の要素数に変更する。
- プロトコルに対応したsendXXXX()に置き換える。
Atomの赤外線LEDは光が弱い
プログラムを実行してみるとわかるのですが、制御対象の機器とAtomとの距離が1mを超えると信号が届かなくなります。これは赤外線LEDの光が弱いためです。実用性を考えるとかなり厳しいと言わざるを得ません。
赤外線信号の受信に使ったM5Stack用赤外線送受ユニットに搭載されている赤外線LEDを使うと、もう少し遠くまで信号が飛びます。送受信ユニットから信号を送る場合は、送信プログラム内にあるLEDのピン番号を26に変更するだけで送信できます。
エアコンの制御はできるか?
ここまでの例は、リモコンで送信した信号をキャプチャーしてそのまま真似るというものでした。TVのOn/Offやチャンネル変更といった単純なリモコン信号はこのやり方で大丈夫です。しかしエアコンは、冷暖房切り替え、温度、風速、風向などパラメータが多く、キャプチャーして真似るのが困難です。
IRremoteESP8266には、有名メーカーのエアコンを制御するための関数が用意されています。
サンプルプログラムとして用意されているTurnOnDaikinACを見てみましょう。
プログラムの概要はこうなっています。
- 33行目で、ダイキンエアコン制御用のオブジェクトを「ac」という名前で作成しています。
- 36行目で、ac.begin()を呼び出して起動しています。
- 45〜56行目で温度、スイング、現在時刻などのパラメータをacに設定しています。
- 62行目で、設定した値をリモコン信号として送信しています。
どのメーカーに対応しているかとか、どんなパラメータがあるかとかを説明したドキュメントはないので、githubに置いてあるソースコードを読んで理解するしかありません。