Is this a good averaging method ?

Thread Starter

Bogdan.m

Joined Apr 20, 2019
57
I am trying to average out my voltmeter so my screen is somewhat stable, but all i see is a delay in response. is it ok ? or any other idea ?


Code:
{for (int i = 0; i < 10; i++)
{
  V1 = ((ads.readADC_SingleEnded(0)) * 0.0001875) * 7;
  V2 = (((ads.readADC_SingleEnded(1)) * 0.0001875) - 0.588) * 20;
  V3 = (((ads.readADC_SingleEnded(2)) * 0.0001875) - 0.588) * 10;
  V4 = ((ads.readADC_SingleEnded(3)) * 0.0001875) * 8;
  delay(1);
}
{
  V1 = V1;
  V2 = V2;
  V3 = V3;
  V4 = V4;
 
Last edited:

Picbuster

Joined Dec 2, 2013
1,047
I am trying to average out my voltmeter so my screen is somewhat stable, but all i see is a delay in response. is it ok ? or any other idea ?


Code:
{for (int i = 0; i < 10; i++)
{
  V1 = ((ads.readADC_SingleEnded(0)) * 0.0001875) * 7;
  V2 = (((ads.readADC_SingleEnded(1)) * 0.0001875) - 0.588) * 20;
  V3 = (((ads.readADC_SingleEnded(2)) * 0.0001875) - 0.588) * 10;
  V4 = ((ads.readADC_SingleEnded(3)) * 0.0001875) * 8;
  delay(1);
}
{
  V1 = V1;
  V2 = V2;
  V3 = V3;
  V4 = V4;
This loop runs 10 X resulting in 10 x the same value for V(1-4)

Example simple avg (there are other types of avg's, running avg std deviation and more)
for (int n=0 ;n<10,i++)
{
The_Sum= The_Sum+value
}
avg= The_Sum/(n+1); // remark n goes from 0 to 9 = 10 x

Picbuster
 

MrChips

Joined Oct 2, 2009
30,806
I never use float data type. However, if you must use float, here is how to do moving average.
n can be any value depending on whether you want a short average or long average.
value is the new reading from the ADC.

float sum = 0.0;
float avg = 0.0;
int n = 16;

sum = sum + (value - avg);
avg = sum / n ;

If you are using integer values, then use

long sum = 0;
int avg = 0;
int n = 4;

sum = sum + (value - avg);
avg = sum >> n ;
 

joeyd999

Joined Jun 6, 2011
5,283
I never use float data type. However, if you must use float, here is how to do moving average.
n can be any value depending on whether you want a short average or long average.
value is the new reading from the ADC.

float sum = 0.0;
float avg = 0.0;
int n = 16;

sum = sum + (value - avg);
avg = sum / n ;

If you are using integer values, then use

long sum = 0;
int avg = 0;
int n = 4;

sum = sum + (value - avg);
avg = sum >> n ;
This is a first order IIR, not a moving average filter (which is a FIR, sometimes called a boxcar filter).
 

DickCappels

Joined Aug 21, 2008
10,174
Not sure I would want an IIR response in a voltmeter unless the conversion speed and the word depth allows the "infinite impulse" to diminish to an insignificant level before I lose patience. Boxcar filter, might be a better choice. Part of the problem is what is being filtered and why. If its just close to random noise getting into the converter then averaging over N samples works well.
 

Thread Starter

Bogdan.m

Joined Apr 20, 2019
57
well, the end result is this

Code:
 V1 = 0;
  V2 = 0;
  V3 = 0;
  V4 = 0;
  for (int i = 0; i < 10; i++)
  {
    V1 += ads.readADC_SingleEnded(0) * 0.0001875 * 7.0;
    V2 += (ads.readADC_SingleEnded(1) * 0.0001875 - 0.588) * 20;
    V3 += (ads.readADC_SingleEnded(2) * 0.0001875 - 0.588) * 10;
    V4 += ads.readADC_SingleEnded(3) * 0.0001875 * 8.0;
    delay(1);
  }
  V1 /= 10;
  V2 /= 10;
  V3 /= 10;
  V4 /= 10;
it works fine for now.
 

Hymie

Joined Mar 30, 2018
1,284
Probably around 40 years ago, I wrote a short program in Basic that calculated running/updated averages.

Rather than calculating the average of say 20 readings each time – the running total of the 20 readings was calculated as the difference between new sample reading (added) and the oldest sample reading (removed) then dividing by 20.
 

ci139

Joined Jul 11, 2016
1,898
you would always see a "delay" in your average

• you might go semi-predicting the next reading based on the previous (-few)
// assuming there is some sort of inertia in your input data
// (might be other than sample to sample -- might be stepped-/interleaved averages or smth. alike)

•• if your error source is "truly random" - you might work out the weights for (summing the) latest samples that give most stable/"accurate" "SUM" (average)
// it predicts the complementary/?exclusion? set for the next reading = you must know the distribution of the entire input range -- i don't think it can be used here
// but it's what i think - it also might is more likely to predict event at not exact (relatively) "far" future
? smth. like https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/96GL01478 (i didn't spend too much time to filter out these science snippets)
?? https://www.researchgate.net/post/How_do_I_calculate_the_accuracy_of_my_predictive_model (just glanced ... shortly)
 
Last edited:

WBahn

Joined Mar 31, 2012
30,058
well, the end result is this

Code:
 V1 = 0;
  V2 = 0;
  V3 = 0;
  V4 = 0;
  for (int i = 0; i < 10; i++)
  {
    V1 += ads.readADC_SingleEnded(0) * 0.0001875 * 7.0;
    V2 += (ads.readADC_SingleEnded(1) * 0.0001875 - 0.588) * 20;
    V3 += (ads.readADC_SingleEnded(2) * 0.0001875 - 0.588) * 10;
    V4 += ads.readADC_SingleEnded(3) * 0.0001875 * 8.0;
    delay(1);
  }
  V1 /= 10;
  V2 /= 10;
  V3 /= 10;
  V4 /= 10;
it works fine for now.
Is this then running in a loop?

Do you have the memory to store all forty measurements? If so, then you can add the new one and subtract the oldest one and have your display update at the sampling rate, though it will take the length of your window to see large changes settle out (but this is the same thing that happens with handheld multimeters).
 

Thread Starter

Bogdan.m

Joined Apr 20, 2019
57
i am not sure i quite understand what you are saying. As for the memory, if it helps i could make only 5 measurements in order to store them all.
 

WBahn

Joined Mar 31, 2012
30,058
Code:
samples = 10;
i = 0;
while (1)
{
   reading -= value[i];
   value[i] = getVoltage() / samples;
   reading += value[i];
   display(reading);
   i = (i + 1) % samples;
}
This is assuming value is a floating point array and getVoltage() returns a float.

If samples is a power of two, this can be made a lot more efficient. For instance, if there are eight samples.

Code:
lg_samples = 3;
mask = 0x07;
i = 0;
while (1)
{
   reading -= value[i];
   value[i] = getVoltage() / samples;
   reading += value[i];
   display(reading);
   i++;
   i &= mask;
}
 
Top