Welcome!
cool Welcome PIC fans!
(to Pascal language fans too!)
Technical

Close General documentation

Close How to support PMP

Close Manuals

Close Tips

Other stuff

Close Documentation

Close How to support PMP

Close Off Topic

Close Today's favourites

Search




Downloads
Google

Tips - Implementing a low pass filter for ADC or any value

To minimize noise or to limit the response to a disturbing phenomenon, the ADC values may be processed by a LPF (Low Pass Filter) that may be easily implemented with a very common exponential single pole filter:

Value := Value + K*(New - Value);

Where K is of the form 1/N.

if N is chosen as a multiple of 2, the effective implementation with simple integers will be simplified a lot:

Value := (Value * (N - 1) + New) div N;

Which should be optimized by the compiler by using a final right shift.

What are the differences with a classic averaging like Value := (Sample_0 + Sample_1 + ... + Sample_n) div n?

First, if N=2 the filter is strictly equivalent to a classic average:

Value := Value + (New - Value) div 2 == Value := (Value + New) div 2 ;

Then you don't have to accumulate the values in an array or in a larger variable.
Then the response is very different (exponential instead of linear) and the exponential single pole filter will output a value as soon as the first sample is crunched.
Finally a better response may be achieved by cascading several poles with a smaller N value.

Common drawback of a pure integer implementation: The small values accuracy is lowered and Value may suffer from ceiling in the Value-N .. Value + N range.

 

To workaround this, we may use a scaled accumulator, say: a 32-bit accumulator for filtering 16-bit values.

Example:

We may use values scaled by P32 = 65536; this is optimal because 65536 = (1 shl 16).

The formula becomes:

AccValue32 := (AccValue32 * (N - 1) + NewValue32 * P32) div N;

Value16 := AccValue32 div P32;

With N = 16, and P32 = 65536 and 16-bit New16 input value, it comes:

AccValue32 := (AccValue32 * 15 + (longword(New16) shl 16) shr 4;

Value16 := hiword(AccValue32); // The filtered 16-bit output value is simply the high word of the accumulator.

At initialization (or at first input value), we do:

AccValue32 := longword(New16) shl 16;

Value16 := New16;

This is easy for the compiler's optimizer to generate fast code and there is no floor or ceiling phenomenon.


Creation date : 2010.08.13 3:44 PM
Last update : 2014.03.19 1:41 PM
Category : Tips
Page read 7977 times


Print the article Print the article


react.gifReactions to this article

Nobody gave a comment yet.
Be the first to do so!


Connection...
 Members List Members : 147
Visits of the day: Visits of the day: (3)
              PPA              funlw65              brico31   

Your Username:

Password:

[ Password lost ? ]


[ Join us ]


Member online :  Member online :
Anonymous online :  Anonymous online : 11

Total visits Total visits: 596734  

Most ever online
Most ever onlineTotal : 75

The 06/09/2013 @ 08:37


Webmaster - Infos

Ip: 54.196.198.241

Search




Friends News
Where are you from?

Sentence to think about :  Software is like sex, it’s better when it’s free.  Linus Torvalds, Free Software Foundation conference, febuary 1996.
^ Top ^