# Very simple integer digital low pass filter

Low pass filters are often used to reduce higher frequency components of a signal. Electronic LP filters are for example used after a sensor to remove high frequency noise from the signal before analog to digital conversion in a micro controller. Often we want to reduce the bandwidth of the signal even more using a digital LP filter within the micro controller program.

An equation for the calculation of a first order digital low pass filter can be written as $y_{n}= y_{n-1}(1-a) + ax_{n}$

or $y_{n}= y_{n-1} -ay_{n-1} + ax_{n}$

The new filter output $y_{n}$ is calculated from the old output $y_{n-1}$ and the present input value $x$. $a (\ll 1)$ determines the filter time constant. The equation is simple and fast to compute if we have a floating point processor. But for reasonable processing rates and code size, 8 bit micro controllers use integer arithmetics.

Assume a 10 bit A/D converter. The value range of $x_{n}$ is then \$latex0 – 1023\$. For integer calculations many bits of the input signal will be lost as $a$ is smaller than 1.

Scaling the equation

We can scale the value ranges by multiplying the equation by $b=1/a$. So we get $by_{n}= by_{n-1} - y_{n-1} + bx_{n}$

Choosing the factor $b=2^{m}$ the multiplications can be substituted by an $m$-bit left shift, as implemented in C:

`y = ( ((y+x)<>m`

If the range of $x$ is $0-1024$, the output range of $y$ is $0 - 1024*2^m$. For 10 bit input and $m=6$ the output range is exactly the range of 16 bit unsigned integers. However, the intermediate $(y+x)\ll m$ product range is about $2^m$ times this. With 10 bit input and $b=2^{6}=64$ the intermediate product range is $(1024*64 + 1024)*64 = 4,259,840$. For this range at least 3 byte integers must be used. The graph shows the step response of this filter with $m=6$ and $x=1000$. The steady state value is $1000*64=64,000$. The response pass the time constant at 63%, 40,300. That is at about the 64th sample. If the sampling time is 10 msec, this corresponds to a time constant of 640 msec.

An alternative implementation

The scaled equation can also be written as $y_{n}= y_{n-1} - y_{n-1}/b + x_{n}$

Here we loose some accuracy, but as we shift the accumulated $y$ value this will lose less precision than if we shift the input value. So in C we have

`y= y + x - (y>>m)`

This function is simpler, only one shift operation and the intermediate result has a smaller range. The steady state step response value is $2^{m}$ times the input value for this implementation too. So worst case for ten bits and 6 bit shift is $y=65,535, x=1024$ and $y\gg m=1024$. In that case the sum of $x$ and $y$ exceeds the 2-byte integer range, but $(y - y\gg m) + x$ just fits within. So a better implementation is

`y= ((y - (y>>m) ) + x`

Non-integer shift

This equation is simple to modify to achieve better resolution in time constant. We introduce an extra shift operation

`y= ((y - (y>>m) - (y>>n) ) + x`

Now the effective shift value is not an integer, $m_{eff}=(m+n)/mn$. As an example, for $m= 6$ as before we get these approximate time constants and steady state output values by varying $n$: $n$ $m_{eff}$ S-s value 16 12.8 12800 32 21.3 21300 64 32 32 128 42.7 42700 256 51.2 51200

The corresponding step responses are shown in this graph for the first 100 samples. The blue dots are at the sample corresponding to $[(n+m)/nm]-1$ and 63% of the steady state value. This is the approximate time constants, measured in samples.

We can add even more shift operations to fine tune the time constant, but there really isn’t much to be gained by fine adjustment of a first order filter.

Conclusion
By restricting the time constant to an exponent of two samples we can implement a low pass filter with only addition, subtraction and shift operations. Thus, fast filter operations can be implemented for small micro controllers lacking in resources. Like the Atmel tiny series which doesn’t even have hardware integer multiplication.