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を施し上下に分けています。
| 固定リンク


コメント