I want to measure signal with ADC and send measurements to PC to generate plots.

My code:

    ADC3ConvertedVoltage = ADC3ConvertedValue * 3300/0xFFF;
    ADCresultsTab[i] = ADC3ConvertedVoltage;

The problem is that I want to sample signal as fast as it is possible. Here I'm using baud rate = 256000 (Windows only). What is the possibility to sample signals faster? What is more optimal code for sample and send measurement?

I see that the problem there is UART transmission.

And my additional questions are: Is it real time measurement with this code? How it should be made if I want real time measurement?

  • \$\begingroup\$ Ad. as fast as possible: Check the datasheet (so add a link to it) on how fast the ADC actually is. Ad. additional question: First define what your requirement is for "real time". \$\endgroup\$ – jippie Jun 2 '13 at 19:12
  • \$\begingroup\$ But there the problem is also with uart sending of data. I know that the limiting is ADC speed, but in the code in question it is slowed by UART sending of data. My question is how to implement it effictient to not limit measurement speed. I do not understand secod part of question, I thought that there is one "real time" definition? \$\endgroup\$ – krzych Jun 2 '13 at 19:16
  • 1
    \$\begingroup\$ Interrupts. The ADC can do a conversion while the data is shifted out through UART. During the conversion the CPU is doing nothing and you can use that time for filling the UART buffer with data. \$\endgroup\$ – jippie Jun 2 '13 at 19:18
  • 1
    \$\begingroup\$ Or DMA, though you would probably have to set up two DMA streams (DAC to memory, memory to UART). \$\endgroup\$ – fm_andreas Jun 2 '13 at 19:20
  • 1
    \$\begingroup\$ If the purpose of the transfer to the PC is to generate real time plots, take a moment to think about how that data can be used and interpreted on the user end. Plotting 8Msample/second data in real time is just useless for visualization. Also, the "as fast as possible" thing is a bit backwards. Start with "as fast as I need it to work", put a number on that, and strive to achieve it. \$\endgroup\$ – Scott Seidman Jun 3 '13 at 20:57

While more elaborate interrupt- or DMA-based code would be necessary to achieve the best performance, relatively minor improvements to your code would improve the situation already. I'd start by transmitting samples in binary instead of in text. This requires slightly more work at the receiving end, but will cut the required UART bandwidth by at least 2-3x (2 bytes per sample vs. up to 6 in text with separator). You can also readily increase the baud rate to, e.g., 921.6kbps, which is standard and should be well supported on the receiving end. Assuming a standard STM32F2 architecture, you could go up to 7.5Mbps but you'd need to check support for that at the receiving end.

With 2 bytes per sample and 921.6kbps, you would get a throughput of about 46'000 samples/s. At 7.5Mbps, you'd get 370'000 samples/s. If your application allows it, you could reduce the resolution to 8 bits and thus use a single byte per sample, effectively doubling the throughput in samples/s.

While 370ksamples/s is not bad, it's still pretty far from the theoretical 6Msamples/s (assuming STM32F2, 12bit conversion and using the 3 ADC in triple interleaved mode). This translates to 12MB/s of data to transfer from the MCU to the computer, which is no trivial amount. UART will not do. SPI, at a max of 30Mbps (2-3MB/s) wont do it either. Writing to a microSD card via SDIO would come close. USB 2.0 would do it but is much more complicated software-wise and requires external components for the PHY. ETH would do fine as well but would require additional components and a network stack to be implemented on the MCU. This complexity explains why, in most applications, the samples are buffered in memory and transferred asynchronously.

  • \$\begingroup\$ Worth mentioning that STM32 USART has theoretical peak at 4Mbps, and realistically to PC over a FTDI dongle maybe 3Mbps max. Some specific RS485 setup could maybe go a bit higher. \$\endgroup\$ – kert Nov 4 '15 at 21:38

It's probably also worth mentioning that the sprintf call is probably fairly slow and (if it's the only time you use it) pulls in a lot of library code. Even if you want to keep human-readable ascii, you could probably serialize the number a lot faster yourself than sprintf. While you're at it, you could include the semicolon in the string and make only one call to USART2_SendText.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.