1. 環境設定:Arduino IDE 入門チュートリアルを参照して IDE をインストールし、使用するコントローラーに対応するボードパッケージと必要なドライバライブラリをインストールします。
2. 使用するドライバライブラリ:
3. 使用するハードウェア:


Module Audio は STM32 コントローラーを搭載し、ヘッドセットインターフェース規格の切り替え、LED 制御、ヘッドホン挿入検出(チャンネル 2 のみ)、マイク入力モード設定などの機能を提供します。
audio.setHPMode(AUDIO_HPMODE_NATIONAL); を呼び出し、OMTP(AUDIO_HPMODE_NATIONAL)または CTIA(AUDIO_HPMODE_AMERICAN)を選択してください。
#include <M5Unified.h>
#include <M5Module_Audio.h>
M5ModuleAudio audio;
void setup()
{
// Initialize M5Unified without the built-in audio devices.
auto cfg = M5.config();
cfg.serial_baudrate = 115200;
cfg.internal_mic = false;
cfg.internal_spk = false;
M5.begin(cfg);
if (!audio.begin(Wire)) {
Serial.println("Module Audio not found.");
while (true) {
delay(1000);
}
}
audio.setHPMode(AUDIO_HPMODE_NATIONAL);
// audio.setHPMode(AUDIO_HPMODE_AMERICAN);
audio.setMICStatus(AUDIO_MIC_OPEN);
audio.setRGBBrightness(100);
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, 0x0000FF);
}
}
void loop()
{
M5.update();
bool is_hp_inserted = audio.getHPInsertStatus();
if (is_hp_inserted) {
Serial.println("Headphone Inserted");
} else {
Serial.println("Headphone Removed");
}
delay(500);
}
初期化後、以下の API を呼び出して、入出力チャンネル、音量、ゲインなどのパラメーターを設定します。
// Use input 1 for both channels.
audio.setMicInputLine(ADC_INPUT_LINPUT1_RINPUT1);
// Use input 2 for both channels.
// audio.setMicInputLine(ADC_INPUT_LINPUT2_RINPUT2);
audio.setSpeakerOutput(DAC_OUTPUT_OUT1);
audio.setMicAdcVolume(100);
audio.setSpeakerVolume(40);
audio.setMicGain(MIC_GAIN_24DB);
audio.setBitsSample(ES_MODULE_ADC, BIT_LENGTH_16BITS);
audio.setSampleRate(SAMPLE_RATE_44K);TRS 配線を使用し、MIC 入力をチャンネル 1、オーディオ出力をチャンネル 2 に接続して、マイク入力データをリアルタイムで取得して再生します。
#include <M5Unified.h>
#include <M5Module_Audio.h>
M5ModuleAudio audio;
static constexpr size_t AUDIO_BUFFER_SIZE = 512;
static uint8_t audio_buffer[AUDIO_BUFFER_SIZE];
void setup()
{
// Initialize M5Unified without the built-in audio devices.
auto cfg = M5.config();
cfg.serial_baudrate = 115200;
cfg.internal_mic = false;
cfg.internal_spk = false;
M5.begin(cfg);
// Initialize Module Audio on the internal I2C bus.
if (!audio.begin(M5.In_I2C)) {
Serial.println("Module Audio not found.");
while (true) {
delay(1000);
}
}
// Configure the Module Audio controller.
audio.setHPMode(AUDIO_HPMODE_NATIONAL);
audio.setMICStatus(AUDIO_MIC_OPEN);
audio.setRGBBrightness(100);
Serial.printf("HP mode: %d\n", audio.getHPMode());
Serial.printf("MIC status: %d\n", audio.getMICStatus());
// Set the status LEDs.
const uint32_t colors[] = {
0x00FF00,
0xFFFF00,
0xFFFFFF,
};
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, colors[i]);
Serial.printf(
"RGB-%u: set=%06X, read=%06X\n",
i,
static_cast<unsigned>(colors[i]),
static_cast<unsigned>(audio.getRGBLED(i)));
}
// Configure ES8388 for microphone loopback.
audio.setMicInputLine(ADC_INPUT_LINPUT2_RINPUT2);
audio.setMicGain(MIC_GAIN_24DB);
audio.setMicAdcVolume(100);
audio.setSpeakerVolume(40);
audio.setSpeakerOutput(DAC_OUTPUT_OUT1);
audio.setBitsSample(
ES_MODULE_ADC_DAC,
BIT_LENGTH_16BITS);
audio.setSampleRate(SAMPLE_RATE_44K);
// Print the ES8388 register values.
Serial.println("Read ES8388 registers:");
uint8_t* registers = audio.readAllReg();
if (registers != nullptr) {
for (uint8_t i = 0; i < 53; ++i) {
Serial.printf(
"Reg-%02u = 0x%02X\r\n",
i,
registers[i]);
}
}
Serial.println("Audio loopback started.");
}
void loop()
{
M5.update();
// Capture one audio buffer.
if (!audio.record(audio_buffer, sizeof(audio_buffer))) {
Serial.println("Audio record failed.");
delay(100);
return;
}
// Play the captured audio buffer.
if (!audio.play(audio_buffer, sizeof(audio_buffer))) {
Serial.println("Audio playback failed.");
delay(100);
}
}チャンネル 2 をオーディオ出力として設定し、microSD カードに保存された WAV ファイルを読み込んで再生します。使用前に WAV ファイルを microSD カードへ保存し、コントローラーのカードスロットに挿入してください。
#include <M5Unified.h>
#include <M5Module_Audio.h>
#include <SPI.h>
#include <SD.h>
M5ModuleAudio audio;
File wav_file;
static constexpr char WAV_PATH[] = "/hello.wav";
static constexpr size_t WAV_HEADER_SIZE = 44;
static constexpr size_t AUDIO_BUFFER_SIZE = 1024;
static uint8_t audio_buffer[AUDIO_BUFFER_SIZE];
bool openWavFile()
{
if (wav_file) {
wav_file.close();
}
wav_file = SD.open(WAV_PATH, FILE_READ);
if (!wav_file) {
Serial.printf("Failed to open %s\n", WAV_PATH);
return false;
}
if (wav_file.size() <= WAV_HEADER_SIZE) {
Serial.println("Invalid or empty WAV file.");
wav_file.close();
return false;
}
Serial.printf(
"WAV file size: %u bytes\n",
static_cast<unsigned>(wav_file.size()));
if (!wav_file.seek(WAV_HEADER_SIZE)) {
Serial.println("Failed to skip WAV header.");
wav_file.close();
return false;
}
return true;
}
void setup()
{
auto cfg = M5.config();
cfg.serial_baudrate = 115200;
cfg.internal_mic = false;
cfg.internal_spk = false;
M5.begin(cfg);
Serial.printf(
"Detected board: %d\n",
static_cast<int>(M5.getBoard()));
if (!audio.begin(M5.In_I2C)) {
Serial.println("Module Audio not found.");
while (true) {
delay(1000);
}
}
audio.setHPMode(AUDIO_HPMODE_NATIONAL);
audio.setMICStatus(AUDIO_MIC_OPEN);
audio.setRGBBrightness(100);
Serial.printf("HP mode: %d\n", audio.getHPMode());
Serial.printf("MIC status: %d\n", audio.getMICStatus());
const uint32_t colors[] = {
0x00FF00,
0xFFFF00,
0xFFFFFF,
};
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, colors[i]);
Serial.printf(
"RGB-%u: set=%06X, read=%06X\n",
i,
static_cast<unsigned>(colors[i]),
static_cast<unsigned>(audio.getRGBLED(i)));
}
// M5ModuleAudio has already initialized ES8388.
audio.setMicAdcVolume(100);
audio.setSpeakerVolume(80);
audio.setSpeakerOutput(DAC_OUTPUT_OUT1);
audio.setBitsSample(
ES_MODULE_ADC_DAC,
BIT_LENGTH_16BITS);
audio.setSampleRate(SAMPLE_RATE_44K);
Serial.println("Read ES8388 registers:");
uint8_t* registers = audio.readAllReg();
if (registers != nullptr) {
for (uint8_t i = 0; i < 53; ++i) {
Serial.printf(
"Reg-%02u = 0x%02X\r\n",
i,
registers[i]);
}
}
// Get the SD SPI pins for the detected board.
int sd_sclk = M5.getPin(m5::pin_name_t::sd_spi_sclk);
int sd_miso = M5.getPin(m5::pin_name_t::sd_spi_miso);
int sd_mosi = M5.getPin(m5::pin_name_t::sd_spi_mosi);
int sd_cs = M5.getPin(m5::pin_name_t::sd_spi_cs);
Serial.printf("SD SPI: SCLK=%d, MISO=%d, MOSI=%d, CS=%d\n", sd_sclk, sd_miso, sd_mosi, sd_cs);
SPI.begin(sd_sclk, sd_miso, sd_mosi, sd_cs);
if (!SD.begin(sd_cs, SPI, 25000000)) {
Serial.println("Failed to initialize SD card.");
while (true) {
delay(1000);
}
}
Serial.println("SD card initialized successfully.");
if (!openWavFile()) {
while (true) {
delay(1000);
}
}
Serial.println("WAV playback started.");
}
void loop()
{
M5.update();
if (!wav_file) {
delay(100);
return;
}
// Restart playback at the beginning of the audio data.
if (wav_file.available() == 0) {
if (!wav_file.seek(WAV_HEADER_SIZE)) {
Serial.println("Failed to restart WAV file.");
delay(100);
}
return;
}
size_t bytes_read =
wav_file.read(audio_buffer, sizeof(audio_buffer));
if (bytes_read == 0) {
return;
}
if (!audio.play(audio_buffer, bytes_read)) {
Serial.println("I2S write failed.");
delay(100);
}
}Module Audio の側面には 3 個のプログラマブル RGB LED が搭載されています。以下の例を参考に制御できます。
#include <M5Unified.h>
#include <M5Module_Audio.h>
M5ModuleAudio audio;
void setup()
{
auto cfg = M5.config();
cfg.serial_baudrate = 115200;
cfg.internal_mic = false;
cfg.internal_spk = false;
M5.begin(cfg);
if (!audio.begin(M5.In_I2C)) {
Serial.println("Module Audio not found.");
while (true) {
delay(1000);
}
}
audio.setRGBBrightness(100);
Serial.println("Module Audio initialized successfully.");
}
void loop()
{
M5.update();
// Cycle all LEDs through red, green, and blue.
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, 0xFF0000);
}
delay(1000);
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, 0x00FF00);
}
delay(1000);
for (uint8_t i = 0; i < 3; ++i) {
audio.setRGBLED(i, 0x0000FF);
}
delay(1000);
}