espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.66k stars 7.41k forks source link

High noise on INMP441 output #6699

Closed Huyyuh2000 closed 2 years ago

Huyyuh2000 commented 2 years ago

Board

DOIT ESP32 Devkit V1, WEMOS LOLON32 Lite, Wemos D1 R32

Device Description

All hardware plain on breadboard

Hardware Configuration

INMP441_WS connected to D15 INMP441_SD connected to D13 INMP441_SCK connected to D2 INMP441_VDD connected to 3.3V Pin INMP441_GND connected to GND

Version

v2.0.2

IDE Name

Arduino IDE

Operating System

Windows 11 Home Single Language

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

115200

Description

Hello, I recorded .wav file using INMP441 and the data was able to process (noise was at acceptable level). At the moment, when I am recording for collect data, the noise is very high. I have change wire, dev kit and sensor but the result are the same. Here are the link that I save 2 recorded file. The low noise is before I meet the problem. I have read #3939 and follow some suggestion like soldering 10K between SD and GND but still not working.

Sketch

#include <driver/i2s.h>
#include <SPIFFS.h>

#define I2S_WS 15
#define I2S_SD 13
#define I2S_SCK 2
#define I2S_PORT I2S_NUM_0
#define I2S_SAMPLE_RATE   (16000)
#define I2S_SAMPLE_BITS   (16)
#define I2S_READ_LEN      (16 * 1024)
#define RECORD_TIME       (30) //Seconds
#define I2S_CHANNEL_NUM   (1)
#define FLASH_RECORD_SIZE (I2S_CHANNEL_NUM * I2S_SAMPLE_RATE * I2S_SAMPLE_BITS / 8 * RECORD_TIME)

File file;
const char filename[] = "/recording.wav";
const int headerSize = 44;

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);
  SPIFFSInit();
  i2sInit();
  xTaskCreate(i2s_adc, "i2s_adc", 1024 * 3, NULL, 1, NULL);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void SPIFFSInit(){
  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFS initialisation failed!");
    while(1) yield();
  }
  SPIFFS.remove("/test.wav");
  SPIFFS.remove(filename);
  file = SPIFFS.open(filename, FILE_WRITE);
  if(!file){
    Serial.println("File is not available!");
  }

  byte header[headerSize];
  wavHeader(header, FLASH_RECORD_SIZE);

  file.write(header, headerSize);
  listSPIFFS();
}

void i2sInit(){
  esp_err_t err;
  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_t(I2S_SAMPLE_BITS), 
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB),
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 1024,
    .use_apll = 1
  };

  err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
  if (err!=ESP_OK) {
    Serial.println("Failed to install driver");
  } else {
    Serial.println("Installed driver");
  }

  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
  };

  err = i2s_set_pin(I2S_PORT, &pin_config);
  if (err!=ESP_OK) {
    Serial.println("Failed to install pin");
  } else {
    Serial.println("Installed pin");
  }

}

void i2s_adc_data_scale(uint8_t * d_buff, uint8_t* s_buff, uint32_t len)
{
    uint32_t j = 0;
    uint32_t dac_value = 0;
    for (int i = 0; i < len; i += 2) {
        dac_value = ((((uint16_t) (s_buff[i + 1] & 0xf) << 8) | ((s_buff[i + 0]))));
        d_buff[j++] = 0;
        d_buff[j++] = dac_value * 256 / 2048;
    }
}

