cancel
Showing results for 
Search instead for 
Did you mean: 

Reading PDM data from MP34DT05-A with STM32F407 I2S

ArturasV
Senior

Hello, it is the first time when i have to deal with microphones and PDM interface. I just can't get correct data from the microphone, or the data is correct but i am doing something terribly wrong. I configure I2S to sample microphone with DMA. When DMA Rx callback is received, i do the processing of PDM data and send it to PC via USB VCP interface. Problem is that when i get the data in PC, there are some high frequency harmonics which are giving very anoying "beep" sound, even though in the background i can hear the "clap sound" that i am making with my hands. Could someone look at my code and tell me what am i doing wrong?

I attache the main file of my program, also the file where DMA controller of I2S is configured. I also attach pictures of how my signals look in frequency and time domains. Appreciate for the help if anyone could tell my what i am doing wrong.

By the way, i have read ST documents UM2372, AN5027. I do not see from them that i am doing something wrong.

I also add the recorded wav file. Listen it carefully and at low sound because the "beep" is really annoying. You can hear in the background that i am clap two times slowly, then one time i do a double clap quickly.

Will wait for the responses, cheers.

17 REPLIES 17
T J
Lead

it looks like switching power supply noise on the Audio input, probably on the processor rail too.

you can see the AGC kicking in, in the time domain.

do you use ferrites on the PCB ?

can you try a DC supply for simple test ?

I didn't use the PDM systems myself, not much help after this...

so its either power supply or sampling rate overrun/underun or DMA length, stuff like that..

sampling rate issues would give you a very constant tone. like 4.5khz always, is that what you have ?

ArturasV
Senior

Hi TJ, thank you for the answer. I forget to write that i am doing this on STM32F4 discovery board. Microphone that i wired up is from this dev board: https://www.st.com/en/evaluation-tools/steval-mic001v1.html and i am powering the microphones from the STM32F4 discovery board.

For the tone: Try to listen, i added the sound file, called test1.wav . I have harmonics at 1khz, 2khz, 3 khz and etc... So it is an aliasing problem you think?

I did try to use external power supply for microphones, but no effect, result is the same. My guess is that i am doing some wrong with either PCM output samples number, or with DMA buffers length, or with sampling frequency of I2S or decimation factor, i just dont understand what exactly... I am using ST provided PDM2PCM library if you looked at my code.

Any other thoughts?

T J
Lead

I dont like this line:

       if(UserRxBufferFS[0] == 0xCC && UserRxBufferFS[1] == 0x36 && UserRxBufferFS[2] == 0xAD)

T J
Lead

I would say that you issue may be in that you have no buffer between the I2S data interrupt and the USB CDC_Transmit_FS

the CDC_Transmit_FS is not always ready and thereby you will start missing frames.

ie.

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  /* USER CODE BEGIN 7 */
  USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
  if (hcdc->TxState != 0){
    return USBD_BUSY;       <-  here , returning without sending...
  }

and you dont look at the err_code.. yes many issues...

ArturasV
Senior

TJ, that line was just a quick dumb line to accept a command, it is of course bad and will not be in the code later. + ST got examples where they transmit Audio captured at 48kHz And there are no problems there. I looked with oscilloscope how long does it take to send data before my buffer is full again, and there is plenty of time left. I think that i dont understand something with the protocol itself, not correct sampling frequencies, or i am selecting bad data from the data buffer that i have received.

J Lee
Associate III

I think the PDM input data format should be byte-packed, whih means u should transfer the data array pointer type from uint16 to uint8, so each time a byte of PDM data is fed into the PDM_Filter.​

One more thing, the input and output data number in your code seems to be the same, the # of PCM and # of PDM data should have a ratio

ArturasV
Senior

@Community member​  What do you mean that they should have a ration? If I am a little bit lost. If i configure this to only one channel, so when i receive data from microphone, is the first byte from left channel, and second byte is from right channel, or all bytes are from left channel? Then you say that if i feed uint16_t pdmdata[16] , so i should not get 16 PCM samples? How much should i get then?

J Lee
Associate III

I suppose u use the mic in mono mode, u can have a look at any of the audio record and play sample project in Cube instalation folder

  1. What i meant uint8 is the pointer type, which means each time the address has an increment of 8 bit, like following

PDM_Filter((uint8_t *)(&PDMbuff[0]), (uint16_t *)(&PCMbuff[0]), &PDM_FilterHandler);

2.I am also figuring out what is the ratio, but in the sample project, the PDM data # and PCM data # are as following:

/* PDM buffer input size */

#define INTERNAL_BUFF_SIZE          128*DEFAULT_AUDIO_IN_FREQ/16000*DEFAULT_AUDIO_IN_CHANNEL_NBR

/* PCM buffer output size */

#define PCM_OUT_SIZE             DEFAULT_AUDIO_IN_FREQ/1000

ArturasV
Senior

I am watching that example also at the moment and it is bugging me because i do not get it, why it is configured this way. So basically if i am using mic in mono mode, so DEFAULT_AUDIO_IN_CHANNEL_NBR is equal to 1. If i use DEFAULT_AUDIO_IN_FREQ equal to 16kHz In that case my PDM buffer is uint16_t pdmbuff[128] and pcm buff is only int16_t pcmbuff[16]. So PCM buffer is 8 times smaller than pdm buffer, i do not get it.

Also, do you understand how PDM interface should work. I am now seeing timing diagram of MP34DT05-A, which says that output of pdm bits is interleaved (one bit is from left channel, then one from right, one left, one right and so on). So since i am using only channel, shouldn't i always see zeros in another channel? Also, this looks like in one 16 bit word i have 8 bits of channel data that i want. So it needs more processing i think. I am analyzing the example too @Community member​ , but if you get this working could you share how you did it? Because i am struggling with it for a few days now. I will also share my progress if i manage to get something working.