cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Microphone Data logging to SD card

anna23
Associate II
Posted on May 18, 2016 at 12:23

Hi,

My system is microphone - stm32f401 nucleo board - SD card

I am using ST extension board for mems mic and software STM32CubeExpansion_MEMSMIC1_V1.2.0.

This open source soft is acquires the mic and streaming it to USB ( that recognized by the computer as microphone) every 1msec. every mSec a buffer of 16 samples is transferred to usb. I added to this code SDIO with FatFs +DMA interface. 

every 1 mSec when the streaming buffer is full I am buffering it in double buffer system to bigger buffer of 50 mSec and then writing it to SDcard.

The problems I have: 

1. I am getting a noise like '' tuk tuk tuk tuk tuk '' in a some frequency (after some measures like 500Hz) . If I am turning off (comment the function)  the ''saving data'' the noise disappear. 

2. When I am importing to Audacity the binary file of the recordings, the tempo is a little faster then the original sound. (Sampling freq 16000Hz) 

Maybe somebody have an idea?

Thanks

#fatfs #stm32 #sd #sdio #!stm32f4
6 REPLIES 6
Posted on May 18, 2016 at 13:54

Id use a block size that matches the size of the media, at least 32KB but not some odd size. I would have a double buffer (ping-pong) so that data could be writen at HT and TC DMA signals so the content doesn't change underneath as it is being written.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
anna23
Associate II
Posted on May 18, 2016 at 14:54

Hi Clive,

Thanks for your answer. I am new with embedded programming and need some clarifications :)

1. 32K must be the block size that I sending to write on SD card?

2. I have 2 buffers for ping-pong . what is ''HT and TC DMA signals''

do you mean the 2 dma streams for writing and reading?

void DMA2_Stream3_IRQHandler(void)

void DMA2_Stream6_IRQHandler(void)

3. May it be possible that the USB streaming is always hold the USB interrupt active ? and all other interrupts interferes and the streaming stops for a some moment and then continue ? and I m getting the ''tuk tuk tuk ..'' noise?

When I am trying to buffer 32KB data I am getting errors:

Error[Lp011]: section placement failed 

          unable to allocate space for sections/blocks with a total estimated minimum size of 0x1c058 bytes (max align 0x8) in <[0x20000000-0x20017fff]> (total  

uncommitted space 0x18000). 

Error[Lp021]: the destination for compressed initializer batch ''P2-1'' is placed at an address that is dependent on the size of the batch, which is not allowed when  

using lz77 compression. Consider using ''initialize by copy with packing = zeros'' (or none) instead. 

Error while running Linker 

Thanks!!!!!

Posted on May 18, 2016 at 19:14

The media has 512 byte sectors, and probably 128KB erase blocks, the file system may have some smaller cluster size, but in a 16GB FAT32 volume probably 32KB.

The data you write needs, at a minimum, to be a multiple of 512 bytes to be remotely efficient. The 32KB suggested is a balance between speed, and available resources. So I'm saying use 32768 bytes, not 30000 or 32000, adjust your sampling buffer to address size rather than time. Speed is a achieved through a combination of long sustained/contiguous writes, and not splicing existing and new content via reads/writes interleaved.

The DMA can interrupt/signal at HT (Half Transfer) and TC (Transfer Complete), you should use this to determine which half of your memory buffer to write to the SD card. The audio side should specify one buffer, in circular mode. I would do the writing in a foreground task, not under interrupt.

You want to ensure your SDIO code can write at significantly higher rates than you can sample, you do not want to copy any memory, and perform the write to SD directly from the inactive half of the sample buffer.

Not sure where your noise is coming from but an SDIO interface running at 24 MHz is likely to be electrically quite noisy if hooked up with a handful of flying wires.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
anna23
Associate II
Posted on May 19, 2016 at 09:31

Hi Clive thank you very much for your help

what does it mean in technical implementation? ''I would do the writing in a foreground task''.

In my code: 

/*User function that is called when 1 ms of PDM data is available.

* In this application only PDM to PCM conversion and USB streaming  is performed.

* User can add his own code here to perform some DSP or audio analysis.*/

