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

So, you have 1M samples per second, convert them to ASCII (i.e. 1..4 digits, mostly 4), add 2 characters, so in result have around 6 MegaBytes or around 50 Megabits per second.

You can't transmit that using 2 Megabits per second UART (and there's a penalty of start/stop bits of UART).

I don't know what's the practical sustainable transfer speed of SD cards (@Community member​ will surely have some relevant numbers), but IMO 50Mbits/s would be beyond anything that could be practically achieved, plus SD cards feature an inherent lack of absolute guarantee for transfer speeds.

Not to mention the processing needed to convert the data to ASCII.

Even transmitting as binary, even if packed, would require 12Mbits/s sustained.

You may want to reconsider your goals.

JW

Approach here seems entirely wrong.

You can't do all this in the callback, which occurs under interrupt context.

You'd need large ping pong buffers, writing large blocks to the SD Card, likely in binary, and not with 1000s of small writes. And certainly not opening, closing and mounting continuously.

F3 likely to be using SPI, not SDIO, so likely below 1MBps writes even if optimal.​

Going to need to reevaluate pacing and flow.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ADynr.1
Associate II

Thank you so much for the answer @Community member​ @Community member​ 

Seems like it's not possible with UART or sd card(using SPI).

I'm trying to make the USB work now, is it possible to transfer that data fast enough with "CDC_Transmit_FS"?

AScha.3
Chief III

USB full speed is 12Mb bus speed max, so real maybe 8 Mb pure data. (in my tests max. was about this, 1MB/s ).

so with 16bit data, you could get 500k sampels/s. 1M not.

on SD card, with other cpu, in SDIO and 4 bit mode, it could be possible, but need big buffer, if dropouts have to be avoided. maybe 128KB circular write buffer and min. 200KB input buffer, because SD cards sometimes have 100ms (!) delay, when write command coming; this needs big buffer...

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

Thank you so much.

Is there anything that you suggest for USB for 500k samples/s I should pay attention to?

Can I transfer that data with a new board that has an ethernet port?

Do the SDIO mean boards have their own SD card adapter onboard? Setting the sd card sounds difficult and the speed is not certain if it is fast enough or not.

AScha.3
Chief III

>Is there anything that you suggest for USB for 500k samples/s I should pay attention to?

many things...receiving system (win ..xx ? linux ..?) set buffer-blocksize etc. ; just try it !

>Can I transfer that data with a new board that has an ethernet port?

shure , with 100M port your 16Mb are no problem; but you need ethernet running ... Ooo...

>Do the SDIO mean boards have their own SD card adapter onboard?

no, just the chip needs to have the SDIO (4bit) peripheral;

0693W00000aICYjQAO.pngi have here a "black pill" board with stm32F411 cpu, 9 short (7cm) wires to a micro/SDcard adapter;

0693W00000aICYFQA4.pngworking fine; got about 2MB/s average speed, so could work for your sampling.

but what you wanna do at all , with 1 Msample continuous data ?? is about 8GB in one hour - and then ??

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

Thank you so much again!

It will be just a very simple radar application, I'm trying to convert received signals. For the SDIO, just soldering wires to the adapter will work as I understand. And, I will need to figure out how to use ethernet also.

I'm still trying to use USB Virtual COM, but can't get any data. What might be the reason?

I followed this link to receive data:

https://controllerstech.com/send-and-receive-data-to-pc-without-uart-stm32-usb-com/

The driver seems okay, PC recognizes the STM32 connection. Unfortunately, I can't receive any data. There is no error while connecting.

I also tried other tutorials on youtube too, they are similar.

Briefly the code I used:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
#include "string.h"
/* USER CODE END Includes */
 
  /* USER CODE BEGIN 1 */
	uint8_t data[] = "Hello \n";
  /* USER CODE END 1 */
 
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
	  CDC_Transmit_FS(data, sizeof(data));
	  	  HAL_Delay (1000);
  }
  /* USER CODE END 3 */
}

AScha.3
Chief III

>It will be just a very simple radar application

"simple" and "radar" are two very different worlds for me ! :)

afaik is radar signal analyzed as soon as possible, usually in an asic or fpga (many MHz..GHz speed) and only the result from this is propagated further, to a display etc.

so i think, you should think , what you wanna do , or how to analyze your signal "here", not how to store or send to storage (useless to do this way...) .

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

Hi Ascha,

I'm very sorry for not being clear. It is a kind of ground-penetrating radar, so recording data is necessary.

I bought a Nucleo-H723ZG board for an ethernet port and SDIO. I'll use one of them with a 16 bits ADC now.

I couldn't find any tutorial or example about sending ADC data through ethernet or saving with SDIO.

I tried this ethernet beginning tutorial but I don't know how to implement this for the ADC application. https://controllerstech.com/stm32-ethernet-1-connection/

Which one would you recommend? I think SDIO is more practical since it doesn't need a PC to save data. This board supports up to 128MHz SDIO. What should I pay attention to on code to save ADC data at max speed? How it should be? Could you help me with this, please?