上位に戻る BGM用自動放送装置 初版2025/5/21

テストで、Webラジオがうまく動いたので、正規に作ることにしました
機能 
・インターネットのRadikoで日本語FM放送を流す
・定時チャイム ラジオの時刻起動など
・音楽ファイルを再生
・Webページで設定
・赤外線リモコンで制御

  1. 構成
    FMラジオは、インターネットのRadikoを使って流します。プレミアム会員になると、全国のFMラジオ放送を聞くことができます
    無料会員だと、自分の住まいのエリアのみとなります
    ESPRESSIF社のマイコン ESP32 S3 N16R8(フラッシュ16MB PSRAM8MB)と、デジタル信号を音声に変換するDAC
    PCM5102を使います

    チャイムを流したり、音楽ファイルを再生するのは、MP3プレイヤー MP3-TF-16Pを使うことにします
    余って持っていたので SDカードユニットを追加してDACで再生する方法もあるかと思います

    赤外線受光器は、VS18388を使っています 大量に余って持ってるので
    赤外線リモコンは、すでにダイニングで使っているELPA IRC-202Tを使っています 手元に余っているリモコンがあれば
    信号解析してつかえると思います(プログラムが自動判別してくれるので、メジャーどころであれば利用可能)
  2. どんな感じ
    左上が、電源
    右上が、赤外線受光部と
    アンプ起動用リレー
    右中が、マイコン
    右下が、DACと、プレイヤー

    左下が、DACと、プレイヤー
    の出力を切り替えるリレー

    最初は、下のミキサーで
    設計
    ミキサー
    オペアンプで作ろうかと思った
    のですが アリエクでヘッドフォン
    アンプが、50円だったので
    購入しました
    設置したところ
    赤外線が届くようスピーカの
    上に設置しています
    以前は、古いスマホを利用

    スピーカの電源を入れて
    スマホのRadikoを起動してました
    webページ
    選曲画面と、設定画面

    設定画面作るのめんどいス
    週間スケジュールとかも
    できるようにしようかと思った
    のですが、画面を作るのが
    めんどい・・・。
    HTML全部記述するのはきつい

    あと、設定したデータを保存
    するのも記述が増える・・。

    で、断念しました



  3. どんな回路
    最初の回路
    MP3プレイヤーですが、ソフトシリアル通信だと処理が忙しすぎるようで不安定なので、ハードシリアルに変更しました
    送信は、正常になりましたが、受信ができません。単体でのテストでも受信できませんでした。ライブラリも別ものも
    試してみましたが受信できず、BUSY端子があったので再生中の判定をこのBYSY端子を使って行いました

    バラックで組んでいるときは異常無かったのですが、組み込んで スイッチング電源から供給すると、
    起動できず、再起動を繰り返します Wi-Fi接続失敗による再起動です COMポートのUSB接続で電源供給されると
    起動します たまに失敗しますが・・・。赤外線の受信確認のLEDが、たまに、ビビと光ます ノイズかあ?3V3に1000μ
    のパスコン入れてみましたが改善しませんでした 結論 赤外線センンサーの電源を5Vラインに変更したところ正常に
    なりました
    ミキサーアンプも不定期周期で、ノイズがでます。テストで別電源にてLM386アンプでミキシングしていた時は、問題なかった
    のですが アンプのゲインを下げるとましにはなりますが、無音が続くとノイズが気になって仕方がない
    Wi-Fiの電波は出てるし、マイコン本体からもノイズ出てるし アンプとの相性最悪
    ミキサーアンプ止めて、リレーで切り替えることにしました

    改修後、回路図



  4. プログラムについて
    ■Radikoのプログラムについて
     wakwak-kobaさん提供のプログラムです 以下のページ参照してください
     ESP32 Radikoで、日本語放送を聞く

    ■音量調整について
     デフォルトは、最大音量になっているので、出力音量デカいです
     
      out.SetGain(volatai);

    音量は、上記で設定できます volatai は、0〜1

    ■設定用Webページについて
     設定用Webページを追加するのに、選曲ページのラジオ局一覧リストの最後尾に、遷移用のボタンを追加しました
     元のページがフレームを利用している為、そのまま遷移すると、そのフレーム内に表示されてしまうので、一旦フレーム
     解除したウィンドウに表示する用にします top.window.location.href= を使います
     listページの最後尾に、「設定」ボタンを追加しました
      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 = "<br><button type=\"button\" onclick=\"top.window.location.href='/settei'\">設定</button></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);
      });

     遷移先の設定画面の作り方は、以下を参考にしてください
     ESP32 webサーバ ブラウザから設定変更する

    ■MP3-TF-16P ハードシリアル通信について
     参考 ESP32で、MP3-TF-16Pを使ってみる ソフトシリアル通信です これをハードシリアル通信に変更します
     以下のように記述しましたが、送信は、okでコマンドは送れますが、受信がで来ませんでした。原因不明です
     別のライブラリDFRobotDFPlayerMini.hでも試しましたが、ハードシリアルにすると、受信できませんでした
     プレイヤーの状態を知りたいので、BUSY信号を使っています トホホ・・・・。
     

    #include <DFPlayer.h>

    #define MP3_RX_PIN              18    //GPI18 to DFPlayer Mini TX
    #define MP3_TX_PIN              17    //GPI17 to DFPlayer Mini RX
    #define MP3_SERIAL_SPEED        9600  //DFPlayer Mini suport only 9600-baud
    #define MP3_SERIAL_TIMEOUT      350   //average DFPlayer response timeout 200msec..300msec for YX5200/AAxxxx chip & 350msec..500msec for GD3200B/MH2024K chip

    HardwareSerial mp3Serial(2);
    DFPlayer       mp3;


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

      mp3Serial.begin(MP3_SERIAL_SPEED, SERIAL_8N1,MP3_RX_PIN, MP3_TX_PIN); //false=signal not inverted, 0=ISR/RX buffer size (shared with serial TX buffer)
      mp3.begin(mp3Serial, MP3_SERIAL_TIMEOUT, DFPLAYER_HW_247A, false); //"DFPLAYER_MINI" see NOTE, false=no response from module after the command
     
      mp3.setVolume(30);                      //0..30, module persists volume on power failure
      Serial.println(mp3.getStatus());        //0=stop, 1=playing, 2=pause, 3=sleep or standby, 4=communication error, 5=unknown state
      Serial.println(mp3.getVolume());        //0..30

      mp3.repeatFolder(2); //02フォルダのファイルを順次再生し、繰り返す(001.mp3〜)
      //mp3.playFolder(1,1); //01フォルダ内の001.mp3ファイルを再生する

    }

    void loop()
    {

    }


    ■esp32 赤外線受信について
     赤外線受信のライブラリ調べると、昔と比べてかなり良くなってました
     IrReceiver.printIRResultShort(&Serial);で、受信したコマンドがコンソールに出力されますので、解析可能な信号であれば
     ボタンに対するcommand番号が判ります 以下は、command番号でしか識別していないので、リモコンが複数ある場合は、
     識別の為、メーカ識別や、識別アドレスなどで、分ける必要があります

     
    #include <IRremote.hpp>

    #define IR_RECEIVE_PIN      13
    //#define ENABLE_LED_FEEDBACK true

    void setup() {
      Serial.begin(115200);
      IrReceiver.begin(IR_RECEIVE_PIN);
    }
    int ccomand;
    void loop() {
      if (IrReceiver.decode()) {
        switch(IrReceiver.decodedIRData.command){
          case 0x1:
                  Serial.println("1がおされました");
                  break;
          case 0x2:        
                  Serial.println("2がおされました");
                  break;
          case 0x60:
                  Serial.println("音量大");
                  break;
          case 0x61:
                  Serial.println("音量小");
                  break;                        
        }
     
        IrReceiver.printIRResultShort(&Serial);
        Serial.println();

        IrReceiver.resume();
      }
    }


    ■設定データの保存について
     設定データは、保存したいので デフォルトのパーティションで割り当てられたSPIFFS領域を使うことにします
     Radikoのプログラムも選局データを保存していますが、保存処理を調べたのですが、どこで記述されているか
     判りませんでした SPIFFSは使ってなさそうで、おそらくnvs領域(EEPROM)に保存してるのではないかと推定
     SPIFFS領域への保存は、以下を参照願います

     ESP32 お便利関数


    ■時計処理
     内部時計を、インターネットのNTPサーバと同期させています
     参考にしたサイト ESP32/ESP8266でインターネット時刻と同期する | Program Resource



    作ったソースデータのっけようかとも思ったのですが、プログラムが大きいので見ても参考になりそうにない
    ので、割愛しました





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

   

    ご意見箱