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.
- Write a Comment Select to add a comment
The next output depends upon the last out put and a fraction of the new input.
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.
Also why >>2 is performed on the already truncated A1?
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.
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: