ESP32はWiFiやBluetoothが使える高機能なボードです。I2S(Inter-IC Sound)というサウンドをデジタル通信できる機能も持っていて、I2S対応のマイクモジュールやアンプモジュールを接続してArduino IDEで制御することができます。
「ESP32のプログラムガイド」や「ESP32のI2Sマイク研究」、「I2Sマイク、ESP32、Arduino、SPH0645LM4H」などの記事を参考にしながら試してみました。
結論から書くと、マイクからの入力をイヤフォンで聞くことができましたが、音質がどうこうというレベルにはなっていません。タイムラグをまったく感じないのは今後に期待できるかもしれません。
興味のある方への参考と、自分のための備忘録
ESP32は「 MH-ET LIVE MiniKit」を使用しました。マイクは「Sipeed 1マイクモジュール」2個、アンプは「GY-PCM5102」を使用しました。
ESP32のI2Sは2本あり、入力か出力どちらかを選択できます。今回はI2S_0をマイク入力、I2S_1をアンプ出力に使います。それぞれバッファメモリが使えますので、マイクの入力バッファからデータを読んで、32ビット符号付整数に変換して、処理(たんなる掛け算)して、バイト配列に戻してから、アンプ出力のバッファに書き込みます。delay()を入れずに繰り返して呼び出していますが、アンプ出力を見る限りではバッファがうまく丸く収めてくれているようです。
マイクモジュールの配線
DA — IO18(1kΩでGNDに接続)
CK — IO23
LR — L:3.3V, R:GND
WS — IO19
V — 3.3V
G — GND
アンプモジュールの配線
SCK — GND
BCK — IO16
DIN — IO21
LCK — IO17
GND — GND
VIN — 3.3V
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 |
#include <driver/i2s.h> #define I2S_NUM_MIC I2S_NUM_0 #define I2S_PIN_CLK_MIC 23 #define I2S_PIN_WS_MIC 19 #define I2S_PIN_DOUT_MIC -1//not use #define I2S_PIN_DIN_MIC 18 #define I2S_NUM_AMP I2S_NUM_1 #define I2S_PIN_CLK_AMP 16 #define I2S_PIN_WS_AMP 17 #define I2S_PIN_DOUT_AMP 21 #define I2S_PIN_DIN_AMP -1//not use #define I2S_SAMPLE_RATE 44100 //44.1kHz #define I2S_BUFFER_COUNT 4 #define I2S_BUFFER_SIZE 512 #define Sound_LEN 512 uint8_t Mic_Buffer[I2S_BUFFER_SIZE]; // DMA転送バッファ uint8_t Sound[Sound_LEN]; // サウンドデータ int L_Data, R_Data; int Volume = 8; void setup() { Serial.begin(115200); i2sInit_MIC(); i2sInit_AMP(); Serial.println("MicModAmp02.ino"); } void loop() { mic2amp(); } void mic2amp(){ size_t transBytes; i2s_read(I2S_NUM_MIC, (char*)Mic_Buffer, I2S_BUFFER_SIZE, &transBytes, portMAX_DELAY);// Mic In //Convert 8 bytes data to L_Data and R_Data for(int i=0;i<transBytes;i=i+8){ for(int j=0;j<4;j++){ L_Data=L_Data<<8; L_Data=L_Data + Mic_Buffer[i+j]; } for(int j=4;j<8;j++){ R_Data=R_Data << 8; R_Data=R_Data + Mic_Buffer[i+j]; } //Process L_Data and R_Data L_Data=L_Data * Volume; R_Data=R_Data * Volume; //Convert to 8 bytes data for(int j=0;j<4;j++){ Sound[i+3-j]=(byte)(L_Data & 0xFF); L_Data=L_Data >> 8; } for(int j=0;j<4;j++){ Sound[i+7-j]=(byte)(R_Data & 0xFF); R_Data=R_Data >> 8; } } i2s_write(I2S_NUM_AMP, (char*)Sound, I2S_BUFFER_SIZE, &transBytes, portMAX_DELAY);// Speak Out } void i2sInit_MIC() { i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = I2S_SAMPLE_RATE, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //stereo .communication_format = I2S_COMM_FORMAT_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = I2S_BUFFER_COUNT, .dma_buf_len = I2S_BUFFER_SIZE, .use_apll = false, .tx_desc_auto_clear = false, .fixed_mclk = 0 }; i2s_pin_config_t pin_config = { .bck_io_num = I2S_PIN_CLK_MIC, .ws_io_num = I2S_PIN_WS_MIC, .data_out_num = I2S_PIN_DOUT_MIC, .data_in_num = I2S_PIN_DIN_MIC, }; i2s_driver_install(I2S_NUM_MIC, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_MIC, &pin_config); } void i2sInit_AMP() { i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), .sample_rate = I2S_SAMPLE_RATE, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //stereo .communication_format = I2S_COMM_FORMAT_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = I2S_BUFFER_COUNT, .dma_buf_len = I2S_BUFFER_SIZE, .use_apll = false, .tx_desc_auto_clear = false, .fixed_mclk = 0 }; i2s_pin_config_t pin_config = { .bck_io_num = I2S_PIN_CLK_AMP, .ws_io_num = I2S_PIN_WS_AMP, .data_out_num = I2S_PIN_DOUT_AMP, .data_in_num = I2S_PIN_DIN_AMP, }; i2s_driver_install(I2S_NUM_AMP, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_AMP, &pin_config); } |