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:
\[\overline{x}_k = \frac{x_1 + x_2 + \dots + x_k}{k}\]
Multiplying both sides by \(k\) yields:
\[k \overline{x}_k = x_1 + x_2 + \dots + x_k\]
Dividing both sides by \(k-1\) and split the last term yields:
\[\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}\]
Dividing again both sides by \(\frac{k}{k-1}\) results in the recursive formula for the average:
\[\overline{x}_k = \frac{k-1}{k}\overline{x}_{k-1} + \frac{1}{k}x_k\]
This form is similar to a low-pass filter with \(\alpha:= \frac{k-1}{k} = 1 - \frac{1}{k}\) from which follows that \(\frac{1}{k} = 1 - \alpha\) and therefore
\[\overline{x}_k = \alpha\overline{x}_{k-1} + (1 - \alpha)x_k\]
Software implementation
let x = read_value() // initial 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: