現時点の情報です。最新情報はM5StickC非公式日本語リファレンスを確認してみてください。
概要
前回はジョイスティックでした。今回は赤外線受信センサーです。
赤外線受信センサーとは?
秋月さんだと上記になります。主に赤外線リモコンの受信用センサーになります。キットに入っているのはモジュールになっていて、信号を受信するとLEDが光るのでわかりやすくなっています。
気をつける必要があるのが、赤外線には波長があり一般的に使われているのが940nm前後になります。センサーによって940nmだったり945nmあたりが一番感度が良くなっていますがこれぐらいの差であればそれほど気にしなくてもよいと思いますが、なるべく同じ波長のものをペアにして使ったほうがいいと思います。
また、商品ページに中心周波数が書いてありますが、基本的には38kHz前後を赤外線リモコンで使うことが多いみたいです。
赤外線のフォーマットについて
- 赤外線リモコンのフォーマット 電子工作の森
- 赤外線リモコンの通信フォーマット ChaN
上記などのサイトが詳しいです。
上記などで細かい内部関数を使って受信をためしましたが、通常はライブラリを使いますので細かいことは知らなくても大丈夫です。
接続方法

ちょっとわかりにくいのですが、キットの赤外線受信センサーは以下の表の役割になっています。接続するGPIOはどこでも問題ないはずです。
赤外線受信センサー | M5StickC |
G(GND) | GND |
R(VCC) | 3V3 |
Y(Signal) | GPIO26 |
ライブラリ準備

