espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.66k stars 7.29k forks source link

I2S mic not working since 4.4 (IDFGH-8138) #9635

Closed MikeBailleul closed 1 year ago

MikeBailleul commented 2 years ago

Answers checklist.

IDF version.

v4.4

Operating System used.

macOS

How did you build your project?

VS Code IDE

If you are using Windows, please specify command line type.

No response

Development Kit.

ESP32 Dev Module

Power Supply used.

USB

What is the expected behavior?

Using this sketch: https://github.com/atomic14/esp32-i2s-mic-test/blob/main/i2s_mic_test/i2s_mic_test.ino With a INMP441 configured as follow: WS -> 25 SCK -> 32 SD -> 33 L/R -> GND GND -> GND VDD -> 3.3V

It should output values of the sound received by the mic.

What is the actual behavior?

Only 0 values

Steps to reproduce.

I originally submitted an issue here: https://github.com/espressif/arduino-esp32/issues/7177 But I was redirected to esp-idf since it appears to be related to it.

A brief summary:

In platformio.ini, this does NOT work because it is using the latest release of arduino-esp32

platform = espressif32

By changing it to this, it works as intended

platform = espressif32@5.0.0

Later we discovered this commit in arduino-esp32 repo is where it stops to work normally

platform = espressif32
platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#666c66d3d1c7437aaebaaadf2084927b7fc476c4

Debug Logs.

No response

More Information.

No response

happychriss commented 2 years ago

Thanks for raising this, I am having the same issue - also with Tasmota image: It seems to have stopped between 4.4.0 and 4.4.3

Working: platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip framework-espidf @ 3.40400.0 (4.4.0)

Not workingt: platform = https://github.com/tasmota/platform-espressif32 framework-espidf @ 3.40403.0 (4.4.3)

I am using the following I2S Config: ` i2s_config_t i2s_config_micro = { .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = 16000,

        //  The data word size is set at 32 bits and "I2S_PHILIPS_MODE" format. So a single stereo frame consists of two 32-bit PCM words or 8 bytes.
        //  The actual PCM audio data is 24 bits wide, is signed and is stored in little-endian format with 8 bits of left-justified 0 "padding".
        .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,

        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // was I2S_CHANNEL_FMT_RIGHT_LEFT
        .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S),
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 4,
        .dma_buf_len = 1024,
        .use_apll = false,
        .tx_desc_auto_clear = false,
        .fixed_mclk = 0
};`
L-KAYA commented 2 years ago

I've tried on the latest release/v4.4 branch, it works well now, this bug(only_lefthas no sound) should has already been fixed in commit 56a89b920dcf47c7c1d34cbd00ff745ffd7b3246.

MikeBailleul commented 2 years ago

How do I test for a specific commit of the IDF? Is this the right way in platform.ini?

platform = espressif32
platform_packages = framework-espidf @ https://github.com/espressif/esp-idf.git#56a89b920dcf47c7c1d34cbd00ff745ffd7b3246

If yes, it does not work for me. I receive only NaN values from the mic.

L-KAYA commented 2 years ago

Maybe you can try release/v4.4 branch directly instead of a specific commit, hope it can work

platform_packages = framework-espidf @ https://github.com/espressif/esp-idf/tree/release/v4.4
MikeBailleul commented 2 years ago

I believe you meant this?

platform_packages = framework-espidf @ https://github.com/espressif/esp-idf.git#release/v4.4

because your suggestion was not building.

And, still no luck: NaN values.

L-KAYA commented 2 years ago

I ran that example directly on IDF release/v4.4 and modified slightly to make it build:

#include <stdio.h>
#include "driver/i2s.h"

// you shouldn't need to change these settings
#define SAMPLE_BUFFER_SIZE 512
#define SAMPLE_RATE 8000
// most microphones will probably default to left channel but you may need to tie the L/R pin low
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
// either wire your microphone to the same pins or change these to match your wiring
#define I2S_MIC_SERIAL_CLOCK GPIO_NUM_32
#define I2S_MIC_LEFT_RIGHT_CLOCK GPIO_NUM_25
#define I2S_MIC_SERIAL_DATA GPIO_NUM_33

// don't mess around with this
i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4,
    .dma_buf_len = 1024,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
};

// and don't mess around with this
i2s_pin_config_t i2s_mic_pins = {
    .bck_io_num = I2S_MIC_SERIAL_CLOCK,
    .ws_io_num = I2S_MIC_LEFT_RIGHT_CLOCK,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = I2S_MIC_SERIAL_DATA
};

void setup(void)
{
    // start up the I2S peripheral
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &i2s_mic_pins);
}

int32_t raw_samples[SAMPLE_BUFFER_SIZE] = {0};

void loop(void)
{
    // read from the I2S device
    size_t bytes_read = 0;
    i2s_read(I2S_NUM_0, raw_samples, sizeof(int32_t) * SAMPLE_BUFFER_SIZE, &bytes_read, portMAX_DELAY);
    int samples_read = bytes_read / sizeof(int32_t);
    // dump the samples out to the serial channel.
    for (int i = 0; i < samples_read; i++) {
        printf("%d ", raw_samples[i]);
    }
    printf("\n");
}