void AudioProcess(void)

{

   BSP_AUDIO_IN_PDMToPCM((uint16_t * )PDM_Buffer,PCM_Buffer);  

  Send_Audio_to_USB((int16_t *)PCM_Buffer, AUDIO_SAMPLING_FREQUENCY/1000*AUDIO_CHANNELS);  

   

FillBuffer (PCM_Buffer); // the implementation of this function is mine.

}

/* This function if filling 2 buffers 0.5 sec every one (16000 samples = 500*32 PCM_Buffer samples) in double buffer producer concumer 

technology. The program enter this function every msec and puts the cuurent data in the buffer. When 0.5 sec one of the buffers full 

the data sent to SD Card by SoreToSD() function. */

/* AS YOU SEGESTED I WILL CHANGE IT TO 32768 bytes*/

void FillBuffer ( uint16_t *PCM_data)

{

  static  uint16_t count1=0 , count2=0, Flag1Full =0, Flag2Full=0;

  static SD_RESULT LastStat=STORED_SUCC  ;

  SD_STATUS Status =FINISH  ; 

  static enum FLAG WorkFlag=Flag1; 

  static uint16_t BUFF1[Half_buffer],BUFF2[Half_buffer] ; 

  if ( (Flag1Full==0) & (WorkFlag==Flag1))   /***** Filling Buffer 1****/

  {

          memcpy(BUFF1+count1, PCM_data, 64);     

          count1 =count1+32;

          

          if (count1 == Half_buffer)      /* Buffer 1 is full switching the work state to buffer 2 and store the buffered data to SD*/

          {

            Flag1Full=1;

            count1=0;

            WorkFlag=Flag2;

            

              LastStat=StoreToSD(BUFF1, &Status); /* StoreToSD(BUFF1, &Status) just writes the buffer to sd*/

             

if (LastStat==STORED_SUCC)

              {

                   Flag1Full=0;

              }

              else  printf ('' Store to SD card is failed . '');

            }

  }

  

  else if ( (Flag2Full==0) & (WorkFlag==Flag2))   /***** Filling Buffer 2****/

  {

          memcpy(BUFF2+count2, PCM_data, 64);      

          count2 +=32;

          

          if (count2 == Half_buffer)    

          {

            Flag2Full=1;

            count2=0;

            WorkFlag=Flag1;

            

            LastStat=StoreToSD(BUFF2, &Status);

              if (LastStat==STORED_SUCC)

              { Flag2Full=0;

              }

              else printf ('' Store to SD card is failed'');

         }

  } 

}  

anna23
Associate II
Posted on May 19, 2016 at 14:12

Implemented all you suggestions about the size works well. 

Ok after a lot of work... no matter where I am adding the store to sd function it makes the interfering noise. In while loop of main, as interrupt , in audio process  ... 

I made some GPIO output set or reset on different function running to see the interrupts and function running ratio. Measuring by oscilloscope I found that USB interrupt always set  and all other toggle .

But I don`t know how to overcome this problem :(

mark239955_stm1
Associate II
Posted on May 21, 2016 at 03:11

The noise may well be due to ''ground bounce''.

When the MCU writes to the SD card, the SD card briefly consumes a largish amount of current (100-200mA).  This step current increase (and decrease) can cause system components that are sensitive to voltage - typically, analog components, e.g. ADC's - to see a small change in their negative reference voltage, which then appears as noise in your audio file.

The physical cause of this is that your microphone/codec/amplifier, MCU, and SD card are not co-located on a single board, with a ground plane, with vias from components directly to the ground plane.  Instead, they are connected by leads, which is perfectly OK for digital signals but not so good in this case for high-quality analog signals.

You can test this out by shutting down or disconnecting the microphone and otherwise running the system as normal.  If my theory is correct, your ''silent'' audio files will still have the ''tuk tuk tuk'' noise.  Another indicator is that the frequency of the sinusoids caused by the step change may be 500Hz, but the period between the sinusoids will be the period between writes to the SD card (50ms).  You will be able to see this if you inspect a ''silent'' file with an audio editor like audacity.