void i2s_adc(void *arg)
{
//    i2s_start(I2S_PORT);
    int i2s_read_len = I2S_READ_LEN;
    int flash_wr_size = 0;
    size_t bytes_read;

    char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
    uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));

    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
    i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);

    Serial.println(" *** Recording Start *** ");
    while (flash_wr_size < FLASH_RECORD_SIZE) {
        //read data from I2S bus, in this case, from ADC.
        i2s_read(I2S_PORT, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
        //example_disp_buf((uint8_t*) i2s_read_buff, 64);
        //save original data from I2S(ADC) into flash.
        i2s_adc_data_scale(flash_write_buff, (uint8_t*)i2s_read_buff, i2s_read_len);
        file.write((const byte*) flash_write_buff, i2s_read_len);
        flash_wr_size += i2s_read_len;
        ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
        ets_printf("Never Used Stack Size: %u\n", uxTaskGetStackHighWaterMark(NULL));
    }
    file.close();

    free(i2s_read_buff);
    i2s_read_buff = NULL;
    free(flash_write_buff);
    flash_write_buff = NULL;
//    Serial.println("Finish free memory");
    listSPIFFS();
//    Serial.println("Finish lissSPIFFS function");
//    i2s_stop(I2S_PORT);
    vTaskDelete(NULL);
}