void app_main(void)
{
    setup();
    while (1) {
        loop();
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

The code ran as expected for me, maybe you can take a try as well. If it works, we can just waiting for the release of v4.4.3

MikeBailleul commented 2 years ago

I tried your sample code, it does not work with my INMP441 mic.

L-KAYA commented 2 years ago

Have you tried to use I2S_CHANNEL_FMT_RIGHT_LEFT or I2S_CHANNEL_FMT_ONLY_RIGHT

MikeBailleul commented 2 years ago

Interesting, I2S_CHANNEL_FMT_ONLY_RIGHT worked! I2S_CHANNEL_FMT_RIGHT_LEFT did not. Why is that tough?

L-KAYA commented 2 years ago

It's indeed a bug before, that only_left is actually only_right meanwhile only_right is still only_right, but it has been fixed on release/4.4 about 3 weeks ago.

Have you checked which channel your mic actually sampling (i.e. left when L/R pin of INMP441 is pulled down and right when it is pulled up)?

MikeBailleul commented 2 years ago

Got it, but if it has been fixed on release/4.4, then why did I still had the bug when I tried this release a few comments earlier in this thread?

Not too sure about which channel is it using, I tried to pull L/R up and down and switch between only_left/only_right but I do not see any difference.

L-KAYA commented 2 years ago

Weird, have you updated to the latest release/v4.4? Anyway, I'll take an another try next week.

MikeBailleul commented 2 years ago

Yes like so:

platform = espressif32
platform_packages = framework-espidf @ https://github.com/espressif/esp-idf.git#release/v4.4

And it does not work. I mean, it works only if I use I2S_CHANNEL_FMT_ONLY_RIGHT which is fine by me anyway, I just wanted to raise the issue.

Jason2866 commented 2 years ago

@MikeBailleul You can try

platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.1/platform-espressif32-2.0.5.1.zip

i use a very actual IDF commit. The mentioned commit is there.

gpantazis commented 1 year ago

So I can confirm that on tag v4.4.4 I am still having this issue. I am 90% certain that I was NOT seeing this issue in tag 4.4.1 but can't guarantee it (and switching right now is not that simple).

Specifically: Using an ESP-EYE (esp32 based) I am unable to read the mic using I2S_CHANNEL_FMT_ONLY_LEFT but can successfully read it using I2S_CHANNEL_FMT_ONLY_RIGHT. According to the ESP-EYE schematic pin 5 (L/R) of the microphone (MSM261S4030H0) is tied to ground, which should mean, only the left channel should be producing any output.

Separately I have a custom board with an ESP32 connected to an I2S ADC programmed to only output on the left channel. This also does not work on tag v4.4.4 but did work on old firmware compiled with tag v4.4.1. Curiously though it works when I use I2S_CHANNEL_FMT_ONLY_RIGHT. It seems that somewhere the meaning of these two was switched or mangled?

I can temporarily use the wrong channel_format but that seems strange.

gpantazis commented 1 year ago

@L-KAYA Are there any updates on this? As stated the workaround is rather simple but it would be ideal to have this fixed. Anything else we can test?

khseal commented 1 year ago

I had the same issue. Thank you for the hint.

L-KAYA commented 1 year ago

Appologize for the late reply!

I'll take further test this week, if there is any workaround or patch, I'll post here for preview

L-KAYA commented 1 year ago

The bug was found, the rx_chan_mod on v4.4 is set to opposite value comparing to v5.0 and v5.1 image

Details

Concretely, the rx_chan_mod is actually related to msdb_right bit, meanwhile msdb_right is depended on the bits_per_sample. The correct relations are (ESP32 mono mode specific):

┌──────────────────┬─────────────┬───────────────┬──────────────────┐
│ bits_per_sample  │  msb_right  │  rx_chan_mod  │  sample_channel  │
├──────────────────┼─────────────┼───────────────┼──────────────────┤
│       16         │      1      │       1       │    only_right    │
├──────────────────┼─────────────┼───────────────┼──────────────────┤
│       16         │      1      │       2       │    only_left     │
├──────────────────┼─────────────┼───────────────┼──────────────────┤
│       32         │      0      │       2       │    only_right    │
├──────────────────┼─────────────┼───────────────┼──────────────────┤
│       32         │      0      │       1       │    only_left     │
└──────────────────┴─────────────┴───────────────┴──────────────────┘

The bug is that rx_chan_mod on v4.4 didn't take msb_right into consideration, so that the left channel and the right channel are exchanged.

Solution

The bug will be fixed in the next minor version, for now, you can try the following way to get a temporary fix.

Workaround

Fix patch

You can also try the patch:

0001-i2s-fixed-incorrect-channel-format-on-ESP32.patch

gpantazis commented 1 year ago

@L-KAYA Thank you for tracking down the fix! I will await v4.4.5 (v4.5?) for our project as the using the opposite channel is simple enough currently.

L-KAYA commented 1 year ago

FYI, the fix has already released in v4.4.5 (commit d337d9dc)