ライブラリマネージャーより「IRremoteESP8266」をあらかじめいれておきます。このライブラリの元になっている「IRremote」が有名ですが、ESP32の場合には「IRremoteESP8266」を使ったほうが楽です。
スケッチ例を開く(IRrecvDumpV3)
#include "BaseOTA.h" #include <Arduino.h> #include <IRrecv.h> #include <IRremoteESP8266.h> #include <IRac.h> #include <IRtext.h> #include <IRutils.h> const uint16_t kRecvPin = 26; const uint32_t kBaudRate = 115200; const uint16_t kCaptureBufferSize = 1024; #if DECODE_AC const uint8_t kTimeout = 50; #else // DECODE_AC const uint8_t kTimeout = 15; #endif // DECODE_AC const uint16_t kMinUnknownSize = 12; #define LEGACY_TIMING_INFO false IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true); decode_results results; // Somewhere to store the results void setup() { OTAwifi(); // start default wifi (previously saved on the ESP) for OTA #if defined(ESP8266) Serial.begin(kBaudRate, SERIAL_8N1, SERIAL_TX_ONLY); #else // ESP8266 Serial.begin(kBaudRate, SERIAL_8N1); #endif // ESP8266 while (!Serial) // Wait for the serial connection to be establised. delay(50); Serial.printf("\n" D_STR_IRRECVDUMP_STARTUP "\n", kRecvPin); OTAinit(); // setup OTA handlers and show IP #if DECODE_HASH irrecv.setUnknownThreshold(kMinUnknownSize); #endif // DECODE_HASH irrecv.enableIRIn(); // Start the receiver } void loop() { if (irrecv.decode(&results)) { uint32_t now = millis(); Serial.printf(D_STR_TIMESTAMP " : %06u.%03u\n", now / 1000, now % 1000); if (results.overflow) Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize); Serial.println(D_STR_LIBRARY " : v" _IRREMOTEESP8266_VERSION_ "\n"); Serial.print(resultToHumanReadableBasic(&results)); String description = IRAcUtils::resultAcToString(&results); if (description.length()) Serial.println(D_STR_MESGDESC ": " + description); yield(); // Feed the WDT as the text output can take a while to print. #if LEGACY_TIMING_INFO Serial.println(resultToTimingInfo(&results)); yield(); // Feed the WDT (again) #endif // LEGACY_TIMING_INFO Serial.println(resultToSourceCode(&results)); Serial.println(); // Blank line between entries yield(); // Feed the WDT (again) } OTAloopHandler(); }
コメント行を消していますが、編集すべき場所は使うGPIOの行のみになります。この状態で付属の赤外線リモコンを操作するとシリアル出力にリモコンのコードが表示されます。
Protocol : NEC Code : 0xFF6897 (32 Bits) uint16_t rawData[67] = {9434, 4488, 642, 540, 582, 568, 612, 540, 612, 540, 582, 568, 610, 540, 584, 568, 584, 568, 610, 1618, 640, 1620, 614, 1644, 642, 1614, 646, 1616, 612, 1644, 616, 1644, 616, 1642, 616, 566, 612, 1620, 642, 1616, 644, 538, 586, 1644, 612, 568, 588, 564, 594, 560, 608, 1622, 620, 562, 588, 564, 606, 1626, 614, 566, 590, 1642, 638, 1620, 612, 1644, 638}; // NEC FF6897 uint32_t address = 0x0; uint32_t command = 0x16; uint64_t data = 0xFF6897;
上記が付属リモコンの0ボタンを押したときの情報になります。実際に送信しているデータはrawDataの値であり、それをデータ化するとProtocolとCodeがわかります。このCodeをさらにデコードすると、addressとcommandがわかります。
Protocol : NEC Code : 0xFF30CF (32 Bits) uint16_t rawData[67] = {9268, 4456, 596, 572, 614, 538, 648, 498, 568, 572, 596, 544, 572, 570, 574, 568, 572, 570, 598, 1620, 604, 1672, 574, 1646, 602, 1648, 600, 1646, 602, 1648, 600, 1648, 600, 1646, 600, 570, 596, 546, 574, 1648, 600, 1650, 600, 570, 574, 568, 574, 570, 572, 572, 574, 1646, 602, 1650, 600, 570, 574, 570, 574, 1648, 626, 1624, 600, 1648, 602, 1652, 622}; // NEC FF30CF uint32_t address = 0x0; uint32_t command = 0xC; uint64_t data = 0xFF30CF;
ちなみに、こちらが1のボタンを押したときのデータになります。addressは受信側と送信側で同じものを処理するので、リモコンなどによって固定です。commandの値を変更することでどのボタンかを見分けています。
Protocol : NEC (Repeat) Code : 0xFFFFFFFFFFFFFFFF (0 Bits) uint16_t rawData[3] = {9236, 2204, 626}; // NEC (Repeat) FFFFFFFFFFFFFFFF uint64_t data = 0xFFFFFFFFFFFFFFFF;
あと特徴的なのがリピートです。同じボタンを押し続けると、このリピートが飛んできます。ボリューム変更などはリピートを受け付けたりしますが、一般的な処理では無視しても問題ありません。
Protocol : UNKNOWN Code : 0x531F42F9 (8 Bits) uint16_t rawData[15] = {242, 2692, 350, 1280, 370, 45816, 1916, 1060, 508, 324, 386, 286, 554, 1462, 2832}; // UNKNOWN 531F42F9
また、上記のようなデータも受信する場合もあります。赤外線はいろいろなところに飛んでいるので、無意味なデータをたまたま受信してしまうこともあります。
Protocol : SONY Code : 0x10 (12 Bits) uint16_t rawData[103] = {2382, 594, 596, 592, 596, 592, 596, 592, 596, 592, 596, 592, 598, 592, 596, 594, 1190, 592, 598, 592, 596, 594, 596, 592, 596, 27370, 2380, 594, 596, 594, 594, 594, 596, 592, 596, 592, 596, 592, 596, 592, 598, 592, 1194, 590, 596, 592, 596, 592, 596, 594, 596, 27380, 2380, 594, 596, 592, 594, 594, 596, 592, 596, 592, 596, 592, 596, 592, 596, 592, 1192, 592, 596, 592, 596, 596, 594, 592, 598, 27392, 2382, 592, 596, 592, 598, 592, 596, 592, 596, 592, 596, 594, 596, 592, 596, 594, 1190, 592, 596, 592, 596, 594, 596, 594, 596}; // SONY 10 uint32_t address = 0x1; uint32_t command = 0x0; uint64_t data = 0x10;
上記はソニーのテレビで1ボタンを押した場合のデータです。NECプロトコルが一般的なのですが、ソニーは独自プロトコルを採用しています。
Protocol : PANASONIC_AC Code : 0x0220E004000000060220E00400312E80AF00000660000080001690 (216 Bits) Mesg Desc.: Model: 4 (JKE), Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off uint16_t rawData[439] = {3500, 1754, 438, 410, 464, 1314, 436, 414, 462, 420, 462, 414, 462, 414, 462, 414, 462, 420, 462, 414, 464, 414, 462, 416, 464, 418, 462, 412, 462, 1314, 436, 414, 462, 420, 462, 414, 464, 414, 464, 414, 464, 418, 462, 414, 462, 1312, 436, 1312, 436, 1318, 436, 414, 464, 412, 462, 1314, 436, 420, 462, 414, 464, 414, 464, 414, 462, 422, 462, 414, 462, 414, 462, 414, 464, 418, 462, 416, 462, 414, 462, 414, 464, 418, 462, 416, 462, 414, 462, 414, 462, 420, 464, 414, 462, 414, 464, 414, 464, 418, 462, 414, 464, 414, 462, 416, 462, 420, 464, 412, 464, 414, 462, 414, 462, 420, 462, 412, 462, 1314, 434, 1314, 436, 418, 462, 414, 464, 414, 462, 416, 462, 412, 464, 9990, 3506, 1748, 438, 412, 462, 1314, 436, 414, 462, 420, 462, 414, 462, 414, 464, 414, 464, 418, 462, 416, 462, 414, 464, 414, 464, 418, 462, 412, 464, 1314, 436, 414, 464, 420, 462, 414, 464, 412, 464, 414, 462, 420, 462, 412, 464, 1312, 436, 1312, 436, 1318, 434, 414, 462, 412, 462, 1314, 436, 420, 462, 414, 464, 414, 462, 414, 464, 418, 462, 414, 464, 414, 464, 414, 464, 418, 462, 414, 462, 414, 464, 414, 464, 416, 464, 1314, 434, 414, 468, 408, 464, 416, 462, 1312, 436, 1314, 436, 414, 464, 420, 462, 412, 462, 1314, 436, 1312, 436, 1318, 436, 410, 464, 1314, 436, 414, 462, 420, 462, 414, 462, 414, 462, 414, 462, 420, 462, 414, 462, 414, 462, 412, 462, 1326, 432, 1312, 436, 1310, 436, 1312, 436, 1316, 438, 410, 464, 1314, 436, 410, 464, 1318, 434, 414, 464, 414, 464, 414, 464, 418, 462, 414, 464, 412, 464, 416, 462, 418, 462, 414, 462, 414, 464, 414, 462, 420, 462, 414, 464, 416, 462, 412, 464, 420, 462, 412, 464, 1312, 436, 1312, 436, 418, 462, 414, 462, 416, 462, 416, 462, 420, 462, 414, 462, 414, 462, 416, 462, 420, 462, 412, 464, 1312, 436, 1314, 436, 418, 462, 414, 462, 414, 462, 414, 462, 418, 462, 414, 464, 414, 462, 414, 462, 420, 462, 414, 464, 414, 462, 414, 462, 420, 462, 414, 462, 414, 464, 414, 462, 418, 462, 416, 464, 412, 464, 414, 466, 416, 462, 414, 462, 416, 462, 412, 462, 1320, 436, 412, 464, 412, 462, 414, 462, 422, 460, 416, 462, 414, 462, 414, 462, 422, 462, 412, 462, 1312, 436, 1312, 436, 420, 462, 1314, 436, 412, 464, 414, 462, 422, 462, 414, 462, 414, 462, 416, 462, 420, 462, 1314, 438, 412, 462, 412, 464, 1316, 436}; // PANASONIC_AC uint8_t state[27] = {0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04, 0x00, 0x31, 0x2E, 0x80, 0xAF, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x80, 0x00, 0x16, 0x90};
こちらが手元にあったパナソニック製エアコンの冷房ボタンを押した情報です。
Mesg Desc.: Model: 4 (JKE), Power: On, Mode: 3 (Cool), Temp: 23C, Fan: 7 (Auto), Swing(V): 15 (Auto), Quiet: Off, Powerful: Off, Clock: 00:00, On Timer: Off, Off Timer: Off
データが多いのでわかりにくいですが、上記の行が内容になります。エアコンのリモコンは差分だけではなく、すべての情報をまとめて送信しています。そのため、送信するデータ量は非常に大量になります。
受信最小スケッチ例
#include <IRrecv.h> // PIN, Buffer Size, Timeout, Save Buffer IRrecv irrecv(26, 1024, 50, true); void setup() { Serial.begin(115200); delay(50); irrecv.enableIRIn(); } void loop() { decode_results results; if (irrecv.decode(&results)) { if (results.decode_type == NEC && results.address == 0) { if (results.repeat == false) { // 受信 Serial.printf("受信: %d\n", results.command); } else { // リピート Serial.printf("リピート受信\n"); } } } delay(1); }
IRrecvDumpV3はいろいろな機能がありましたが、必要なさそうなものを削ってみると結構シンプルでした。
赤外線送信について
赤外線送信を利用する場合には、上記のような赤外線LEDを使います。使い方は普通のLEDと同じですが、赤外線なので実際に光っているのを目視で確認することはできません。
デジタルカメラなどでは確認することができる場合があります。ただ最近のスマホ用のカメラは赤外線を見えなくしているものが多いようです。小さい自撮り用のインカメラは比較的赤外線を確認できるものが多いようです。
M5StickCの場合には、GPIO9に赤外線LEDが内蔵されているのでそのまま赤外線を送信することが可能です。ただし、ちょっと奥まった場所に設置しているので飛びが弱いです。1メートル程度の距離しか届かないので、もう少し遠距離に送信したい場合には外部に赤外線LEDを接続したほうがいいです。
また、受信ではaddressとcommandをデコードしてから解析していましたが、送信の場合には見本となるリモコンのコードを受信してみて、Codeを確認して、その値をそのまま送信してしまったほうがかんたんです。
上記の記事では、ダイソーの300円リモコンライトを受信してCodeを解析後に、M5StickCの内蔵赤外線LEDで操作する方法を紹介しています。
赤外線送受信ユニット
- M5Stack用赤外線送受信ユニット スイッチサイエンス
上記の送受信がセットになって、Groveケーブルで接続するだけで使えるユニットもあります。こちらのほうが若干送信が強いと思います。
まとめ
赤外線の送受信はライブラリを使うことで、比較的かんたんに行うことが可能です。最近のスマートスピーカーなどで使われている赤外線ユニットは、送信用の赤外線LEDを複数個使って、いろいろな方向に飛ばしています。一個だけの赤外線LEDだとピンポイントに方向を合わせないと難しそうです。
コメント