digital filter

Hi Group,

About a year and a half ago someone (several someones actually) replied to a request for a simple digital low pass filter. I boiled it down to a single line of C, tested it and it worked great. Since then I have lost it. Used it to filter A/D readings. Anybody have this design handy?

Thanks! Doug

Reply to
Doug Dotson
Loading thread data ...

Try executing, at some interval,

filtered = (filtered + newsample) / 2.

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
     USE worldnet address!
Reply to
CBFalconer

I like having a time constant: filtered = (0.9 * filtered + 0.1 * newsample)

Play around with it, it's not hard to get useful filtering.

Kelly

Reply to
Kelly Hall

A very slight modification of this may be useful in some cases:

The equation above is in the form:

filtered = (1-k) * filtered + k * newsample

This can be written:

filtered = filtered + k * (newsample - filtered)

Mathematically, these are identical. The second one does have some practical advantages, though:

  1. with small k (long decay time) and limited calculation precision the round-off errors are smaller
  2. with non-constant k there is no need for 1-k

Computationally, the relative cost of these two ways depends on the relative cost of multiplication and addition (2 mult/1 add vs. 1 mult/2 add).

- Ville

--
Ville Voipio, Dr.Tech., M.Sc. (EE)
Reply to
Ville Voipio

I believe this is the one I remember:

I picked k to be a power of 2 so that a shift instruction could be used for speed. I try these out.

Thanks to all! Doug

Reply to
Doug Dotson

Yes, it's under "advanced search" on this webpage:

formatting link

-----

formatting link

Reply to
Ben Bradley

Hummm. That's where I looked first. I try again.

Doug

to a

single

it

Reply to
Doug Dotson

Here, and this includes my contribution to the thread:

formatting link
*embedded*+author:%22Doug+Dotson%22&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=W3Bt8.16024%24A%253.132932%40ord-read.news.verio.net&rnum=1

Best regards, Spehro Pefhany

--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
Reply to
Spehro Pefhany

That's the one! Thanks!

Doug

formatting link
*embedded*+author:%22Doug+Dotson%22&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=W3Bt8.16024%24A%253.132932%40ord-read.news.verio.net&rnum=1

formatting link

formatting link

Reply to
Doug Dotson

Here is the very simplest digital lowpass:

Y += (X-Y)*k

X = input, Y = output

Here is how k is defined:

k = 1 - exp(-Fc/Fdis))

where Fc = cutoff frequency, Fdis = sample rate

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Doug Dots>

Reply to
Vladimir Vassilevsky

Right! I picked n to be a power of 2 (8 actually in my application) and in C it turns into:

y += (x - y) >> n;

Works great!

Doug

to a

single

Used it

Reply to
Doug Dotson

I presume you mean "y += (x - y) >> p;" where "p" is the power rather than n (e.g., 3 rather than 8).

But beware...

On your platform. This revision.

There are no guarantees that right shifting a signed value will yield the result you desire. You might get zeros shifted in regardless of the actual sign of the value being shifted.

Most compilers are smart enough to make the "shift to divide by a power of two" optimization on their own. The following

y += (x - y) / n;

will be guaranteed to work, and should produce nearly identical code on your system.

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

If it doesn't, and the speed turns out to be critical, he could use unsigned ints and a bias, such as INT_MAX. The input y would have to first be corrected to INT_MAX + yin, where yin is int and y is unsigned. The filtered y would need to be initialized to INT_MAX also. This assumes that INT_MAX is roughly 1/2 of UINT_MAX.

So the result would be, more or less:

#include

unsigned int avg = INT_MAX; unsigned int sig; int input;

#define FACTOR 3

....

sig = (unsigned)input + INT_MAX) avg += (sig - avg) >> FACTOR;

which also avoids triggering UB via integer overflows.

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
     USE worldnet address!
Reply to
CBFalconer

Oops! You ae correct.

I didn't include all the contect of my application. 12 bit positive values,

32 bit words. I've been doing this programming thing for a while :)

Doug

Reply to
Doug Dotson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.