The average filter that is usually used for sensor initialisation,
like setting zero of an electronic weighing scale, is basically a
re-written average formula in recursive form. Starting with the
intuitive average formula where the sum of the data points is divided by
its count:
x ‾ k = x 1 + x 2 + ⋯ + x k k \overline{x}_k = \frac{x_1 + x_2 + \dots
+ x_k}{k} x k = k x 1 + x 2 + ⋯ + x k
Multiplying both sides by k k k
yields:
k x ‾ k = x 1 + x 2 + ⋯ + x k k \overline{x}_k = x_1 + x_2 + \dots +
x_k k x k = x 1 + x 2 + ⋯ + x k
Dividing both sides by k − 1 k-1 k − 1 and
split the last term yields:
k k − 1 x ‾ k = x 1 + x 2 + ⋯ + x k k − 1 = x 1 + x 2 + ⋯ + x k − 1 k − 1 + x k k − 1 = x ‾ k − 1 + x k k − 1 \begin{array}{rl}
\frac{k}{k-1}\overline{x}_k &= \frac{x_1 + x_2 + \dots + x_k}{k-1}\\
&= \frac{x_1+x_2+\dots+x_{k-1}}{k-1} + \frac{x_k}{k-1}\\
&= \overline{x}_{k-1} + \frac{x_k}{k-1}
\end{array} k − 1 k x k = k − 1 x 1 + x 2 + ⋯ + x k = k − 1 x 1 + x 2 + ⋯ + x k − 1 + k − 1 x k = x k − 1 + k − 1 x k
Dividing again both sides by k k − 1 \frac{k}{k-1} k − 1 k results in the recursive
formula for the average:
x ‾ k = k − 1 k x ‾ k − 1 + 1 k x k \overline{x}_k =
\frac{k-1}{k}\overline{x}_{k-1} + \frac{1}{k}x_k x k = k k − 1 x k − 1 + k 1 x k
This form is similar to a low-pass filter with α : = k − 1 k = 1 − 1 k \alpha:= \frac{k-1}{k} = 1 - \frac{1}{k} α := k k − 1 = 1 − k 1
from which follows that 1 k = 1 − α \frac{1}{k} = 1 -
\alpha k 1 = 1 − α and therefore
x ‾ k = α x ‾ k − 1 + ( 1 − α ) x k \overline{x}_k =
\alpha\overline{x}_{k-1} + (1 - \alpha)x_k x k = α x k − 1 + ( 1 − α ) x k
Software implementation
let x = read_value ()
for (let k = 1 ; ; k++) {
let α = (k - 1 ) / k
x = α * x + (1 - α) * read_value ()
write_value (x)
}
Plot Measuring a 5V reading over the period of 60s with a STD of 3V can be
smoothed out quite quickly with an average filter:
-10 -6 -2 2 6 10 14 18 22 26 30 34 38 42 46 50 54 58 62 66 -10 -6 -2 2 6 10 14 18