cancel
Showing results for 
Search instead for 
Did you mean: 

Occasionally reading channel 0 when expecting channel 1 of ADC sequence. Why?

JayC
Associate

I have a fairly simple STM32F051R8 system reading an ADC sequence with two channels. I configured the system using CubeMX (v5.1.0, linux) with continuous and discontinuous modes disabled. I am polling the ADC in the simplest way imaginable.

At times (5-10 seconds), I get the value for the first channel when reading the second. I have never seen the opposite (but it could be happening without me catching it). To test this, I am placing different DC values on each channel and logging the read values.

I have tried various modes (continuous, discontinuous), EOC vs. EOS, without too much success. I found that the most stable sampling was performed this way (for polling at least).

Any ideas why the ADC is not behaving as expected? What am I doing wrong with this simple ADC polling method?

Thanks for the help!

Here is my ADC config generated from CubeMX:

 hadc.Instance = ADC1; 
 hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; 
 hadc.Init.Resolution = ADC_RESOLUTION_12B; 
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; 
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD; 
 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 
 hadc.Init.LowPowerAutoWait = DISABLE; 
 hadc.Init.LowPowerAutoPowerOff = DISABLE; 
 hadc.Init.ContinuousConvMode = DISABLE; 
 hadc.Init.DiscontinuousConvMode = DISABLE; 
 hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; 
 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; 
 hadc.Init.DMAContinuousRequests = DISABLE; 
 hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; 
 if (HAL_ADC_Init(&hadc) != HAL_OK) 
 { 
   Error_Handler(); 
 } 
 /** Configure for the selected ADC regular channel to be converted. 
 */ 
 sConfig.Channel = ADC_CHANNEL_10; 
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; 
 sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5; 
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) 
 { 
   Error_Handler(); 
 } 
 
 /** Cofigure for the selected ADC regular channel to be converted. */ 
 sConfig.Channel = ADC_CHANNEL_11; 
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)  { 
   Error_Handler(); 
 }

My sampling code is:

 HAL_ADC_Start(pAdcInst); 
 for (idx = 0; idx < 2; idx++) 
 { 
   status |= HAL_ADC_PollForConversion(pAdcInst, 100); 
   g_adc_values[idx] = HAL_ADC_GetValue(pAdcInst); 
 } 
 HAL_ADC_Stop(pAdcInst);

4 REPLIES 4

I don't Cube and the "logic" behind the ADC functions in Cube eludes me, so I don't really understand what's exactly causing your problem. But I guess it's related to the fact that you are attempting a two-conversion sequence with software readout of the values, together with a relatively short sampling time it's bound to fail, sooner or later you're going to miss conversions (you might want to check the overflow bit). Sequences are meant to be converted with DMA readout.

Why don't you set ADC to a single-channel sequence with the first channel, perform conversion with polling, then set it again to a single-channel sequence with second channel and then preform the conversion with polling?

JW

PS. Change your username to a normal nick.

JayC
Associate

Thanks, JW. I got it to work in a more stable fashion. I had some dead timer code lying around from some experiments that was conflicting with my ADC polling. I removed it and ADC seems good.

I want to move to DMA for these reads, and will try to configure that next.

I read somewhere that the ADC sample rate is affected by the resistance/load on the analog input... do you happen to have any information on this?

Thanks,

Jay

> I read somewhere that the ADC sample rate is affected by the resistance/load on the analog input... do you happen to have any information on this?

Just the "usual" behavior of a S&H stage, which is basically a RC element.

"Sampling time" is the time you allow the hold capacitor to be charged from the input.

The standard calculation rules apply. Check the datasheet and you input circuitry.

Jay,

ADC is sampled onto an internal sampling capacitor, it's capacity C is given in the DS. If R is the impedance of the signal source, and there's no other external capacitance on the ADC input pin, if the sampling time is shorter than a fraction of RC, the sampling capacitor won't be fully charged and the ADC result won't reflect the output voltage of the signal source would it be completely unloaded.

JW

@Vincent Onde​ ,

You may say that the effect of ADC sampling capacitor and input impedance is obvious, and that that is already covered enough in DS/RM. As you can see, it's neither. How hard is to write an appnote covering this in clear terms, giving examples for input signal sources, with actual screenshots from oscilloscope together with the readout values, demonstrating the effect for various input impedances, various sampling times, and various actual input voltages? Goes to the ADC dozen.

Another one to the ADC dozen is the original problem in this thread, namely that using the automatic sequencer without DMA may easily lead to data loss/overruns; discussing briefly latencies (which btw. could make another AN or even several, looking at it from several aspects) that might also illustrate the overrun flag, etc.