RDA5708M FMラジオ

FMラジオにはまり RDA5708M で作ってみました。構成 XAIO ESP32C3 GC9A01 RDA5708M

プログラムはAIにお願いしました。

#include <Wire.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <RDA5807.h>
#include <AiEsp32RotaryEncoder.h> // ロータリーエンコーダ用ライブラリ

// ピン定義
#define I2C_SDA 6
#define I2C_SCL 7

#define ROTARY_ENCODER_A_PIN 20
#define ROTARY_ENCODER_B_PIN  21
#define ROTARY_ENCODER_BUTTON_PIN  5
#define ROTARY_ENCODER_VCC_PIN -1 // VCCは3.3Vピンから直接取るため無効化
#define ROTARY_ENCODER_STEPS   4  // エンコーダのステップ数(通常は4)

// インスタンス作成
TFT_eSPI tft = TFT_eSPI(); 
RDA5807 rx;
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);

uint16_t currentFrequency = 8000; // 80.0 MHz
uint8_t currentVolume = 1;        // 0 - 15
bool isTuneMode = true;           // true:選局モード, false:音量モード

// エンコーダの値を読み取る割り込みハンドラ
void IRAM_ATTR readEncoderISR() {
  rotaryEncoder.readEncoder_ISR();  
  rotaryEncoder.begin(); // 有効化
}

void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL);

  // 1. ロータリーエンコーダの初期化
  rotaryEncoder.begin();
  rotaryEncoder.setup(readEncoderISR);
 
  rotaryEncoder.setAcceleration(0); // 加速無効(1クリックずつ確実に動かす)
  
  // 初期状態(選局モード)の範囲を設定
  // 日本のFM(76.0〜108.0MHz)を100kHz刻みで制御するため、760〜1080の範囲にする
  rotaryEncoder.setBoundaries(760, 1080, true); 
  rotaryEncoder.setEncoderValue(currentFrequency / 10);

  // 2. ラジオの初期化
  rx.setup();
  rx.setBand(RDA_FM_BAND_JAPAN_WIDE); 
  rx.setVolume(currentVolume);
  rx.setFrequency(currentFrequency); 

  // 3. ディスプレイの初期化
  tft.init();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.drawCentreString("XIAO FM RADIO", 120, 30, 2);

  updateDisplay();
}

void loop() {
  // スイッチのワンプッシュを検出
  if (rotaryEncoder.isEncoderButtonClicked()) {
    isTuneMode = !isTuneMode; // モード切り替え

    if (isTuneMode) {
      // 選局モードに切り替え:範囲を 760〜1080 に設定
      rotaryEncoder.setBoundaries(760, 1080, true);
      rotaryEncoder.setEncoderValue(currentFrequency / 10);
    } else {
      // 音量モードに切り替え:範囲を 0〜15 に設定
      rotaryEncoder.setBoundaries(0, 15, false);
      rotaryEncoder.setEncoderValue(currentVolume);
    }
    updateDisplay();
  }

  // 回転を検出
  if (rotaryEncoder.encoderChanged()) {
    //long encoderValue = AiEsp32RotaryEncoder::readEncoderValue()();
     long encoderValue = rotaryEncoder.readEncoder(); // ライブラリの標準的な関数名

    if (isTuneMode) {
      currentFrequency = encoderValue * 10; // 10倍して実際の周波数(kHz)にする
      rx.setFrequency(currentFrequency);
    } else {
      currentVolume = encoderValue;
      rx.setVolume(currentVolume);
    }
    updateDisplay();
  }
}

// 画面表示の更新(文字サイズ拡大版)
void updateDisplay() {
  // --- モード表示 ---
  // フォントを 2 から 4 に拡大(高さが約26pxになるため、塗りつぶし高さを 35 に変更)
  tft.fillRect(20, 65, 200, 35, TFT_BLACK); 
  if (isTuneMode) {
    tft.setTextColor(TFT_YELLOW, TFT_BLACK);
    tft.drawCentreString("[ TUNE MODE ]", 120, 65, 4);  // フォント2 -> 4
  } else {
    tft.setTextColor(TFT_CYAN, TFT_BLACK);
    tft.drawCentreString("[ VOL MODE ]", 120, 65, 4);   // フォント2 -> 4
  }

  // --- 周波数表示 ---
  // フォントを 4 から 6(または7)に拡大。ここでは非常に見やすい「6」に設定
  // 文字が大きくなるため、塗りつぶし位置と高さを調整(Y軸: 110 -> 115、高さ: 40 -> 50)
  tft.fillRect(10, 115, 220, 50, TFT_BLACK);
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  float freqMHz = currentFrequency / 100.0;
  tft.drawCentreString(String(freqMHz, 1) + " MHz", 120, 115, 6);   // フォント4 -> 6

   // 「MHz」の単位を少し小さめのフォント4で数字の右側(X=190)に配置
  tft.setTextColor(TFT_GREEN, TFT_BLACK);
  tft.drawString("MHz", 150, 132, 4); // Y座標を少し下げて数字のベースラインに合わせる

  // --- 音量表示 ---
  // フォントを 2 から 4 に拡大(Y軸: 160 -> 180 に下げて周波数との重なりを防止、高さ: 35)
  tft.fillRect(20, 180, 200, 35, TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.drawCentreString("Volume: " + String(currentVolume), 120, 180, 4); // フォント2 -> 4
}

いろいろ問題がありましたがなんとか音がでるようになりました。

ロータリーエンコーダの回転に動作が追い付かずゆっくり回転させるかFM局の周波数に合わせなければなりません。
ちょっと不便ですが対応方法がわかりませんのでこれで良しとします。

コメント