2022-03-07 08:36 PM
Microcontroller newbie here. I currently use an STM32F411 MCU.
For every cycle of 500μs, I need to: 1-perform ADC conversion for 200μs at a high sampling rate (obtaining at least 300-400 samples in that timeframe); and 2-Transfer the ADC data to a computer using the virtual com port.
What would be the most reliable approach to accomplish this?
Up until now, I am able to: 1-use DMA to store ADC data with a sampling rate of 4MSamples/s; 2-use the "CDC_Transmit_FS" function to send random stuff through the com port.
Thank you for your reply!
2022-03-07 09:11 PM
The other way would be cube monitor loading data throught swd link. Learning curve for the sw tool required, so estimate its ROI (is it worth it)
2022-03-08 04:21 AM
So 400 uint16_t values every 500us. That's 12.8 Mbps.
Too much for USB FS by quite a bit, but potentially doable with USB HS if you can code things well.
Create a large, flexible buffer for the data that is resilient against hiccups in USB, send it out ASAP when the peripheral is free. Send out large chunks in multiples of the packet size (64 or 512) for highest efficiency and use DMA to do so.
Note that the VCP will need to be direct and not via UART, as the baud rates are not nearly enough to support that bandwidth.
2022-03-08 06:03 AM
Seems you are newbie in math too.
400x16 maybe reduced 400x12bit ADC = 4800b every 0,5 ms = 9,6Mbps
Virtual COM maybe 10x slower (980k) then your repeat time can be 5ms ...
2022-03-08 08:48 AM
Thank you for your super prompt reply! I will look into it.
2022-03-08 08:54 AM
Thank you TDK for your very thorough answer!
I read that USB FS has a rate of 12 Mbit/s (?), that's why I thought it might be possible to transmit the data fast enough.
2022-03-08 08:55 AM
Yes! It would seem so haha!
Thank you very much for the info!
2022-03-08 09:26 AM
2022-03-08 09:30 AM
I’m super grateful for all your insightful answers!
Before I had the chance to try your suggestions, I quickly attempted the following in my main.c file:
…
/* USER CODE BEGIN PV */
uint16_t adc_buf[400];
/* USER CODE END PV */
…
/* USER CODE BEGIN 0 */
extern uint8_t CDC_Transmit_FS(uint16_t* Buf, uint16_t Len);
/* USER CODE END 0 */
…
int main(void)
{
…
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, 400);
/* USER CODE END 2 */
…
}
… // (near the end of my main.c file)
/* USER CODE BEGIN 4 */
// Called when buffer is full
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
CDC_Transmit_FS(adc_buf,sizeof(adc_buf));
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
}
/* USER CODE END 4 */
This is the signal from my GPIO pin C13 via a probe (see figure below, I had peaks around every 100us):
However, I see a constant flow of gibberish from my COM port, something like: “D@=EC>EE;@F=;HD9AG;<IB:DEGE99CEFNH9<A>�?
When I connect my ADC pin to ground, the flow of gibberish stops (meaning it is transmitting zeros?).
And when I connect my ADC pin to 3.3V, I get a constant flow of this symbol (denoting max voltage?): ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Nevertheless, when I pause my script in CubeIDE, I do see my buffer with ADC values:
Would you say that I’m getting closer to my objective? I’m not exactly sure what is wrong with my code.
Thank you so much!