71歳の挑戦... インターネットラジオの選局が赤外線リモコンで出来ました。結構簡単！

　前回の投稿
 
https://qiita.com/Mobu_Kyoto/items/0efef61b983303411ea2

では、インターネットラジオの選局をタクトスイッチで行いました。その後、「MUSIC SPEAKERS」付属の赤外線リモコンでできないかと色々試したところ、出来るようになったので報告します。ここで、前回の構成で不具合が解ったので書いておきます。

:::note warn
ESP32ボードをスピーカーの横、上、近くに置くと動作がおかしくなる。強い磁力の為と思われます。
:::
なので、離すことにしました。
　話を戻して、今回使用するのは
 
:::note info
IRセンサー VS1838B
「MUSIC SPEAKERS」付属のリモコン
:::

![IRRemocon_VS1383B.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/55e5bb0a-d53a-badf-32d9-241b2435ec15.jpeg)

です。ArduinoIDEでの使い方は次のサイト
https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master
内の

    New 4.x program
    examples -> SimpleReceiver.ino
などを参考にしました。ただし、そのままでは良く解りませんでした。試行錯誤した結果、次のスケッチにより各ボタンの「Command」を調べ、それを利用すれば良いとわかりました。

```c:Read_IRCommand.ino
#include <IRremote.hpp>    // IRremoteライブラリ
#define IR_RECEIVE_PIN 13  // GPIOピン番号を定義

void setup() {
  Serial.begin(115200);  // シリアル通信の初期化

  pinMode(IR_RECEIVE_PIN, INPUT);
  // 赤外線受信の初期化
  IrReceiver.begin(IR_RECEIVE_PIN, true);
}

void loop() {
  if (IrReceiver.decode()) {  // 信号を受信したら
    if (IrReceiver.decodedIRData.decodedRawData != 0x0) {
      //Serial.print("Received Raw Data: ");
      //Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);  // 生のデータを16進数で表示
      IrReceiver.printIRResultShort(&Serial);  // 受信したデータの簡潔な概要を表示
      //IrReceiver.printIRSendUsage(&Serial);    // 受信した信号を送信するためのコードを表示
    }
    IrReceiver.resume();  // 次の信号を受信できるようにする
  }
}
```
解ってみればすごく簡単でした。
　接続についてです。赤外線センサー「VS1338B」の隣合うGND、VCC(3.3V)ピンをそのままESP32ボード横に直刺しし、信号ピンは13番とジャンパーワイヤーで接続。

![IR_Sensor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/aa49e222-a73a-d719-5a21-4cb82f796868.jpeg)
　ネットラジオ選局は

    チャンネルアップは、[ >>| ]ボタンで。コマンドは、0x43
    チャンネルダウンは、[ >|| ]ボタンで。コマンドは、0x44
としました。チャンネルダウンに、[ |<< ]ボタンを割り振りたかったのですが、ノイズとして常に出てるようなので使わないことにしました。VCC=3.3Vは電圧不足でノイズが出るのかも知れません。


arduinoIDE 2.3.2でのスケッチは以下です。

