Fast Hardware ADC, any samples for this? are there any plans to make some examples for this?

On my company, we need a high-speed 16-bit ADC of at least 1MSPs.

I used the information on post #6 on this link Portenta H7 ADC DMA first steps - #4 by alexbau wherein the ADC code is extracted from a generated STM32Cube configuration. (There is a zip file attached) Fast_ADC_arduino.zip (13.1 KB)

We are not using DMA and we are just letting it convert continuously with the following pseudo code

Start_ADC(); // continuous conversion

for(int ctr=0; ctr<5000;ctr++)
{
buffer[ctr] = ReadADC();
}

Stop_ADC(); // stop conversion

The ADC sampling is fast (around 1.5MSps), but there are problems with the consistency of reading. Let's say for example I placed a constant DC signal (with a 10uF and 0.1uF decoupling capacitor and this signals are very clean when I view from the oscilloscope) of a certain volts, I am expecting the ADC values to be consistent with little fluctuations. example:

60000, 60001, 60000, 60000,60000, 60002

But I am seeing something like
60000, 60000, 60000,60000, 20000, 60002

This 20000 is an outlier. I though it was because of the signal or there is something wrong on the signals connected, but when I tried using the analogRead which is built-in to arduino, I can see it was able to read the DC signal correctly without any outlier data.

I am at lost of what to do next because I dont know where to look at. Could this be an issue on the generated STM32cube? or is there something that I need to do on the hardware for this?

1 Like

Not familiar with the Portenta H7, but took a quick look at main.ino.
Potential issues with data type mismatches?

here...

const uint32_t   data_len = 100000;  // line 18
for(int i=0; i<data_len;i++){        // lines 56, 84, 89

and here...

uint16_t   raw = 0;
raw = HAL_ADC_GetValue(&hadc1);     // Get ADC value returns uint32_t 

and here...

uint16_t   data[data_len];
data[i] = HAL_ADC_GetValue(&hadc1);     // Get ADC value returns uint32_t 

I wonder if its because analogRead() returns an int?

Hi dlloyd,

basically, what I am currently using is uint16_t for my buffer array.

The analogread returns an int and non-negative results from 0 to 1023. I am also using the same uint16_t buffer for that and i am getting the right results using analogread but it is very slow.

what baffles me right now is the occasional fluctuation of values using the fast ADC on the link above. I even tried placing half the analog reading to get 30,000 just to ensure nothing is overflowing, and I am still seeing some outliers and they are always lower than the expected value.

for example, im getting something like 30003, 30005, 20000, 30000,30003

I also tried disabling the continuous conversion and im still geting the fluctuation on values.

for(uint16_t ctr=0;ctr<5000;ctr++)
{
  HAL_ADC_Start(&hadc1);                                    // Start ADC conversion
  HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);         // Wait until conversion is finished
  buffer[ctr]= HAL_ADC_GetValue(&hadc1);                           // Get ADC value (buffer array is uint16_t, ADC is configured to return 16-bit value)
}
1 Like

In your code, not sure what MCU pin that adc1 relates to ... is it PA1_C?

image

From the STM32H747xI/G datasheet page 192:

3. Direct channels are connected to analog I/Os (PA0_C, PA1_C, PC2_C and PC3_C) to optimize ADC performance.
4. Fast channels correspond to PF3, PF5, PF7, PF9, PA6, PC4, PB1, PF11 and PF13.
5. Slow channels correspond to all ADC inputs except for the Direct and Fast channels.

Note that PA1_C is direct channel, not fast channel.

Perhaps they do use the Oversampler when using AnalogRead()?
image

datasheet for 745xI/G says: "3× ADCs with 16-bit max. resolution (up to 36
channels, up to 3.6 MSPS)"
I would assume, 1 MSPS is possible.

Just bear in mind:

  • Portenta H7 runs just with 400 MHz core clock, instead of nominal 480 MHz

  • You might to configure and select one of the PLLs as ADC clock source. If you use clock config as default, it might use a very slow clock.

Clock config is often the hook to get the "expected" performance.

thank you for all the reply.

after evaluating my experience on this, I decided to use a Nucleo board and use STM32Cube IDE. The project is done now and working very well.

I had seen people generating code from STM32Cube and generate the ADC with DMA and port it to Arduino Portenta and making some trial and error modifications. I feel this is a hacky solution and since my project is critical, I decided to abandon the use of Portenta H7 and use a Nucleo board with STM32H7. And the Nucleo board is way cheaper than the Portenta H7.

The first day I used the Nucleo, I was able to quickly implement the ADC with DMA running exactly at 1MSps. I was able to configure that 1MSps accurately using the STM32Cube clock tree configuration and the ADC configuration. I had the whole project working in 3 days with STM32Cube.

3 Likes

Yes, I have long since abandoned the Portenta for the same reasons. It has the hardware of a professional board but constantly having to implement these "hacks", in order to take advantage of said hardware, has been a huge waste of time. Due to the lack of good documentation/examples and tailored/optimized Arduino libraries, the Portenta H7 was essentially made dead on arrival.

1 Like

Actually, I agree: a nice piece of HW, this Portenta H7. The support could be better, the Arduino IDE (and LIB) is a nightmare.
I use this board just with plain and full open source, with STM32CubeIDE.
Arduino IDE is not usable and seen bugs in Arduino mbed implementation (SPI LSB first is not possible to configure). And Arduino is not really Open Source.

2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.