FPGARelated.com
Blogs

Running Average

Mike February 15, 20166 comments

The running average filter is a useful way to reduce noise in a system.  One project I recently worked on required a 4 times frequency output from an encoder input.  The problem was the encoder is mounted to the wheel of an old truck and bearing noise was making the original algorithm generate way too many pulses.  The original algorithm worked, but the noise on the input made it useless.

I first implemented the moving average based on this description.  In my notation this is $$M_1=M_0+t_0-A_0$$ where $M_1$ is the next moving average, $M_0$ was the previous moving average, $t_0$ is the measured time between edges and $$A_0=M_0/8$$ is the "oldest" time value.  A flow chart of the algorithm looks like this:

The constant 4 added before the $>>3$ shift is a rounding operation.  This helps smooth out the randomness instead of pure truncation.  Sometimes it's high, sometimes it is low so that on average the time estimate is close to accurate.

Another way to look at this filter is $$M_1 = M_0 + (t_0 - A_0)$$ The running average changes by the difference between the new input and the previous average.  If the difference is small, the average doesn't change.  If the difference is big, it still takes a while to work through the filter before the change is noticed.  This is great for a noisy system because the noise does not pass through to the output.  But long term changes do make it through.  The larger the change, the longer it actually takes.

So in that sense this is not really an accurate moving average.  It does not subtract off the actual data previous to the 8 values which should be summed over.  For some applications this may not be useful, but for the an encoder mounted to a bad wheel bearing it works really well.




[ - ]
Comment by drjohnsmithFebruary 22, 2016
I would say what you have implemented is an exponential smoothing circuit.

https://en.wikipedia.org/wiki/Exponential_smoothing


The next output depends upon the last out put and a fraction of the new input.

[ - ]
Comment by drjohnsmithFebruary 22, 2016
Its also interesting to look at the circuit output in the frequency domain.
What you have is a low pass filter,

different frequencies going in will be attenuated by different amounts,

I found this once on a trading floor when the simple moving average filter had the effect of amplifying certain regular trades and made there values more significant to the output than the random trades.
[ - ]
Comment by drmikeFebruary 22, 2016
Yes, the whole point is to remove fast changes which is definitely a low pass filter. It isn't exactly an exponential filter, but it is definitely similar. Interesting application on the stock market!
[ - ]
Comment by odissey1March 29, 2016
Thank you for describing the filter, but can you also post a code snippet (Verilog/VHDL) for the above filter?
Also why >>2 is performed on the already truncated A1?
[ - ]
Comment by drmikeMarch 29, 2016
Unfortunately the code I have is proprietary so I can't post it. The first shift on A1 divides by 8 which is the number of terms being averaged over. The final shift gives me the 4 times frequency multiply. So the whole system averages the time between samples and divides that average by 4 so the output frequency is 4 times the input (on average). In the end, this did not solve the problem because the end user was demanding _exactly_ 4 times and that's just not possible. Especially in a noisy system.

I should point out that you can do an exact sum of 8 terms using circular buffer. For high speed this does not work too well, but if you have a lot of clocks between samples it can work fairly well.
[ - ]
Comment by tonyp12April 26, 2016
running average reading battery once an hour, don't want a intermittent voltage drop making the system thinking the battery is near death.

unsigned int temp = ADC10MEM;
battery.volt = (temp + battery.volt*3) /4; // averaging 3/4 old + 1/4 new

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Please login (on the right) if you already have an account on this platform.

Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: