M5StickC(ESP32)による「ELEGOO Arduino用UNO R3スターターキット」を利用したArduino入門 その11 赤外線受信モジュール

現時点の情報です。最新情報はM5StickC非公式日本語リファレンスを確認してみてください。

概要

前回はジョイスティックでした。今回は赤外線受信センサーです。

赤外線受信センサーとは?

秋月さんだと上記になります。主に赤外線リモコンの受信用センサーになります。キットに入っているのはモジュールになっていて、信号を受信するとLEDが光るのでわかりやすくなっています。

気をつける必要があるのが、赤外線には波長があり一般的に使われているのが940nm前後になります。センサーによって940nmだったり945nmあたりが一番感度が良くなっていますがこれぐらいの差であればそれほど気にしなくてもよいと思いますが、なるべく同じ波長のものをペアにして使ったほうがいいと思います。

また、商品ページに中心周波数が書いてありますが、基本的には38kHz前後を赤外線リモコンで使うことが多いみたいです。

赤外線のフォーマットについて

上記などのサイトが詳しいです。

上記などで細かい内部関数を使って受信をためしましたが、通常はライブラリを使いますので細かいことは知らなくても大丈夫です。

接続方法

ちょっとわかりにくいのですが、キットの赤外線受信センサーは以下の表の役割になっています。接続する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で操作する方法を紹介しています。

赤外線送受信ユニット

上記の送受信がセットになって、Groveケーブルで接続するだけで使えるユニットもあります。こちらのほうが若干送信が強いと思います。

まとめ

赤外線の送受信はライブラリを使うことで、比較的かんたんに行うことが可能です。最近のスマートスピーカーなどで使われている赤外線ユニットは、送信用の赤外線LEDを複数個使って、いろいろな方向に飛ばしています。一個だけの赤外線LEDだとピンポイントに方向を合わせないと難しそうです。

コメントする

メールアドレスが公開されることはありません。

管理者承認後にページに追加されます。公開されたくない相談はその旨本文に記載するかTwitterなどでDM投げてください。またスパム対策として、日本語が含まれない投稿は無視されますのでご注意ください。