« 忘れるな!フォルダ名指差喚呼 | トップページ | ◆静止視力と動体視力とハトの首 »

I2Sマイク、ESP32、Arduino、SPH0645LM4H

 I2Sマイク、ESP32、Arduino、プロット

I2Sマイクロフォンモジュール

  • SPH0645LM4H搭載 I2S MEMSマイクモジュール
2個を
  • 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を施し上下に分けています。

|

« 忘れるな!フォルダ名指差喚呼 | トップページ | ◆静止視力と動体視力とハトの首 »

コメント

コメントを書く



(ウェブ上には掲載しません)




« 忘れるな!フォルダ名指差喚呼 | トップページ | ◆静止視力と動体視力とハトの首 »