I2S not working properly with Wrover32

aaronw
Posts: 14
Joined: Fri Apr 17, 2020 4:33 am

I2S not working properly with Wrover32

Postby aaronw » Fri Apr 17, 2020 5:24 am

I am trying to get i2s working with a SPH0645LM4H-B digital microphone and am not having much luck.
The data sheet can be found here: https://media.digikey.com/pdf/Data%20Sh ... LM4H-B.pdf
I have a 100K pull-down resistor as is suggested by the data sheet. I do not have any inline resistors since the traces are quite short (and I do not have room on the PCB). When I look at the signals on my oscilloscope they look quite clean without any ringing. While my schematic may not show it in the snapshot below, there is plenty of filtering on the microphone and nothing else is connected to those pins (except for IO0 which also has the reset circuit hooked up to it). The signal on IO0 looks clean though.

The microphone outputs a 24-bit output (MSB first). I have it wired as the right channel with IO0 set for the bclk, IO19 for the word select (WS) and IO35 for the data in. I do not get any data unless I configure it for 32-bits per sample. Note that this device expects 32 clock pulses per sample. If I configure bits_per_sample to 24 or less all I get are zeroes (i.e. I2S_BITS_PER_SAMPLE_24BIT).

I have tried several sampling frequencies but the 32-bit data does not appear to show any pattern when I use a fixed frequency audio source.

I have also tried multiple sampling frequencies, i.e. 16KHz, 44100 and 48000 but the data still appears to be garbage (but I also only see

It looks like I am getting 17 bits of data but I do not see any of the expected pattern. It seems that no matter what I do I just see garbage data.

[Codebox]
static const i2s_port_t i2s_mic_num = I2S_NUM_0;

static const i2s_config_t i2s_mic_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 512,
.use_apll = true,
.fixed_mclk = 0,
};

static const i2s_pin_config_t mic_pin_config = {
.bck_io_num = 0,
.ws_io_num = 19,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = 35,
};

int setup_i2s_mic(void)
{
int ret;

ret = i2s_driver_install(i2s_mic_num, &i2s_mic_config, 0, NULL);
if (ret) {
Serial.printf("i2s_driver_install returned %d for MIC\n", ret);
return ret;
}
ret = i2s_set_pin(i2s_mic_num, &mic_pin_config);
if (ret) {
Serial.printf("i2s_set_pin returned %d for MIC\n", ret);
return ret;
}
return ret;
}

int mic_read(int *buf, size_t size, size_t *samples_read)
{
int ret = i2s_read(i2s_mic_num, (void *)buf, size * 4, samples_read, portMAX_DELAY);
// Output is 24 bits per sample, changed to signed integers by shifting the MSB
if (samples_read) {
*samples_read /= 4;
}
return ret;
}

int mic_start(void)
{
return i2s_start(i2s_mic_num);
}

int mic_stop(void)
{
return i2s_stop(i2s_mic_num);
}

int mic_test(void)
{
const int bytes_per_sample = i2s_mic_config.bits_per_sample / 8;
size_t buf_len = bytes_per_sample * i2s_mic_config.sample_rate / 32;
int *buffer = new int[buf_len];
size_t samples_read = 0;

if (!buffer) {
Serial.printf("Out of memory! Could not allocate %u bytes\n", buf_len);
return -1;
}
Serial.printf("Recording 1 second...\n");
mic_read(buffer, buf_len, &samples_read);
Serial.printf("Done. Read %u samples\n", samples_read);
for (int i = 0; i < samples_read; i++)
Serial.printf("0x%08x\n", buffer);
Serial.printf("\n");

return 0;
}

void setup() {
int ret;
Serial.begin(115200);
ret = setup_i2s_mic();
if (ret)
Serial.printf("Error setting up mic\n");
delay(1000);
if (!ret)
mic_test();
}
[/Codebox]

Am I doing something wrong here? When I looked at the signals on my oscilloscope they looked clean and the traces are quite short (the microphone is mounted only a couple mm away from the Wrover32).

Here is an output after sampling a 2KHz tone at a 16KHz sample rate (note that there are plenty more samples but they all more or less look the same):
0xead38000
0xf36b0000
0xfcb60000
0xfeb30000
0xfc8a0000
0xf4890000
0xeaea0000
0xe8678000
0xeb610000
0xf4750000
0xfd3a0000
0xfeb10000
0xfc3a8000
0xf3c30000
0xea928000
0xe8a30000
0xec188000
0xf5978000
0xfdcd8000
0xfec68000
0xfbe98000
0xf2e90000
0xea2c8000
0xe8d10000
0xecc70000
0xf69f8000
Attachments
Screenshot_20200416_222035.png
Screenshot_20200416_222035.png (138.96 KiB) Viewed 5254 times
Screenshot_20200416_221827.png
Screenshot_20200416_221827.png (44.52 KiB) Viewed 5254 times

aaronw
Posts: 14
Joined: Fri Apr 17, 2020 4:33 am

Re: I2S not working properly with Wrover32

Postby aaronw » Sat Apr 18, 2020 5:26 am

I think it may be working but it looks like with the Knowles microphone I need to add a high-pass filter to filter out DC.

aaronw
Posts: 14
Joined: Fri Apr 17, 2020 4:33 am

Re: I2S not working properly with Wrover32

Postby aaronw » Sat Apr 18, 2020 7:16 am

After adding a DC blocking filter it is working. It sounds like the microphone I am using goes down to DC or at least has some DC offset that needs to be removed.
https://www.knowles.com/docs/default-so ... =fdb77b1_6

Who is online

Users browsing this forum: No registered users and 99 guests