cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo-F303RE Getting ADC Data Speed Problem

ADynr.1
Associate II

Hello everyone,

I'm trying to get ADC(DMA) data on the NucleoF303RE STM32 board. The sampling speed is 1Msamples/s. When I apply a sinus wave I see data losses on ADC data. I tried to read data with a serial port and save it to an sd card. Both of them have the same problem.

ADC is 12 bits and 1M samples/s.

While saving to the sd card, I stopped ADC after the buffer is filled to see what's is the problem. There is no data loss when ADC is stopped after filling the buffer. But, I need continuous conversion, so it is not a solution for me. I guess the ADC uses the same buffer immediately, and saving data commands are not fast enough before ADC fills the buffer again.

Do you have any suggestions? Where am I doing wrong? or maybe any other algorithms?

Codes to save to the sd card I use:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
   // HAL_ADC_Stop_DMA(&hadc1);
    for (int i = 0; i < ADC_BUF_LEN; i++) {
        fres = f_printf(&fil, "%d\n", adc_buf[i]);
        if (fres < 0) {
            myprintf("f_printf error (%i)\r\n", fres);
                while(1);
        }
    }
    f_close(&fil);
    f_mount(NULL, "", 0);
}

Codes to read from the serial port I use:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    for (int i = 0; i < ADC_BUF_LEN; ) {
        myprintf("%i\r\n", adc_buf[i]);
        i++;
    }
}

I also tried to transfer data when the half buffer is filled, then transfer the second half when the full buffer is filled. But, It only uses the first half buffer with this code and keeps doing data losses.

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
    for (int i = 0; i < ADC_BUF_LEN/2; ) {
        myprintf("%i\r\n", adc_buf[i]);
        i++;
    }
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    for (int i = ADC_BUF_LEN/2; i < ADC_BUF_LEN; ) {
        myprintf("%i\r\n", adc_buf[i]);
        i++;
    }
}

And, I tried with DMA USART:

len=sizeof(BUFFER_SIZE);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)buffer1, len);
HAL_UART_Transmit_DMA(&huart2, buffer, len);

My max baud rate is 2000000 for USART.

20 REPLIES 20
AScha.3
Chief III

Hi ,

i would try SD card first; just because i use it and it is working at 2MB/s or more; (you want 2MB/s , 1Ms x 16bit ); and on 32GB card you can store about 8 hours continuous data - more than you need, i think. SD interface must be 4bit and 50MHz clk for best speed; i would recommend circular buffer with minimum 2x32KB, to have some buffer for the SD-command time; SD cards need about 1ms--20ms to begin a command, so dont try with cheap chinese noname card , i use SanDisk and Transcend ; you should test it with different cards and see, what problems arise... :)

If you feel a post has answered your question, please click "Accept as Solution".

Thank you so much for the detailed answer.

I tried to use SDMMC with FATFS but unfortunately, I couldn't solve the sd card mount error. I tried different MHz(including 50MHZ), sd card partition sizes, changing settings on cube mx, and checked the connections many times. (I soldered wires on the sd card adapter) My sd card is SanDisk Class10. It was working on the previous board with SPI.

I am going to try the Ethernet port now. I think I will need to create a UDP server, then modify it for ADC data. It looks much harder than SDIO/SDMMC, I hope I can figure it out.

Hi ASCha.3 again,

I could finally write on an sd card.

The first problem was the sd card. I tried another Sandisk class10 and it worked.

But I have some issues with clock settings, I couldn't understand why it is happening.

If I use below 5 clock dive factor, I get "f_mount(1)" error. If there is no sd card connected, it gives "f_mount(3)" error.

I changed the clock settings, but it doesn't affect the clock divider factor. I mean at a lower frequency if I choose less than 5 it gives an error.

The working clock settings is at the below pictures ( With 5 divide factor it is not possible to get 50Mhz)

Do you have any idea why I can't use the below 5 divide factor?

