[M5Stack Core2 for AWS] Arduinoでマイクの利用方法を確認してみました

2021.07.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

IoT事業部の平内(SIN)です。

今回は、Arduinoを使用してM5Stack Core2 for AWSでマイク入力の扱いを確認してみました。

最初に、動作確認している様子です。10秒間マイクの入力をSDカードに保存し、Audacityで再生しています。

マイクのデータ取得に関しては、下記のコードを参考にさせて頂きました。
https://github.com/m5stack/M5Core2/blob/master/examples/Basics/record/record.ino

サンプルで使用しているLEDの点灯やディスプレイ上のボタンについては、下記の記事をご参照ください。
[M5Stack Core2 for AWS] ArduinoでLED (Adafruit NeoPixel フルカラーLED) を点灯してみました
[M5Stack Core2 for AWS] Arduinoで仮想ボタンを作成してみました

2 I2S

SPM1423マイクは、I2Sで接続さています。

参考:https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2s.html

I2Sを初期化は、以下の通りです。

#define SAMPLE_RATE 16000 //サンプリングレート
#define CHUNK 1024 // I2Sバッファサイズ

i2s_config_t i2s_config = {
	.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
	.sample_rate = SAMPLE_RATE,
	.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
	.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
	.communication_format = I2S_COMM_FORMAT_I2S,
	.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
	.dma_buf_count = 2,
	.dma_buf_len = CHUNK
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

また、I2Sのピンの初期化は、次の通りです。

#define CONFIG_I2S_LRCK_PIN 0 // I2Sクロック
#define CONFIG_I2S_DATA_IN_PIN 34 // I2Sデータ

i2s_pin_config_t tx_pin_config = {
	.bck_io_num = I2S_PIN_NO_CHANGE,//未使用
	.ws_io_num = CONFIG_I2S_LRCK_PIN,
	.data_out_num = I2S_PIN_NO_CHANGE, // 未使用
	.data_in_num = CONFIG_I2S_DATA_IN_PIN
};
i2s_set_pin(I2S_NUM_0, &tx_pin_config);

上記の初期化を行った後は、i2s_read() でデータ取得が可能です。

i2s_read(I2S_NUM_0, buffer, CHUNK, &byte_read, (100 / portTICK_RATE_MS));

なお、マイクとスピーカーは、どちらもGPIO0を使用しているため、同時に利用できない事に注意が必要です。

3 Audacity

Audacityを使用すると、ヘッダ情報のついていないRAWデータを再生することができます。

M5Stack Core2 for AWSでSDカードに保存したRAWデータは、次のような指定で取り込んで再生しました。

  • エンコーディング: 16bit PCM
  • バイト順序: インディアンなし
  • チャンネル: 1チャンネル
  • サンプリング周波数: 16KHz

4 コード

コードは、以下の通りです。

ディスプレイ上のボタンをタップするとマイクのデータ取得が始まります。

M5Stack本体でデータ保存できるのは、100K前後で長時間の録音データを扱うことができないため、I2Sから取得したデータは、そのままSDカードに保存しています。

#include <M5Core2.h>
#include <driver/i2s.h>

#include "VButton.h"
#include "Led.h"

#define SAMPLE_RATE 16000 //サンプリングレート
#define CHUNK 1024 // I2Sバッファサイズ
#define PERIAD 10 // 録音時間(sec)

#define CONFIG_I2S_LRCK_PIN 0 // I2Sクロック
#define CONFIG_I2S_DATA_IN_PIN 34 // I2Sデータ

bool InitMic(){
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
        .communication_format = I2S_COMM_FORMAT_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 2,
        .dma_buf_len = CHUNK
    };
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

    i2s_pin_config_t tx_pin_config = {
      .bck_io_num = I2S_PIN_NO_CHANGE,//未使用
      .ws_io_num = CONFIG_I2S_LRCK_PIN,
      .data_out_num = I2S_PIN_NO_CHANGE, // 未使用
      .data_in_num = CONFIG_I2S_DATA_IN_PIN
    };
    i2s_set_pin(I2S_NUM_0, &tx_pin_config);
}

VButton *button;
Led *led;

void button_callback(char *title, bool use_toggle, bool is_toggled){
  led->set(255, 0, 0);

  File f = SD.open("/audio.dat", FILE_WRITE);
  if (f) {
    uint8_t buffer[CHUNK];
    size_t byte_read;
    
    // サンプリングレート * 16bit * 1ch * 録音時間 (bit数)
    // /8 (byte数)
    // /CHANK (chank数)
    int chank_max = (int)((SAMPLE_RATE*16*1*PERIAD)/8/CHUNK);

    for(int i=0; i < chank_max; i++){
      i2s_read(I2S_NUM_0, buffer, CHUNK, &byte_read, (100 / portTICK_RATE_MS));
      Serial.printf(".");
      f.write(buffer, CHUNK);
    }
    f.close();
  }
  led->set(0, 0, 0);
}

void setup() {
    M5.begin(true, true, true, true);
    M5.Lcd.setBrightness(200);
    M5.Lcd.fillScreen(WHITE);

    button = new VButton("REC", button_callback);
    led = new Led();
    InitMic();
}

void loop() {
    button->loop();
}

5 最後に

今回は、マイクの扱い方を確認してみました。次は、取得したRAWデータにヘッダをつけて、WAVファイルにしてみたいと考えています。

音楽は、フリーBGM・音楽素材MusMusを利用させて頂きました。

6 参考リンク


Visual Studio Code + PlatformIO 環境で M5Stack Core2 for AWS でHello Worldしてみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してLEDを光らせてみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してディスプレイに表示してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して仮想ボタンの動作を確認してみました
[M5Stack Core2 for AWS] LVCLを使用してディスプレイ上のボタンの動作を確認してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して電源を操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してスピーカーを操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して静電容量式タッチパネルを操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してジャイロセンサーを操作してみました
[M5Stack Core2 for AWS] PlatformIO を使用して、ArduinoでHello Worldしてみました
[M5Stack Core2 for AWS] ArduinoでLED (Adafruit NeoPixel フルカラーLED) を点灯してみました
[M5Stack Core2 for AWS] Arduinoで仮想ボタンを作成してみました
[M5Stack Core2 for AWS] ArduinoでMQTT接続してみました
[M5Stack Core2 for AWS] Arduinoでオーディオファイルを再生してみました
[M5Stack Core2 for AWS] Arduinoでマイクの利用方法を確認してみました
[M5Stack Core2 for AWS] ArduinoでGroveポートのGPIOを使用しててみました