ESP32 I2S ile Ses Kaydetme

12 Oca 2022

I2S Nedir?


I2S, ses veri aktarımı için geliştirilmiş bir seri protokoldür. Philips tarafından geliştirilen bu protokol, dijital ses verilerini bir mikrodenetleyici, DSP (Digital Signal Processor) veya başka bir dijital ses cihazı ile DAC (Digital-to-Analog Converter) veya ADC (Analog-to-Digital Converter) gibi ses cihazları arasında iletmek için kullanılır.

I2S'nin temel avantajlarından biri, dijital ses sinyallerini eş zamanlı olarak iletebilmesi ve bu sayede yüksek kaliteli ses işleme uygulamalarında kullanılabilmesidir. I2S, özellikle düşük gecikme ve yüksek doğruluk gerektiren uygulamalarda tercih edilir.

ESP32 Üzerinde I2S Kullanarak Ses Kaydı


Mikrofon Seçimi


I2S protokolünü destekleyen bir mikrofon seçmek önemlidir. Genellikle, bu tür mikrofonlar dijital MEMS mikrofonları olarak adlandırılır. Bu mikrofonlar, ses sinyallerini PCM veya PDM formatına dönüştürerek ESP32'ye gönderir. Piyasada INMP441 ve Adafruit PDM mikrofon modülü rahatlıkla bulunabilmektedir. Bu iki mikrofon da benzer kalitede ses sağlar.

Mikrofonları tanıdığımıza göre bağlantı şemasına geçelim. İki mikrofon da benzer bağlantılara sahip.

SCK veye CLK: Mikrofona gelen saat sinyalidir.

SD veya DAT : Mikrofondan mikrokontrolcüye giden veri.

WS (LRCLK): Sağ ve Sol kanal Seçici Pin (Bu sinyal 0 değerindeyken ses sol kanala, 1 değerindeyken sağ kanala kaydedilir.)

SEL veya L/R: Mikrofonun hangi kanala ses vereceğini belirler. Bu pin 0 a (GND) bağlıyken sol kanala, 1'e bağlıyken (VCC) sağ kanala ses gönderilir.

INMP441 için bağlantı şeması

Adafruit PDM Mikrofon için bağlantı şeması

Farklı mikrofon modülleri farklı i2s ayarlarıyla çalışmakta. Bu nedenle aşağıda iki farklı mikrofon için kodu bulabilirsiniz. Bu kod mikrofondan veriyi alıp serial monitör üzerinden göstermeye yaramaktadır. Bu kod sayesinde mikrofonları bağlayıp belirlediğiniz ayarlarda mikrofonun çalışıp çalışmadığını kontrol edebilirsiniz. Sonraki yazılarda sesin wav dosyası olarak kaydedilmesini ele alacağız.

// INMP441  mikrofon modülü için ses alma kodu

#include <driver/i2s.h>

#define I2S_WS 33
#define I2S_SD 32
#define I2S_SCK 25

#define I2S_PORT I2S_NUM_0

#define bufferLen 1024
int16_t sBuffer[bufferLen];
 
void i2s_install() {

  const i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 16,
    .dma_buf_len = 1024,
    .use_apll = false
  };
 
  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
 
void i2s_setpin() {

  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };
 
  i2s_set_pin(I2S_PORT, &pin_config);
}
 
void setup() {

  Serial.begin(115200);
  Serial.println(" ");
 
  delay(1000);
 
  i2s_install();
  i2s_setpin();
  i2s_start(I2S_PORT);
 
  delay(500);
}
 
void loop() {
 

  int rangelimit = 3000;
  Serial.print(rangelimit * -1);
  Serial.print(" ");
  Serial.print(rangelimit);
  Serial.print(" ");

  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);
 
  if (result == ESP_OK)
  {

    int16_t samples_read = bytesIn / 8;
    if (samples_read > 0) {
      float mean = 0;
      for (int16_t i = 0; i < samples_read; ++i) {
        mean += (sBuffer[i]);
      }

      mean /= samples_read;

      Serial.println(mean);
    }
  }
}
// Adafruit PDM mikrofon için ses alma kodu

#include <driver/i2s.h>

#define I2S_WS 33
#define I2S_SD 32
#define I2S_SCK 25

#define I2S_PORT I2S_NUM_0

#define bufferLen 1024
int16_t sBuffer[bufferLen];
 
void i2s_install() {

  const i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 16,
    .dma_buf_len = 1024,
    .use_apll = false
  };
 
  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
 
void i2s_setpin() {

  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };
 
  i2s_set_pin(I2S_PORT, &pin_config);
}
 
void setup() {

  Serial.begin(115200);
  Serial.println(" ");
 
  delay(1000);
 
  i2s_install();
  i2s_setpin();
  i2s_start(I2S_PORT);
 
  delay(500);
}
 
void loop() {
 

  int rangelimit = 3000;
  Serial.print(rangelimit * -1);
  Serial.print(" ");
  Serial.print(rangelimit);
  Serial.print(" ");

  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);
 
  if (result == ESP_OK)
  {

    int16_t samples_read = bytesIn / 8;
    if (samples_read > 0) {
      float mean = 0;
      for (int16_t i = 0; i < samples_read; ++i) {
        mean += (sBuffer[i]);
      }

      mean /= samples_read;

      Serial.println(mean);
    }
  }
}

© Copyright 2023. All rights Reserved.