赤外線用の学習リモコンをBluetooth操作対応リモコンにしてみた

# はじめに
今回は市販の赤外線用の学習リモコン利用し Atom Lite 経由で Bluetooth 機器の操作も可能な万能学習リモコンとして使えるようにしてみたいと思います。
※ 今回は自宅にある Chromecast with Google TV で登録を行って確認してみましたが、Fire Stick TV など他の Bluetooth リモコンでも同じようなことは出来ると思います。
※ 赤外線や Bluetooth の使い方をよく理解していない部分も多いので、試す場合は自己責任でお願いします。

ソース類は [GitHub:toyo-toyo/AtomLite_IR_Recv_2_Ble_Gamepad](https://github.com/toyo-toyo/AtomLite_IR_Recv_2_Ble_Gamepad) に置いています。

# 必要なもの
- [ATOM Lite](https://www.switch-science.com/catalog/6262/) 968 円 (2021-03-10現在)
- [M5Stack用赤外線送受信ユニット](https://www.switch-science.com/catalog/5699/) 308 円 (2021-03-10現在)
- 学習リモコン [(ソニー 学習リモコン RM-PLZ430D : テレビ/レコーダーなど最大5台操作可能 RM-PLZ430D)](https://www.amazon.co.jp/gp/product/B0040N9MZM/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1) 2,600 円 (2021-03-10現在)  
※ 上記リンクの学習リモコンは私が購入したモデルになります。すでに購入済みの学習リモコンを持っているのであれば、他社製品のものだったとしても動作できると思います。
- Arduino IDE が動作可能のパソコン

# 作ることになった経緯
この章は読み飛ばしても問題ありません。

実装方法だけ知りたい方は
[赤外線リモコンを受信し、Bluetooth信号を送信](#赤外線リモコンを受信しbluetooth信号を送信)
から確認してください。

## 市販の学習リモコン調査
家にはリモコンがたくさんあり学習リモコンを使って一つにまとめたいと思いましたが、最近購入した Chromecast with Google TV が Bluetooth リモコンでした。
![RemoteControl.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/c904978a-1987-4712-474b-96d6dc1fa258.jpeg  "リモコン類")


そこで Bluetooth の学習もできるリモコン製品を探してみたところ、[ソニー SONY スマートリモコン HUIS REMOTE CONTROLLERクレードルセット (ホワイト) HUIS-100KC](https://www.amazon.co.jp/gp/product/B073J3SN77/ref=ox_sc_act_title_1?smid=AP4OOMR27C7SG&psc=1)ぐらいしか見つけれませんでした。

[ソニー SONY スマートリモコン HUIS REMOTE CONTROLLERクレードルセット (ホワイト) HUIS-100KC](https://www.amazon.co.jp/gp/product/B073J3SN77/ref=ox_sc_act_title_1?smid=AP4OOMR27C7SG&psc=1)の値段を確認してみると 19,800 円 (2021-03-10現在)と思っていた以上に高価で、しかも液晶での操作なので少し使いにくそうだなと感じました。


スマートリモコンはすでに使っていますが、携帯画面でのリモコン操作が面倒なので声での操作でしかほぼ使っていない状況です。

## Bluetooth 対応リモコン自作方法の検討
とりあえず Bluetooth と赤外線を操作できるリモコンを自作出来ないか?と考え、余っているリモコンの赤外線信号を判断し、スマートリモコンの API または Bluetooth の操作をするという方法を考えました。
スマートリモコンの API 呼び出しと Bluetooth での接続が可能な、家に存在するIoT機器で考えてみたところ、色々と候補はありましたが Raspberry Pi Zero で確認してみることにしました。

実用はしてはいませんでしたが昔に作った Raspberry Pi の自作スマートリモコンから赤外線受信部品をとりだし、試作を簡単に Raspberry Pi Zero で作ってみました。
![RaspberryPiZero_IR_module.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/2b4a7329-a796-5884-9e7a-4b9d4f2fdf46.jpeg "Raspberry Pi Zero と 赤外線受信モジュール")

この方法だと余ったリモコンさえあれば、学習リモコンすら必要ないのでいいと考えていましたが、スマートリモコンへの登録が面倒そうだったのと、Raspberry Pi だと赤外線受信部分もむき出しなので何かしら工作が必要なのでもう少し考えてみることにしました。

そこで学習リモコンを購入する必要は出てきますが、赤外線の信号を学習リモコンに任せてしまえば、スマートリモコンの API を叩く必要もなくシンプルでいいのかな?と考えました。

スマートリモコンの API が不要であれば、赤外線受信が出来て Bluetooth の操作出来るだけでもいいので、 Atom Lite でも試してみることにしました。
M5Stack 用の赤外線送受信ユニットも購入後に一度試して放置していたという経緯もあり部品はそろっていました。
![AtomLite_IrUnit.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/bc09a083-b9a8-8a66-6fcc-e9be26f4d3d4.jpeg "Atom Lite と M5Stack 用の赤外線送受信ユニット")

物理操作が出来る赤外線用の学習リモコンは複数あるみたいでしたが、比較的安価で評判もよさそうな
[ソニー 学習リモコン RM-PLZ430D : テレビ/レコーダーなど最大5台操作可能 RM-PLZ430D](https://www.amazon.co.jp/gp/product/B0040N9MZM/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)
を購入して、とりあえず赤外線リモコンはこれに集約し、Bluetooth リモコンは Atom Lite 経由で操作する方針に切り替えました。



# 赤外線リモコンを受信し、Bluetooth信号を送信
Atom Lite で赤外線リモコンのボタンを判断し、 Bluetooth の信号を送信するようにしてみます。
Bluetooth の送信には Keyboard 用のライブラリもありましたが、今回は Gamepad 用のライブラリを使用します。

[lemmingDev/ESP32-BLE-Gamepad](https://github.com/lemmingDev/ESP32-BLE-Gamepad) で Zip ファイルをダウンロードします。
Arduino IDE の「スケッチ」＞「ライブラリをインクルード」＞「.zip形式のライブラリをインストール」でライブラリを登録してください。

```c:AtomLite_IR_Recv_2_Ble_Gamepad.ino
#include <M5Atom.h>
#include <IRrecv.h>
#include <IRremoteESP8266.h>
#include <IRutils.h>
#include <BleGamepad.h> 

const uint16_t kRecvPin = 32;
const uint16_t kCaptureBufferSize = 1024;
const uint8_t kTimeout = 50;
const CRGB CRGB_BLE_CONNECTED(0x00, 0x00, 0xf0);
const CRGB CRGB_BLE_DISCONNECTED(0x00, 0xf0, 0x00);

IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
decode_results results;  // Somewhere to store the results

BleGamepad bleGamepad;
bool isBleConnected = false;

void setup() {
  M5.begin(true, false, true);
  M5.dis.drawpix(0, CRGB_BLE_DISCONNECTED);
  irrecv.enableIRIn();
  bleGamepad.begin();
}

void loop() {
  M5.update();
  // if (bleGamepad.isConnected()) {
  if (true) { // 赤外線信号確認だけの場合は true 固定
    if (!isBleConnected) {
      M5.dis.drawpix(0, CRGB_BLE_CONNECTED);
      isBleConnected = true;
      Serial.println("Connected");
    }
    // Check if the IR code has been received.
    if (irrecv.decode(&results)) {
      uint32_t value = results.value;
      Serial.println(value);
      switch(value){
        case 1111111111:
          Serial.println("上");
          sendLeftThumb(0, -32767);
          break;
        case 2222222222:
          Serial.println("下");
          sendLeftThumb(0, 32767);
          break;
        case 3333333333:
          Serial.println("左");
          sendLeftThumb(-32767, 0);
          break;
        case 4444444444:
          Serial.println("右");
          sendLeftThumb(32767, 0);
          break;
        case 5555555555:
          Serial.println("決定");
          sendButton(BUTTON_1);
          break;
        case 6666666666:
          Serial.println("戻る");
          sendButton(BUTTON_2);
          break;
        default:
          Serial.println("他の値です");
      }
    }
  } else {
    if (isBleConnected) {
      M5.dis.drawpix(0, CRGB_BLE_DISCONNECTED);
      isBleConnected = false;
      Serial.println("Disconnected");
    }
  }
  delay(50);
}
void sendLeftThumb(int16_t x, int16_t y) {
  bleGamepad.setLeftThumb(x, y);
  delay(1);
  bleGamepad.setLeftThumb(0, 0);
}
void sendButton(uint8_t sendkey) {
  bleGamepad.press(sendkey);
  delay(1);
  bleGamepad.release(sendkey);
}
```
上記コードを Arduino IDE で Atom Lite に書き込みします。
赤外線送受信ユニットに向けてリモコンボタンを押下し、シリアルモニタでボタンごとにでる赤外線信号を確認します。

```
1234567890
他の値です
```

のように赤外線信号が表示されると思います。

同じボタンを複数回押下し、数値に変化がないことを確認してください。
確認出来たら case 1111111111:などの部分を対応するボタンの赤外線信号にコードを変更します。
同様に「上」「下」「左」「右」「決定」「戻る」の6か所のボタンを確認しコードを変更します。

変更したコードを再度を Arduino IDE で Atom Lite に書き込みします。
シリアルモニタにボタンに対応した「上」などが表示されるのを確認できれば登録完了です。

すべてのボタンを変更できれば

```c
  // if (bleGamepad.isConnected()) {
  if (true) { // 赤外線信号確認だけの場合は true 固定
```

の部分を

```c
  if (bleGamepad.isConnected()) {
  // if (true) { // 赤外線信号確認だけの場合は true 固定
```

に変更します。

また複数のボタンで同じ動作をさせたい場合は

```c
        case 1111111111:
        case 7777777777:
        case 8888888888:
          Serial.println("上");
          sendLeftThumb(0, -32767);
          break;
```
のように書くことも可能です。
私の場合は2種類のリモコンで同様の操作ができるように登録し、さらに戻るボタンは複数のボタンを割り当ててみました。

# Bluetoothリモコンとしてペアリング
Bluetooth リモコンを登録したい機器で Atom Lite へのペアリングを行います。
ペアリングが完了すると Atom Lite の LED が青く点灯します。
赤外線送受信ユニットに向けてリモコンボタンを押下し想定通り機器が操作できることを確認します。

無事操作出来れば完了です。

登録する Bluetooth 機器によっては操作ができないケースがあると思われます。
その場合は BUTTON_3 など値を変化させるとうまくいくケースもあると思います。

# おまけ
## 独自の赤外線信号を登録
学習リモコン (RM-PLZ430D) を確認していたところ、購入したての状態では信号が登録されていないボタンがいくつかありました。
余ったリモコンの信号などを登録し、何かしらの信号を送信するように出来れば問題ないですが、余ったリモコンがない場合などの為に独自の信号を発信できるコードも書いておきます。

```c:AtomLite_IR_Send.ino
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <M5Atom.h>

const uint16_t kIrLed = 26; // AtomLite内蔵LED 12 IR UNIT 26
const uint32_t sendValue = 1234567890;    //送信する赤外線信号

IRsend irsend(kIrLed);  // Set the GPIO to be used to sending the message.

void setup() {
  M5.begin(true, false, false);
  irsend.begin();
}

void loop() {
  M5.update();
  // Atom Lite Button
  if (M5.Btn.wasReleased()) {
    Serial.println("sendNEC()");
    irsend.sendNEC(sendValue);
  }
  delay(100);
}
```
上記コードを Arduino IDE で Atom Lite に書き込みします。
Atom Lite に赤外線送受信ユニットを装着し、学習リモコンに向けて Atom Lite のボタンを押下すると赤外線信号が送信されます。
sendValue (送信するコード)を変更しながら「上」「下」「左」「右」「決定」「戻る」の6項目を学習リモコンに登録してください。


## 3Dプリンタでケース作成
ここは必要ありませんが、3D プリンター「 ADVENTURER 3S 」でケースも自作してみました。

興味がある方は印刷してお使いください。
[AtomLite_IR_UNIT.stl](https://github.com/toyo-toyo/AtomLite_IR_Recv_2_Ble_Gamepad/blob/master/AtomLite_IR_UNIT.stl)
[AtomLite_IR_UNIT_Cap.stl](https://github.com/toyo-toyo/AtomLite_IR_Recv_2_Ble_Gamepad/blob/master/AtomLite_IR_UNIT.stl)

![AtomLiteIrUnitCase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/cb30fac3-122f-412f-155a-10e1af2b4288.png "3D プリント中の FlashXPrint 画面")
![AtomLiteIrUnitCase2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397682/0dc29c81-3c4c-be7d-c504-1ba7c1545c00.jpeg "完成したケースに Atom Lite と M5Stack 用の赤外線送受信ユニットを装着")



# 参考記事
[ESP32で赤外線通信ができるライブラリ「IRremoteESP8266」の使い方](https://wak-tech.com/archives/1627)
[M5Stack Atomで赤外線リモコンを作る（2）受信編](https://iot-gym.com/how-to-receive-ir-signals-by-using-m5atom/)
[ATOM LiteをBLEキーボードにして，特定の文字列を送付する](https://gist.github.com/3110/aab5376aa27257903b4b3b9bc71b86d4)
[lemmingDev/ESP32-BLE-Gamepad](https://github.com/lemmingDev/ESP32-BLE-Gamepad)



# まとめ
Atom Lite と赤外線送受信ユニットであれば、ケースは作らずにそのままの実用でもそこまで違和感もなく、半田なども使わなくていいのでかなり敷居が低くなりましたね。
リモコンでもっと色々操作出来たほうがいいかな?とも思うので、Raspberry Pi で作り直すかもしれません。

もちろんここまで出来たら Bluetooth 信号もスマートスピーカーやスマートリモコン経由で音声操作も可能になりますね。

スマートリモコンは携帯での操作が不便なので、余ったリモコンで他の赤外線信号を送信できる機能はスマートリモコンの機能として実装してほしいですね。
それと Bluetooth 機器の操作も出来るスマートリモコンも早く市販してほしいです。

あと Atom Lite を操作するのに赤外線である必要はないので、Wifi 対応リモコンとかも市販してほしいですね。

とりあえずこれでリモコンを一つにまとめれそうなのでうれしいですね(●´ω｀●)

まだ使い始めなので、とりあえずこれを使っての使用感など様子をみてみます。
家族が複数人いるのであれば、学習リモコン自体も複数あってもいいかもですね。