```c:NetRadio_IR_Select.ino
#include <IRremote.hpp>  // IRremoteライブラリ

#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define IR_RECEIVE_PIN 13  // GPIOピン番号を定義

#define I2S_DOUT 27  // DIN
#define I2S_BCLK 25  // BCK
#define I2S_LRC 26   // LCK

#define OLED_SCL 15
#define OLED_SDA 4
#define OLED_RST 16
#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

String ssid = "Your SSID";
String password = "Your Password";

Audio audio;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

uint8_t volume = 21;      // 0...21
uint8_t cur_station = 0;  // current station No.

#define EofRadios 10  // 0 - 10
String stations[] = {
  "WRTI_CLASSICAL https://playerservices.streamtheworld.com/api/livestream-redirect/WRTI_CLASSICAL.mp3",
  "WRTI_JAZZ https://playerservices.streamtheworld.com/api/livestream-redirect/WRTI_JAZZ.mp3",
  "relax.stream.publicradio.org/relax.mp3",  // Your Classical - Relax
  "ais-sa2.cdnstream1.com/b22139_128mp3",    // 101 SMOOTH JAZZ
  "smoothjazz.cdnstream1.com/2585_128.mp3",
  "avw.mdr.de/streams/284310-0_mp3_low.m3u",
  "www.radiomonique.nl/winamp_RM_64.pls",
  "ice1.somafm.com/illstreet-128-mp3",    // SomaFM / Illinois Street Lounge
  "ice1.somafm.com/secretagent-128-mp3",  // SomaFM / Secret Agent
  "ice1.somafm.com/seventies-128-mp3",    // SomaFM / Left Coast 70s
  "ice1.somafm.com/bootliquor-128-mp3"    // SomaFM / Boot Liquor
  //audio.connecttoFS(SD, "/test.wav");     // Playing music file in SD 
};

TaskHandle_t thp[1];

void setup() {
  Serial.begin(115200);

  pinMode(IR_RECEIVE_PIN, INPUT);
  IrReceiver.begin(IR_RECEIVE_PIN, true);

  pinMode(OLED_RST, OUTPUT);
  digitalWrite(OLED_RST, LOW);
  delay(20);
  digitalWrite(OLED_RST, HIGH);
  Wire.begin(OLED_SDA, OLED_SCL);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) {  // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);

  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid.c_str(), password.c_str());
  while (WiFi.status() != WL_CONNECTED) delay(1500);
  Serial.println(F("WiFi start"));
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(volume);  // 0...21
  audio.connecttohost(stations[cur_station].c_str());
  //audio.connecttoFS(SD, "/test.wav");     // SD

  display.setCursor(0, 0);
  display.print("NetRADIO:No.");
  display.setCursor(72, 0);
  display.print("0");
  display.setCursor(0, 8);
  display.print(stations[cur_station].c_str());
  display.display();

  xTaskCreatePinnedToCore(Core0, "Core0", 4096 * 2, NULL, 3, &thp[0], 0);
  // if 4096, resetted by WDTimer in some cases.
}

void loop() {
  audio.loop();
}

void Core0(void *args) {
  while (1) {
    delay(1);

    if (IrReceiver.decode()) {
      if (IrReceiver.decodedIRData.command == 0x43 ||  // Button[>>|] pressed
          IrReceiver.decodedIRData.command == 0x44)    // Button[>||] pressed
      // This Sensor cotinuously receives either 0x0 or 0x40 from remo_con.
      // 0x40(|<<) seems to be noise. So can not use Button[|<<].
      {
        audio.stopSong();
        delay(1000);
        if (IrReceiver.decodedIRData.command == 0x43) {
          cur_station++;
          if (cur_station > EofRadios) { cur_station = 0; }
        } else if (IrReceiver.decodedIRData.command == 0x44) {
          cur_station--;
          if (cur_station >= 255) { cur_station = EofRadios; }
        }
        delay(1000);
        Serial.print(F("\n\rStation : "));
        Serial.print(cur_station);
        Serial.print(F(" > "));
        Serial.println(F(stations[cur_station].c_str()));
        audio.connecttohost(stations[cur_station].c_str());

        display.clearDisplay();
        display.setCursor(0, 0);
        display.print("NetRADIO:No.");
        display.setCursor(72, 0);
        display.print(cur_station);
        display.setCursor(0, 8);
        display.print(stations[cur_station].c_str());

        display.display();
      }
      IrReceiver.resume();  // 次の信号を受信できるようにする
    }
  }
}

char BITRATE[6];
void audio_showstreamtitle(const char *info) {
  Serial.print(F("Title : "));
  Serial.println(info);

  display.clearDisplay();

  display.setCursor(0, 0);
  display.print("NetRADIO:No.");
  display.setCursor(72, 0);
  display.print(cur_station);

  display.setCursor(0, 8);
  display.print(stations[cur_station].c_str());

  display.setCursor(0, 8 * 6);
  display.print(info);

  display.setCursor(90, 0);
  display.print("       ");
  display.setCursor(90, 0);
  display.print(BITRATE);

  display.display();
}

void audio_bitrate(const char *info) {
  Serial.print(F("bitrate     "));
  Serial.println(info);

  strncpy(BITRATE, info, 6);

  display.setCursor(90, 0);
  display.print("       ");
  display.setCursor(90, 0);
  display.print(BITRATE);
  display.display();
}

// optional
char *s1 = "slow stream, dropouts are possible";
void audio_info(const char *info) {
  if (strcmp(info, s1) == 0) {
    Serial.print('.');
  }else{
    Serial.print("info -> ");
    Serial.println(info);
  }
}
```
　前回、タクトスイッチを使うことができて喜んだのもつかの間、もう不要になってしまいました。その代わり、強力なツールを手にしました。おもちゃの車の操作などに使えそうです。
　最後まで見ていただきありがとうございました。