Average Filter

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: