メインコンテンツまでスキップ

reTerminal D1001 スピーカーの駆動


はじめに

このガイドでは、reTerminal D1001 開発ボード上の I2S スピーカーを駆動する方法を紹介します。システムアーキテクチャは、次の 3 つのコアコンポーネントで構成されています。

  • ESP32-P4: オーディオデータストリームを管理し、周辺機器の設定を制御するメインプロセッサです。
  • ES8311: デジタル I2S データをスピーカー用のアナログオーディオ信号に変換する、低消費電力モノラルオーディオコーデックです。
  • PCA9535: 電力増幅器のイネーブル状態を制御するために使用される I2C IO エキスパンダで、周辺機器制御用の柔軟な GPIO 拡張を提供します。

スピーカー構成ブロック図

オーディオシステムはデュアルバスアーキテクチャを採用しています。I2S バスは高速なデジタルオーディオデータ伝送専用であり、I2C バスはコーデックおよび IO エキスパンダの低速制御コマンドを処理します。

ピンアサインと動作原理

ESP32-P4 & ES8311(オーディオデータ & 制御)

Signal NameESP32-P4 PinFunction Description
I2C_SDAGPIO20シリアルデータ: ES8311 へ設定コマンド(音量、サンプルレート)を送信します。
I2C_SCLGPIO21シリアルクロック: I2C データ転送を同期します。
I2S_MCKGPIO33マスタークロック: コーデック内部のデルタシグマ変調器用の高周波基準クロックです。
I2S_BCKGPIO32ビットクロック: オーディオデータストリームの各ビットを同期します。
I2S_WSGPIO31ワードセレクト: LRCK とも呼ばれ、新しいオーディオフレームの開始を定義し、左/右チャンネルを選択します。
I2S_DOGPIO30データ出力: ESP32-P4 からコーデックへ再生用のデジタル PCM オーディオデータを送信します。
I2S_DIGPIO11データ入力: 将来のオーディオ録音やコーデックからのループバック用に予約されています。

ESP32-P4 & PCA9535RGER(GPIO 拡張)

Signal NameESP32-P4 PinFunction Description
I2C_SDAGPIO20PCA9535 IO エキスパンダを制御するために共有される I2C データバスです。
I2C_SCLGPIO21共有の I2C クロックバスです。
EN_PAEXP_GPO11PA イネーブル: PCA9535 上のピン P13 にマッピングされています。これを HIGH に設定すると外部パワーアンプが有効になります。

ソフトウェアフロー

GitHub サンプルリポジトリ

GitHub から公式の reTerminal D1001 リポジトリをダウンロードして、ソースコードとドライバを入手します。


ヒント

このスピーカーサンプル用の特定のソースコードとプロジェクトファイルを見つけるには、リポジトリ内の driver_examples/01_I2SCodec/ ディレクトリに移動してください。

開発実行シーケンス

Step 1. I2C IO エキスパンダ(PCA9535RGER)の初期化

外部パワーアンプ(PA)は PCA9535 エキスパンダ経由で制御されます。PA を有効にすることは非常に重要で、これを行わないと、たとえコーデックが正しく動作していてもスピーカーから音は出ません。

static esp_err_t pca9535_write_reg(uint8_t reg, uint8_t data)
{
uint8_t write_buf[2] = {reg, data};
return i2c_master_write_to_device(1, PCA9535_I2C_ADDR, write_buf, sizeof(write_buf), 1000 / portTICK_PERIOD_MS);
}

static void pca9535_init(void)
{
int i2c_master_port = 1; // Use I2C_NUM_1
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = MISC_I2C_SDA,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = MISC_I2C_SCL,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000,
};
i2c_param_config(i2c_master_port, &conf);
i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);

// Configure Port 0 and Port 1 as output mode (0 = output, 1 = input)
pca9535_write_reg(0x06, 0x00);
pca9535_write_reg(0x07, 0x00);

// Set P13 to HIGH to enable the Power Amplifier
pca9535_write_reg(0x02, 0x00);
pca9535_write_reg(0x03, 0x08);

ESP_LOGI(TAG, "PCA9535 initialized, P13 set to HIGH");
}

Step 2. I2S ドライバの設定

I2S は、デジタルオーディオ伝送専用に使用される同期式シリアル通信プロトコルです。ここでは ESP32-P4 を I2S マスターとして設定し、コーデックに BCLK と WS クロックを供給します。

static esp_err_t i2s_driver_init(void)
{
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER);
chan_cfg.auto_clear = true; // Prevents playing stale data from the buffer
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(EXAMPLE_SAMPLE_RATE),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
.gpio_cfg = {
.mclk = I2S_MCK_IO,
.bclk = I2S_BCK_IO,
.ws = I2S_WS_IO,
.dout = I2S_DO_IO,
.din = I2S_DI_IO,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
std_cfg.clk_cfg.mclk_multiple = EXAMPLE_MCLK_MULTIPLE;

ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));
ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));
return ESP_OK;
}

Step 3. ES8311 コーデックの初期化

ES8311 は、ESP32-P4 で定義した I2S 設定(サンプルレート、データ幅)に一致するように設定する必要があります。これは I2C バス経由で行います。プロジェクトをビルドする前に、main/example_config.h 内のマクロを変更することでスピーカーの動作をカスタマイズできます。

MacroDescriptionSetting Principles
EXAMPLE_SAMPLE_RATEオーディオサンプルレート(Hz)オーディオサンプルの周波数を定義します。一般的な値は 16000(音声)や 44100 / 48000(音楽)です。
EXAMPLE_MCLK_MULTIPLEMCLK と LRCLK の比率マスタークロック(MCLK)はサンプルレートの整数倍である必要があります。256 は 16 ビットで標準的ですが、高精度用には 384 がよく使用されます。
EXAMPLE_VOICE_VOLUME再生音量0 から 100 の範囲です。ES8311 コーデックの初期出力レベルを設定します。
EXAMPLE_RECV_BUF_SIZEDMA バッファサイズDMA が処理するデータチャンクのサイズを制御します。バッファを大きくすると音切れを防げますが、オーディオレイテンシが増加します。
static esp_err_t es8311_codec_init(void)
{
const i2c_config_t es_i2c_cfg = {
.sda_io_num = I2C_SDA_IO,
.scl_io_num = I2C_SCL_IO,
.mode = I2C_MODE_MASTER,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000,
};
i2c_param_config(I2C_NUM, &es_i2c_cfg);
i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0);

es8311_handle_t es_handle = es8311_create(I2C_NUM, ES8311_ADDRRES_0);
const es8311_clock_config_t es_clk = {
.mclk_inverted = false,
.sclk_inverted = false,
.mclk_from_mclk_pin = true,
.mclk_frequency = EXAMPLE_MCLK_FREQ_HZ,
.sample_frequency = EXAMPLE_SAMPLE_RATE
};

es8311_init(es_handle, &es_clk, ES8311_RESOLUTION_16, ES8311_RESOLUTION_16);
es8311_sample_frequency_config(es_handle, EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE, EXAMPLE_SAMPLE_RATE);
es8311_voice_volume_set(es_handle, EXAMPLE_VOICE_VOLUME, NULL);
es8311_microphone_config(es_handle, false);
return ESP_OK;
}

Step 4. メインエントリとタスク生成

メインアプリケーションは周辺機器を初期化した後、再生ロジックを専用の FreeRTOS タスクに引き渡します。

void app_main(void)
{
pca9535_init();

if (i2s_driver_init() != ESP_OK) {
ESP_LOGE(TAG, "i2s driver init failed");
abort();
}

if (es8311_codec_init() != ESP_OK) {
ESP_LOGE(TAG, "es8311 codec init failed");
abort();
}

xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL);
}

Step 5. DMA プリロードとデータ再生

DMA(Direct Memory Access) を使用すると、I2S ペリフェラルは CPU の介入なしにメモリから直接データを取得できます。DMA バッファのプリロードは、I2S ハードウェアが空のバッファから動作を開始し、急激な DC オフセット変化を引き起こすことで発生する「ポップノイズ」を防ぐための重要なテクニックです。

static void i2s_music(void *args)
{
esp_err_t ret = ESP_OK;
size_t bytes_write = 0;
uint8_t *data_ptr = (uint8_t *)music_pcm_start;

// Preload data to avoid initial "pop" sound
ESP_ERROR_CHECK(i2s_channel_disable(tx_handle));
ESP_ERROR_CHECK(i2s_channel_preload_data(tx_handle, data_ptr, music_pcm_end - data_ptr, &bytes_write));
data_ptr += bytes_write;

ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));
while (1) {
ret = i2s_channel_write(tx_handle, data_ptr, music_pcm_end - data_ptr, &bytes_write, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "[music] i2s write failed");
abort();
}
data_ptr = (uint8_t *)music_pcm_start; // Loop playback
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

トラブルシューティング

Q1: スピーカーから音が出ない

  • 確認: パワーアンプ(PA)が有効になっているか確認します。EN_PA 信号は PCA9535 IO エクスパンダの P13 ピンで制御されます。pca9535_init() が呼び出され、出力レジスタ(ポート 1、ビット 3)が正しく設定されていることを確認してください。
  • 確認: I2S 接続を確認し、TX チャンネルに対して i2s_channel_enable() 関数が呼び出されていることを確認します。

Q2: 音声が歪んでいる、またはパチパチとしたノイズが入る

  • 確認: I2S クロック構成(MCLK、BCLK、WS)が、使用している音声ファイルのサンプルレートと一致していることを確認します。EXAMPLE_SAMPLE_RATE が一致していないと、音程や再生速度に問題が発生する可能性があります。
  • 確認: ステップ 5 に示すように DMA のプリロードが実装されていることを確認します。プリロードは、空のバッファでチャンネルを開始することによって発生する「ポップ」音を防ぎます。

Q3: ES8311 または PCA9535 との I2C 通信が失敗する

  • 確認: I2C SDA(GPIO20)および SCL(GPIO21)の接続を確認します。これらのピンと競合する他のペリフェラルがないことを確認してください。
  • 確認: I2C アドレスが正しいことを確認します。PCA9535 は 0x20、ES8311 は 0x18 です。

技術サポート & 製品ディスカッション

Loading Comments...