void example_disp_buf(uint8_t* buf, int length)
{
    printf("======\n");
    for (int i = 0; i < length; i++) {
        printf("%02x ", buf[i]);
        if ((i + 1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("======\n");
}

void wavHeader(byte* header, int wavSize){
  header[0] = 'R';
  header[1] = 'I';
  header[2] = 'F';
  header[3] = 'F';
  unsigned int fileSize = wavSize + headerSize - 8;
  header[4] = (byte)(fileSize & 0xFF);
  header[5] = (byte)((fileSize >> 8) & 0xFF);
  header[6] = (byte)((fileSize >> 16) & 0xFF);
  header[7] = (byte)((fileSize >> 24) & 0xFF);
  header[8] = 'W';
  header[9] = 'A';
  header[10] = 'V';
  header[11] = 'E';
  header[12] = 'f';
  header[13] = 'm';
  header[14] = 't';
  header[15] = ' ';
  header[16] = 0x10;
  header[17] = 0x00;
  header[18] = 0x00;
  header[19] = 0x00;
  header[20] = 0x01;
  header[21] = 0x00;
  header[22] = 0x01;
  header[23] = 0x00;
  header[24] = 0x80;
  header[25] = 0x3E;
  header[26] = 0x00;
  header[27] = 0x00;
  header[28] = 0x00;
  header[29] = 0x7D;
  header[30] = 0x00;
  header[31] = 0x00;
  header[32] = 0x02;
  header[33] = 0x00;
  header[34] = 0x10;
  header[35] = 0x00;
  header[36] = 'd';
  header[37] = 'a';
  header[38] = 't';
  header[39] = 'a';
  header[40] = (byte)(wavSize & 0xFF);
  header[41] = (byte)((wavSize >> 8) & 0xFF);
  header[42] = (byte)((wavSize >> 16) & 0xFF);
  header[43] = (byte)((wavSize >> 24) & 0xFF);

}

void listSPIFFS(void) {
  Serial.println(F("\r\nListing SPIFFS files:"));
  static const char line[] PROGMEM =  "=================================================";

  Serial.println(FPSTR(line));
  Serial.println(F("  File name                              Size"));
  Serial.println(FPSTR(line));

  fs::File root = SPIFFS.open("/");
  if (!root) {
    Serial.println(F("Failed to open directory"));
    return;
  }
  if (!root.isDirectory()) {
    Serial.println(F("Not a directory"));
    return;
  }

  fs::File file = root.openNextFile();
  while (file) {

    if (file.isDirectory()) {
      Serial.print("DIR : ");
      String fileName = file.name();
      Serial.print(fileName);
    } else {
      String fileName = file.name();
      Serial.print("  " + fileName);
      // File path can be 31 characters maximum in SPIFFS
      int spaces = 33 - fileName.length(); // Tabulate nicely
      if (spaces < 1) spaces = 1;
      while (spaces--) Serial.print(" ");
      String fileSize = (String) file.size();
      spaces = 10 - fileSize.length(); // Tabulate nicely
      if (spaces < 1) spaces = 1;
      while (spaces--) Serial.print(" ");
      Serial.println(fileSize + " bytes");
    }

    file = root.openNextFile();
  }

  Serial.println(FPSTR(line));
  Serial.println();
  delay(1000);
}

Debug Message

None

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

Huyyuh2000 commented 2 years ago

@PilnyTomas Please help me. Thanks in advance.

PilnyTomas commented 2 years ago

Hi @Huyyuh2000, thanks for creating the issue. Let me understand some things:

Huyyuh2000 commented 2 years ago

Hi @PilnyTomas, I soldered all the pin header for each sensor by myself, I config sample rate is 16kHz, 16 bit depth and 1 channel so that 256kbps, I don't change anything, after recorded I thought It was ok so move to another part of my project. When I get back to compile everything, I meet this problem

PilnyTomas commented 2 years ago

How did you manage to set up 16 bit depth on the microphone? Can you please send a block diagram of the connection for the microphone + a photo from the bottom side of the board with the microphone?

Huyyuh2000 commented 2 years ago

Hi @PilnyTomas , About set up 16 bit depth, I config .bits_per_sample = i2s_bits_per_sample_t(I2S_SAMPLE_BITS) which I2S_SAMPLE_BITS is defined as (16). Here are all the things that you require: link

PilnyTomas commented 2 years ago

That is a setup in the ESP I2S module. My question was about the microphone. How do you know the microphone is outputting 16 bits per sample?

Huyyuh2000 commented 2 years ago

Sorry, I don't know, Is there any way to check the output of the microphone?

PilnyTomas commented 2 years ago

Usually, the first thing is to read the documentation for the chip you want to use. I don't know the chip you are using. Please read the documentation and let me know what setup the microphone expects.

Huyyuh2000 commented 2 years ago

The datasheet said that the microphone output is industry-standard 24-bit I²S interface. image

PilnyTomas commented 2 years ago

Cool. Is the picture from the documentation, because there is depicted 32 bit per sample format. Try setting up 24 and 32 to see which one works.

Huyyuh2000 commented 2 years ago

Hello, I tried change bit per sample and other parameters that come with it but there is still having noise. I found the reason why there a lot of noise was the L/R pin unconected. I watch some instructions and said that the sensor will auto set to ONLY_LEFT_CHANNEL if the pin is unconected. Seem like by unconecting the pin to Vdd or GND cause the problem.

aliyou-sn commented 1 year ago

Hello, please how do you solve this problem, i connect L\R pin to ground, I’m not getting any audio

CaptHigh commented 1 year ago

Hello, please how do you solve this problem, i connect L\R pin to ground, I’m not getting any audio

If You are using Arduino Framework with ESP32 then try connecting the L/R pin with GND and then set the input channel .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,

Using this approach worked for me, try the Left channel if the Right one doesn't work

Vegethalia commented 1 year ago

Hello, do you remember if changing the bits_x_sample from 16 to 24/32 made any difference for you?

I'm receiving audio samples without problems and the quality is good (using a very similar configuration of the I2S as the one shown in the 1st post), but the "volume" of the samples is extremely low: image The 4 "veritical lines" are 4 claps that I did just in front of the mic.

I don't know how to make it "louder".... of course I can "scale up" the signal, but the quality then is horrible.

Vegethalia commented 1 year ago

Ok I'll answer myself, just in case this serves someone else: The problem was that I had configured the I2S in 16 bit mode, and then I was only capturing the MSB of the bit stream. If I configured 24 bits, then the stream was garbled. The solution is to configure I2S in 32 bits mode and when reading, each sample takes 4 bytes and one must be discarted. Like this:

REAL_BYTES_X_SAMPLE=4;

i2s_read(I2S_NUM_0, (void*)dataOrig, buffSizeOrig, &bytesRead, portMAX_DELAY);
uint16_t samplesRead = bytesRead / REAL_BYTES_X_SAMPLE;
for (int i = 0; i < samplesRead; i++) {
    byteIndex = i * REAL_BYTES_X_SAMPLE;
    int32_t value = ((int32_t*)(dataOrig + byteIndex))[0]>>8;
}