0693W00000aJjv9QAC.png0693W00000aJjvTQAS.png0693W00000aJjviQAC.png 

good!

+

i just can tell you, what i found important for good sd-card connection:

  • power supply
  • cabels/line
  • clk + pin setting

power: i put a 10uF X7R smd cer.cap close to card adapter at the vcc-gnd joints.

cabels: all cabels same length , short (i have 7cm) , both gnd have cables.

cpu setting:

0693W00000aJkM0QAK.png0693W00000aJkMKQA0.png0693W00000aJkMeQAK.png0693W00000aJkLJQA0.pngif port/pin speed to high, may get strong reflections - card not working !

if pin-speed to low, can work only with low speed on transfer.

If you feel a post has answered your question, please click "Accept as Solution".

My settings are the same as yours. When I changed the max pin speed from very high to high it worked in 1 clock divider factor and 100MHz PLL2R. I am using PLL2R because if I want to use PLL1, it decreases CPU Mhz for 100MHz SDMMC and it causes mount error. After trying a new clock setting it stopped working, I changed back to the same settings but it doesn't work again with 1 clock divider factor. If I make it 5, then it works.

The power supply is a USB connection from a laptop.

All cables are the same type and length.

I don't have a cap to use it now.

I guess I should find a new sd card that works or I should use 5 clock divide factor with 183MHz.

AScha.3
Chief III

so you got it working with "my" settings, at 100MHz div1 - good.

use this setting for best speed.

+ dont try "more" ... i did and made SD-card instantly no more working.

dead. (but worked one day later again...curiosity kills the cat.)

+

using PLL1 or 2 is not important, just the clk value .

If you feel a post has answered your question, please click "Accept as Solution".

Unfortunately, I can't make it work at 100MHz dv1 again. But, it works at 100Mhz div2 with "high" max pin speed.

You said before "i would recommend circular buffer with minimum 2x32KB, to have some buffer for the SD-command time"

How can I make this happen? Should I define 64000(2*32000) adc buffer size, and use HAL_ADC_ConvHalfCpltCallback and HAL_ADC_ConvCpltCallback functions to write to the sd card?

right. use 64K circular buffer , with ADC-DMA ( HAL_ADC_Start_DMA()... ) ,

half+full callbacks to write 32K block;

+ i would add a LED on a pin, to see (or look with DSO on this pin) the "cpu busy time" : set led on at start, then in callbacks first set led off, at end of each callback set led on again; so you simply can see, how much time the write needs and whether there is enough free time between block writes .

If you feel a post has answered your question, please click "Accept as Solution".

Hello AScha

SDMMC is working at around 32MHz. I made some tests and got distorted results. To see on an oscilloscope if the writing speed is fast enough I am toggling pins at the very beginning of full callback and the end of the writing process. But I realized a problem, sampling speed is too slow when I use fatfs writing commands. What might be the problem?

The first pic is from full callback without fatfs write cmds(below).

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
		for (int i = 0; i < ADC_BUF_LEN/2; i++) {
		fres = f_printf(&fil, "%d\n", adc_buf[i]);
		}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_11);
	for (int i = ADC_BUF_LEN/2; i < ADC_BUF_LEN; i++) {
		fres = f_printf(&fil, "%d\n", adc_buf[i]);
	}
	if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)==GPIO_PIN_SET){  //Check if button pressed
			      f_close(&fil);
			      f_mount(NULL, "", 0);
			      myprintf("closed\r\n");
		  }
}
/* USER CODE END 4 */

0693W00000bhSMnQAM.png 

The second pic is with fatfs write cmds.

0693W00000bhSN2QAM.png 

Another problem is it gets much slower if f_close is not done yet.

0693W00000bhSMjQAM.png

AScha.3
Chief III

f_print...you have text ???

you have 16bit data - so write in callback the whole block -> f_write(...) .

If you feel a post has answered your question, please click "Accept as Solution".