上位に戻る ESP32 Radiko で、日本語放送を聞く 初版2025/04/23

ダイニングキッチンで、BGMで、FM放送 FM802を流しているのですが、お古のスマホでRadikoアプリを使っています
このスマホ相当古くなって来て最近調子が悪いので ESP32と、DACで、Radikoのストリームで、FM802を聞いてみたく
やってみました
と言っても、wakwak-kobaさんが提供頂いているものをそのまま使っただけの何も解ってないけど、動きましたです・・・。



  1. どんな感じ
    提供頂いています 凡例をそのまま使ってます。ブラウザからの操作で、選局できるようになっています


  2. ハード準備
    アリエクで購入
    ESP32 WROOMを使いましたが、
    たまに、音飛びが発生
    おそらくバッファ不足
    後述参照
    アリエクで購入
    添付ケーブル 差す時ムチャ
    硬いが差すと、ズボズボ
    使えんわあ

  3. 回路図


    DACの設定関係のピン配線ですが、内部にジャンパー配線があり、ジャンパーしてしまえば配線不要です
    ハンダ付けが苦手な場合は、ピンで配線してください
    SCK設定

    FLT DEMP XSMT FMT設定


  4. Radikoの会員登録  全国放送を聞く場合にのみプレミアム会員登録必要です 無料会員登録は不要です
    会員登録されてない方は、無料会員又はプレミアムに登録
    無料会員登録は、Webからは出来ないみたい スマホのRadikoアプリから登録
    無料会員登録 わかりにくい!! わざとやろ

    右下のアカウントを選択 下にスクロール 会員登録・ログイン 無料会員登録はこちら



  5. ソフト
    githubに掲載されています wakwak-koba/WebRadio_Japan を使っています wakwak-kobaさんに感謝です!!
    Radiko以外にも、日本語放送対応しています 今回httpd版を利用しています

    必要ライブラリ
    espressif/arduino-esp32
    wakwak-koba/ESP8266Aydio
    wakwak-koba/WebRadio_Japn

    中身ほとんど使っていないと思われ、面倒なので、全部セットアップしました

    Codeを選択してDownloadZIP
    を選択

    他のライブラリも同じ手順で
    ダウンロードします
    librariesフォルダの中に入れます


    プログラムですが、WeRadio_Japan-mainのexamplesのhttpd版のRadikoをそのまま使っています
    他にも多数の凡例がありました スゴスギ
    IPアドレスは、固定にしました でないと、ブラウザで選曲するとき、アドレスがワカランですから
    変更点 
    Radikoの登録メールアドレス 登録パスワード プレミアム会員のみ必要です 通常はコメントアウトしてください
    Wi-Fi 接続 SSID パスワード
    ネットワーク設定 IPアドレス ゲートウェイ サブネット DNS

    // https://twitter.com/wakwak-koba/

    #define RADIKO_USER "Radiko登録メールアドレス"
    #define RADIKO_PASS "登録パスワード"

    #include <WebRadio_Radiko.h>
    #include <AudioOutputI2S.h>
    #include <ArduinoOTA.h>
    #include <WebServer.h>

    static AudioOutputI2S out(0, AudioOutputI2S::EXTERNAL_I2S, 10);
    static Radiko radio(&out, APP_CPU_NUM);
    static WebServer httpd(80);
    static String stationName;

    // Wi-Fi接続情報を入力
    const char* ssid     ="SSIDキー";
    const char* password = "パスワード";
    const IPAddress ip(使用するIPアドレス);
    const IPAddress gateway(デフォルトゲートウェイ);
    const IPAddress subnet(255,255,255, 0);
    const IPAddress dns1(DNSサーバアドレス);
    //wifi接続
    int lpcnt;
    int lpcnt2;


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

    #ifdef CONFIG_IDF_TARGET_ESP32S3
      out.SetPinout(15, 6, 7);    // bck, lrc, dout
      pinMode( 4, OUTPUT); digitalWrite( 4, LOW);   // XSMT
      pinMode( 5, OUTPUT); digitalWrite( 5, LOW);   // FMT
      pinMode(16, OUTPUT); digitalWrite(16, LOW);   // SCK
      pinMode(17, OUTPUT); digitalWrite(17, LOW);   // FLT
      pinMode(18, OUTPUT); digitalWrite(18, LOW);   // DEMP
    #else
    //out.SetPinout(26, 25, 22);  // bck, lrc, dout
    #endif

     // ssidとpasswordを用いてWi-Fiに接続
      Serial.print("Connecting to ");
      Serial.println(ssid);
      if (!WiFi.config(ip,gateway,subnet,dns1)){
         Serial.println("Failed to configure!");
      }
       while (WiFi.status() != WL_CONNECTED) {    // 接続確認
          delay(500);                            //   0.5秒毎にチェック
          lpcnt += 1 ;                           //
          if (lpcnt > 6) {                       // 6回目(3秒) で切断/再接続
            WiFi.disconnect(true,true) ;
            WiFi.config(ip,gateway,subnet,dns1);        //
            WiFi.begin(ssid, password);    //
            lpcnt = 0 ;                          //
            lpcnt2 += 1 ;                        // 再接続の回数をカウント
          }                                      //
          if (lpcnt2 > 3) {                      // 3回 接続できなければ、
            ESP.restart() ;                      // ソフトウェアリセット
          }                                      //
          Serial.print(".");                     //
      }            
     
      // IPアドレスを出力
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());


      ArduinoOTA.onStart([]() {
        radio.stop();
        out.stop();
      });
      ArduinoOTA.begin();

    #if defined( RADIKO_USER ) && defined( RADIKO_PASS )
      radio.setAuthorization(RADIKO_USER, RADIKO_PASS);
    #endif
      radio.setEnableSBR(true);
      radio.onPlay = [](const char * station_name, const size_t station_idx) {
        Serial.printf("onPlay:%d %s\n", station_idx, station_name);
        stationName = String(station_name);
        };
      radio.onInfo = [](const char * text) {
        Serial.println(text);
      };
      radio.setSyslog("255.255.255.255");
     
      if(!radio.begin()) {
        Serial.println("failed: radio.begin()");
        for(;;);
      }

      for(int i = 0; i < radio.getNumOfStations(); i++)
        Serial.printf("%d %s\n", i, radio.getStation(i)->getName());

      httpd.on("/top", [&]() {
        if(httpd.method() == HTTP_POST) {
          auto select_station = httpd.arg("station");
          if(select_station.length()) {
            auto station = radio.getStation(select_station.toInt());
            station->play();
            stationName = String(station->getName()) + " に切り替え中";
          }
        }

        httpd.sendHeader("Connection", "close");
        String html =
          "<!DOCTYPE html><html>"
          "<head>"
          "<title>WebRadio_Radiko</title>"
          "<meta charset=\"UTF-8\">"
          "<meta http-equiv=\"refresh\" content=\"5\">"
          "</head>"
          "<body>"
          "<h1>" + stationName + "<h1>"
          "</body>"
          "</html>";
        httpd.send(200, "text/html", html);
      });
     
      httpd.on("/list", HTTP_GET, [&]() {
        httpd.sendHeader("Connection", "close");
        String htmlHeader =
          "<!DOCTYPE html><html>"
          "<head>"
          "<title>WebRadio_Radiko</title>"
          "<meta charset=\"UTF-8\">"
          "<script type=\"text/javascript\">"
          "  function  sel(index) {"
          "    form.station.value = index;"
          "    form.submit();"
          "  }"
          "</script>"
          "</head>"
          "<body>"
          "<h2>WebRadio_Radiko</h2>"
          "<form method=\"post\" action=\"top\" target=\"top\" id=\"form\">"
          "  <input type=\"hidden\" name=\"station\" />"
          "</form>";
        String htmlFooter = "</body></html>";
        String htmlbody;
        for(int i = 0; i < radio.getNumOfStations(); i++)
          htmlbody += "<a href=\"javascript:sel(" + String(i) + ")\">" + String(radio.getStation(i)->getName()) + "</a><br />";
        httpd.send(200, "text/html", htmlHeader + htmlbody + htmlFooter);
      });

      httpd.on("/", HTTP_GET, [&]() {
        httpd.sendHeader("Connection", "close");
        String html =
          "<!DOCTYPE html><html>"
          "<head>"
          "<title>WebRadio_Radiko</title>"
          "<meta charset=\"UTF-8\">"
          "</head>"
          "<frameset rows=\"96,*\" cols=\"*\" frameborder=\"no\">"
          "  <frame src=\"top\" name=\"top\" frameborder=\"no\" scrolling=\"no\" />"
          "  <frame src=\"list\" name=\"list\" frameborder=\"no\" scrolling=\"auto\" />"
          "</frameset>"
          "<noframes>"
          "  <body>"
          "  フレームを使っています"
          "  </body>"
          "</noframes>"
          "</html>";
        httpd.send(200, "text/html", html);
      });

      httpd.begin();
      radio.play();
    #ifdef CONFIG_IDF_TARGET_ESP32S3
      digitalWrite( 4, HIGH);  // XSMT
    #endif
    }

    void loop() {
      ArduinoOTA.handle();
      httpd.handleClient();
      radio.handle();
    }





  6. 音飛び現象について
    たまに、音が飛ぶことがあります 
    おそらくバッファ不足と思われます。今回使ったのはESP32WROOM32で、RAM 520Kbyteしかありません
    容量の大きなもので後日テストしてみます
    ESP32S3N16R8(RAM8Mのもの)が、アリエクで、662円無料配送で、航空便だったので、ポチってしまいました





    以上間違い等ありましたら、以下ご意見箱にお願いします

   

    ご意見箱