I2Sマイク、ESP32、Arduino、SPH0645LM4H
I2Sマイク、ESP32、Arduino、プロット
I2Sマイクロフォンモジュール
- SPH0645LM4H搭載 I2S MEMSマイクモジュール
- ESP32 DevKitC ESP-WROOM-32
- Arduino-IDE+ Arduino core for the ESP32
- ツール⇒シリアルプロッタ
Sketch(C++ライクのArduinoのコンパイラ言語)を以下に載せます。
// I2SmicPlot.ino #include <driver/i2s.h> const i2s_port_t I2S_PORT = I2S_NUM_0; const i2s_config_t i2s_config = { .mode =i2s_mode_t(I2S_MODE_MASTER|I2S_MODE_RX), .sample_rate =16000, // サンプリング 16kHz .bits_per_sample =I2S_BITS_PER_SAMPLE_32BIT, // 32bit以外不可 .channel_format =I2S_CHANNEL_FMT_RIGHT_LEFT, // ステレオ .communication_format=I2S_COMM_FORMAT_PCM, // PCM .intr_alloc_flags =ESP_INTR_FLAG_LEVEL1, // Interrupt level 1 .dma_buf_count =4, // number of buffers .dma_buf_len =8 // 8 samples per buffer }; const i2s_pin_config_t pin_config = { .bck_io_num = 25, // BCLK .ws_io_num = 27, // LRCL .data_out_num = -1, // マイクでは使わない .data_in_num = 26 // DOUT }; const static int val_shift = 13; // ボリューム調整 const static int val_offset= 14000; // 0点補正 void setup() { Serial.begin(115200); Serial.println("Configuring I2S..."); esp_err_t _err; _err = i2s_driver_install(I2S_PORT,&i2s_config, 0, NULL); if (_err != ESP_OK) { Serial.printf("Failed installing driver: %d\n", _err); while (true); } _err = i2s_set_pin(I2S_PORT, &pin_config); if (_err != ESP_OK) { Serial.printf("Failed setting pin: %d\n", _err); while (true); } Serial.println("I2S driver installed."); } void loop() { int32_t _samples[2]; // ここにデータ(1サンプル左右それぞれ32bit) size_t _num_bytes_read;// ここに読み込んだ長さ esp_err_t _err = i2s_read(I2S_PORT ,(char *)_samples ,8 // 要素数ではなくバイト数 ,&_num_bytes_read ,portMAX_DELAY); // no timeout if ( _err==ESP_OK && _num_bytes_read ==8 ) { int16_t _vR = (_samples[0]>>val_shift)+val_offset + 8000; int16_t _vL = (_samples[1]>>val_shift)+val_offset - 8000; Serial.print(_vR);Serial.print(","),Serial.println(_vL);// プロッタへ } }
これは Using an I2S MEMS microphone on an ESP32 のexamples/InputSerialPlotterのコードを少しだけ手直ししたものです。
モジュール

SPH0645LM4H搭載 I2S MEMSマイクモジュールです。
小さな基板上にマイクも組まれています。
基板面のPort⇒◎の丸穴がマイクの穴です。
底面にならないように気を付ける必要があります。
接続

汎用入出力PINであればどれでも大丈夫です。
2台のCRCL,DOUT,BCLKはそれぞれ同一PINに接続します。
SELはR/Lの選択でRをGNDにLを3Vに接続します。
基本アクセス
I2S入力装置への基本アクセスは次のように行います。
i2s_driver_install()でアクセス仕様を設定し、
i2s_set_pin()でピンアサインを行い
i2s_read()でデータを取得する。
オーディオデータはDMA転送でメモリ上にセットされます。
DMAメモリからi2s_read()で取り込みます。i2s_pop_sample()で取り込むことも可能です。
i2s_readがデータが得られるまでブロックするかどうか調査中です。
i2s_driver_installでstartしますので、別途startを呼ぶ必要は有りません。
ピンアサインがstartの後というのが少し気になりますが、逆では動きませんでした。
ステレオ
2個のI2Sマイクは[SEL]をGNDに接続するとR,VCCに接続するとLと解釈され一つのstreamの中に交互に取り込まれます。
channel_formatにI2S_CHANNEL_FMT_RIGHT_LEFTを設定すると、R/Lの順にデータが得られます。
片チャネルの1サンプルは32ビット(4バイト)固定です。
i2s_readで2個分(8バイト)ずつ取得することでR/Lのデータを得ています。
データフォーマット
1サンプルは32bit固定です。
値の形式は残念ながら良く分かっていません。
今回は13bit右にシフトし、14000を加える事により16bitの符号付きPCMデータを得ています。
+8000/-8000はプロットを上下に分けるためだけに加えたものです。
プロット
ArduinoのSerial.print()は「ツール⇒シリアルモニタ」へのテキスト出力の他、数値を出力する場合 「ツール⇒シリアルプロッタ」にグラフとしてプロットすることも出来ます。

カンマで2値を繋げば2本のプロット出力が得られます。
今回は2値に+8000/-8000を施し上下に分けています。
| 固定リンク
コメント