Oversampling not working correctly

Post here first, or if you can't find a relevant section!
adc_problems
Posts: 11
Joined: Sat Sep 24, 2022 4:05 pm

Oversampling not working correctly

Post by adc_problems »

Hello Guys.
I am struggling for multiple hours now and cant explain my problem.

I try to digitize 7 analog signals with a STM32G071GB.

I started with the standard AnalogRead() implementation which worked flawlessly. However i experience some noise and wanted to accumulate longer samples ad do some oversampling.

I set up the ADC with the HAL using the build_opt.h (-DHAL_ADC_MODULE_ONLY)
and copied the STM32IDE generated initializing code into Arduino.
The init looks like this:

Code: Select all

void MX_ADC_Init()
{

  ADC_ChannelConfTypeDef sConfig = {0};

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 7;
  hadc1.Init.DiscontinuousConvMode = ENABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
  hadc1.Init.OversamplingMode = ENABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_4;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_2;
  hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;

  

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  /** Configure Regular Channel
  */
  ..............
  
My current code looks like this.

Code: Select all

switch(adc){
  case 1:
   HAL_ADC_PollForConversion(&hadc1, 1); // wait until done
   ADCbatt1 = HAL_ADC_GetValue(&hadc1);  // get value   
   HAL_ADC_Start(&hadc1);                // start conversion
   adc++;                                // set next value
   break;
  case 2:
   HAL_ADC_PollForConversion(&hadc1, 1); // wait until done
   ADCbatt2 = HAL_ADC_GetValue(&hadc1);  // get value   
   HAL_ADC_Start(&hadc1);                // start conversion
   adc++;                                // set next value
   break;
  case 3:
   HAL_ADC_PollForConversion(&hadc1, 1); // wait until done
   ADCpower_444 = HAL_ADC_GetValue(&hadc1);  // get value   
   HAL_ADC_Start(&hadc1);                // start conversion
   adc++;                                // set next value
   break;
  case 4:.....
This code does not work. First off all: It outputs the same values for ADCbatt1 / ADCbatt2 and all other channels. These values change seemingly random and after outputting 4 or 5 different values, the ADC gets "stuck" on sending the same value for all channels.

However the code works flawlessly if i do:
hadc1.Init.OversamplingMode = DISABLE;
So no oversampling produces the expected behavior e.g. different values for all 7 ADC channels and they reflect the voltage.
Activating oversampling produces no meaningful output.

I am not sure if my code is wrong or if thats some kind of bug?
dannyf
Posts: 447
Joined: Sat Jul 04, 2020 7:46 pm

Re: Oversampling not working correctly

Post by dannyf »

never used your chip and don't use hal so cannot help you there.

may want to read up the datasheet / ref manual to see how that works and what conditions it requires to operate correctly, and see if hal does it correctly.

with that said, you can use software to average a reading fairly easily. maybe worthy of a try while you try to figure this out on the hardware side.
adc_problems
Posts: 11
Joined: Sat Sep 24, 2022 4:05 pm

Re: Oversampling not working correctly

Post by adc_problems »

I am not sure if i want to do that.

I already tried and its not much better. (with 4-8 samples)

Sample accumulation /oversampling can do 256x with 8x shifting this gives quite some averaging for slower signals.

Everything i see in the data sheet says: that should work. So i am not sure why it behaves so strange.
The more i try the more i am convinced this is a bug.

I am also not quite sure why i get so much noise in the first place.
The uC is located on a custom PCB. I recently changed the uC from a Attiny to the STM32 because i needed the ram for a color display.

The ATTINY performed much much better on the ADC (keep in mind, same board, same ground plane, just different footprint).
The ATTINY got around 10-15 counts noise.
The STM32 shows more than 400 counts of noise.
As i try to measure temperatures and calculate a PID loop, too much noise will ruin the performance.

ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Oversampling not working correctly

Post by ag123 »

STM32 ADC are very sensitive and it is fast, it can pick up radio waves
viewtopic.php?p=8455#p8455
Image

I 'fixed' it by using a 1 nF capacitor to GND at the input to a OpAmp before it.
viewtopic.php?p=8509#p8509
viewtopic.php?p=8524#p8524

having an ADC that is so sensitive and decently fast is both a good and bad thing, it is "bad" as it picks up all that radio waves and it is in your input.
The good thing is that STM32 is effectively a SDR (software defined radio) on its own, it can probably easily receive and demodulate short wave radio channels by just reading it from the ADC alone.
adc_problems
Posts: 11
Joined: Sat Sep 24, 2022 4:05 pm

Re: Oversampling not working correctly

Post by adc_problems »

I just noticed that its not the ADCs fault for having such high noise.
My power supply decoupling wasnt working, i got more than 200mVpp noise on the STM32 supply..

That fix might just have eliminated the need for the software oversampling fix. However i still would want to know why this isnt working.
User avatar
MasterT
Posts: 33
Joined: Mon Apr 20, 2020 12:02 am

Re: Oversampling not working correctly

Post by MasterT »

My undersatnding, you can do both -> Scan 7 channels and Oversampling. Try w/o scan. I have oversampling x256 working on my G474re
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Oversampling not working correctly

Post by ag123 »

I hardly used 'oversampling', i've not tried prior.
What I did is review the ref manual for my specific soc e.g. stm32f103, stm32f401 etc.
The usual things that control the sample rates are - sample time, the APB clocks speed, I think there is a divisor as well?
And that if i need 'slower' - more precisely controlled but lower sample rates (up to 500k samples per sec), I used a hardware timer to drive the ADC.

Using a hardware timer to drive the ADC works very well, so much so that I made a simple DSO / DAQ out of it:
https://github.com/ag88/GirinoSTM32F103duino

then one of the way to do 'smoothing' is like :

Code: Select all


float n = 5;
float alpha = 2.0 / (n + 1);
float x0;

void setup() {
	pinMode(PA0, INPUT_ANALOG);
}

void loop() {
  x0 = analogRead(PA0);
  float ave = alpha * ave + (1 - alpha) * x0;
}

https://en.wikipedia.org/wiki/Moving_av ... ng_average
https://en.wikipedia.org/wiki/Moving_av ... MA_and_EMA

After a while, I decided that it is better to just use an RC filter that does pretty much the same thing, and it has well-defined characteristics.
Last edited by ag123 on Sun Sep 25, 2022 8:09 am, edited 1 time in total.
adc_problems
Posts: 11
Joined: Sat Sep 24, 2022 4:05 pm

Re: Oversampling not working correctly

Post by adc_problems »

I already use a RC filter.
I use a 1k NTC and got linearization resistors:

8,25k to ground in parallel with the NTC with a 825R from the supply to NTC.
That gives me a somewhat linear temperature / voltage curve from 0-60C.

The output of this got a 33n to ground to filter things a bit.
So the RC filter is essentially 825R + 33n so around 6khz -3db bandwidth.

I will try a bigger capacitor to filter some more. Afterall my temperature does not change with 3khz :D
Even 10u would be nice because 20Hz -3db is still more than fast enough.

However this external RC filter only makes the input voltage stable. If the ref voltage is moving, which is the supply of the uC, the adc measurement would still be noisy.

I found it better to not filter the ADC voltage heavily to get a little better following characteristics.

If both the voltage divider and the Vref are supplied from the same source, it’s better if both are “unstable together”. If Vref rises, the divider output voltage will also rise. Filtering will stabilize the input but not the Vref and therefore negatively impact tracking performance.
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Oversampling not working correctly

Post by ag123 »

in my circuit/experiment, I initially placed a 470uF cap between 3V3 and GND, that reduced the noises somewhat, but it did not eliminate it.

It is later when I made an attempt to 'DSO' the ADC input that i figured out it is radio waves.
If that is indeed the case, i'd think shorter wires between the ADC to the thermistor would help.
Then i placed my 1 nF RC filter, which i feel did a slightly bad but adequate removal of noise.

Reprap machines all that 3d printers - nearly all of them) used a 10 uF cap as RC filter !
https://reprap.org/mediawiki/images/f/f ... ematic.png
I think that mainly is to simplify thermistor temperature readings, instead of trying to digitally eliminate the noise, use a huge cap to pretty much remove the 'noise'. That works, but the end result is there'd be a delay before temperature change is detected. My guess is it could be as much as a few seconds worse case, that would matter say during hotend heating etc as it'd likely overshoot quite a bit before the PID control kick in and pull it back.
my guess for NTC, this is less a problem at higher temperatures, the resistance is (much) lower say vs cold where it could be say 100k ohms

in terms of digital processing, i'd think a median filter would very well eliminate noise, but that this is costly in terms of processing.
this would matter if measuring temperatures isn't the only thing the cpu needs to do.
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: Oversampling not working correctly

Post by GonzoG »

ag123 wrote: Sun Sep 25, 2022 2:38 pm
Reprap machines all that 3d printers - nearly all of them) used a 10 uF cap as RC filter !
https://reprap.org/mediawiki/images/f/f ... ematic.png
I think that mainly is to simplify thermistor temperature readings, instead of trying to digitally eliminate the noise, use a huge cap to pretty much remove the 'noise'. That works, but the end result is there'd be a delay before temperature change is detected. My guess is it could be as much as a few seconds worse case.
Your guess is wrong. Worst case it's less then a second (about 1/3 of a second)
Post Reply

Return to “General discussion”