Arduino入門

2. デバイス&サンプル

5. 拡張モジュール&サンプル

アクセサリー

6. アプリケーション

Module Audio Arduino 使用チュートリアル

1. 事前準備

2. 初期化設定

Module Audio は STM32 コントローラーを搭載し、ヘッドセットインターフェース規格の切り替え、LED 制御、ヘッドホン挿入検出(チャンネル 2 のみ)、マイク入力モード設定などの機能を提供します。

インターフェース規格の選択
ヘッドセットのインターフェース規格によってピン配置が異なります。互換性を確保するため、使用する機器に合わせて audio.setHPMode(AUDIO_HPMODE_NATIONAL); を呼び出し、OMTP(AUDIO_HPMODE_NATIONAL)または CTIA(AUDIO_HPMODE_AMERICAN)を選択してください。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#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);
}

3. 入力インターフェース設定

インターフェースの使用方法
Module Audio には 2 つの 3.5mm オーディオインターフェース(チャンネル 1 とチャンネル 2)があります。チャンネル 1 は 3.5mm TRS オーディオ端子からのマイク入力に使用します。チャンネル 2 は 3.5mm TRRS 複合オーディオ機器に対応し、TRS オーディオ端子とも互換性があります。
  • TRS オーディオ配線:MIC 入力をチャンネル 1、オーディオ出力をチャンネル 2 に接続します。PC 用ヘッドセットなど、マイクとオーディオ出力が分離された機器に適しています。
  • TRRS 複合オーディオ配線:複合オーディオ入出力機器をチャンネル 2 に接続します。マイク付き有線ヘッドセットに対応し、TRS オーディオ機器とも互換性があります。

初期化後、以下の API を呼び出して、入出力チャンネル、音量、ゲインなどのパラメーターを設定します。

cpp
1 2 3 4 5 6 7 8 9 10 11 12
// 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);

4. 録音と再生

TRS 配線を使用し、MIC 入力をチャンネル 1、オーディオ出力をチャンネル 2 に接続して、マイク入力データをリアルタイムで取得して再生します。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#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);
    }
}

5. microSD の WAV ファイル再生

チャンネル 2 をオーディオ出力として設定し、microSD カードに保存された WAV ファイルを読み込んで再生します。使用前に WAV ファイルを microSD カードへ保存し、コントローラーのカードスロットに挿入してください。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
#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);
    }
}

6. RGB LED 制御

Module Audio の側面には 3 個のプログラマブル RGB LED が搭載されています。以下の例を参考に制御できます。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#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);
}
Page Tools
PDF
On This Page