Searching \ for '[PIC]: averaging a/d input' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ios.htm?key=a%2Fd
Search entire site for: 'averaging a/d input'.

Exact match. Not showing close matches.
'[PIC]: averaging a/d input'
2003\01\21@222228 by

I am wondering what the best method is to average an
a/d input in C.

I have an a/d tied to a fuel level sender, and am
trying to smooth the resultant value so that any quick
fluctuations in fuel level are dampened out (tilting
the tank, bumps, etc.)  I've thought of a push/pop
stack scheme to average but am afraid that would
consume too much memory.  I've also thought of
sampling the a/d once a second and taking an average
over ten seconds...

Any suggestions?

Bob

__________________________________________________
Do you Yahoo!?
http://mailplus.yahoo.com

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-requestmitvma.mit.edu>
Hard-code a queue. Example with 4 values:
Use a power of 2 so you can shift instead
of dividing.

Bob Japundza wrote:
{Quote hidden}

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-requestmitvma.mit.edu>
----- Original Message -----
From: "Bob Japundza" <bjapundzaYAHOO.COM>
To: <PICLISTMITVMA.MIT.EDU>
Sent: Tuesday, January 21, 2003 9:11 PM
Subject: [PIC]: averaging a/d input

> I am wondering what the best method is to average an
> a/d input in C.
[snip...]

Hi, Bob.

If you search the archives, you'll see that Olin has a good method of
smoothing the data.

Essentially,...
1. multiply the current reading by x, say, 3
2. add the new value to the multiplied result
3. divide by 4.

Increasing x results in  better smoothing, but slower response.

Decreasing x gives better response, but more noise.

I've used this successfully (coded in C) on a couple of projects. (thanks,
Olin.)

You might also try a median filter, where an odd number of sequential (or
multiple, when you have an MSP430 with 8 channels of built in ADC
[heresy...!]) ADC samples are put in order by magnitude, and then the center
value is chosen. Good for distributions with a well behaved central value,
punctuated by noise. I haven't tried this yet, but it looks really good for
the example given was a robot with light sensors being used to detect a
fire. The "noise" they wanted to reject, in this case, was lightning.

Mark

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-requestmitvma.mit.edu>
I had a similar problem wanting to smooth out an A/D reading monitoring the
battery voltage and current on my sailboat. I ran across some data oriented
toward the Basic Stamp (or PicBasic) :

http://www.emesystems.com/BS2math5.htm

Although this is Basic oriented, it describes the idea of a first-order
digital filter.
I'm using this scheme (though not the same code, since I'm using floating
point calculations) and it works fine. It really smooths out variations in
the signal. It's disadvantage in my case (but not in yours) is that an
intentional rapid change (e.g. someone turns on a load) the filter takes a
while to respond to this change. Which is what it is supposed to do.

Then I started looking around the net (using Google) for info on digital
filters. Here are a couple of references:

http://www.vectorsite.net/ttdsp.html

This  last one computes the co-efficients for various digital filters.

At 07:11 PM 1/21/2003 -0800, you wrote:
{Quote hidden}

--
This is in PicBasic, but it works very well:

For K= 1 TO 32
volt=volt+voltage1
PAUSE 1
Next
VOLT=volt/32

Regards,

Anand Dhuru

{Original Message removed}
> I have an a/d tied to a fuel level sender, and am
> trying to smooth the resultant value so that any quick
> fluctuations in fuel level are dampened out (tilting
> the tank, bumps, etc.)  I've thought of a push/pop
> stack scheme to average but am afraid that would
> consume too much memory.  I've also thought of
> sampling the a/d once a second and taking an average
> over ten seconds...

I like to sample the A/D as fast as possible and filter in software.  I've
mentioned this many times, so see the archives for details.  An easy
software single pole filter is:

FILT <-- FILT + (NEW - FILT) * FP

Where FILT is the filtered value, NEW the new measured input value, and FP
the filter pass parameter from 0 to 1.  Note that you can cascade these to
create multi-pole filters.  I like to use two, assuming the cycles and
memory are available.

In your case, the input is changing very slowly from the PIC's point of
view.  The easiest FP to implement is 1/256, which means the mutliply is
just picking off the high byte.  Two filters with FP of 1/256 have a 50%
step in 429 iterations.  If you want the 50% step response time to be 10
seconds, then you need to do an iteration in 10sec / 429 = 23mS.  The 90%
step response time will be 23 seconds, and the 99% step response time 40
seconds.  Sounds plenty fast enough to measure the level in a gas tank and
should smooth out the sloshes nicely.

*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
At 07:11 PM 1/21/03 -0800, you wrote:
>I am wondering what the best method is to average an
>a/d input in C.

Just skimming responses and adding a bit, here are
some options:-

1)      Do a boxcar filter by implementing something like
a circular buffer and averaging the results.
This requires enough RAM to store each result.

2)      IIR filter, the single pole version of which is

Dn = Dn-1 + K(x - Dn-1)

Where K = Ts/(Ts + Tf) (or Tf = (1/K-1)* Ts

Tf is the desired filter time constant
Ts is the periodic sample time.

By making K a 1/(2^n) you can make the calculations
faster.  Watch that there's still enough bits
left after you do the division or your filter output
can have a persistent error.

Eg.     Ts = 0.01 second
K = 1/256

you get a time constant of 2.55 seconds.

This is about the simplest possible filter, this
subject is HUGE.

3)      If your output rate is low and you can
oversample a lot, just accumulate a number n readings
then divide the result by n. n can be made a power
of two or some other number to control the reading
rate (effectively an integration period).

Best regards,

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

--
On Wed, 22 Jan 2003, Olin Lathrop wrote:

> > I have an a/d tied to a fuel level sender, and am
> > trying to smooth the resultant value so that any quick
> > fluctuations in fuel level are dampened out (tilting
> > the tank, bumps, etc.)  I've thought of a push/pop
> > stack scheme to average but am afraid that would
> > consume too much memory.  I've also thought of
> > sampling the a/d once a second and taking an average
> > over ten seconds...
>
> I like to sample the A/D as fast as possible and filter in software.  I've
> mentioned this many times, so see the archives for details.  An easy
> software single pole filter is:
>
>   FILT <-- FILT + (NEW - FILT) * FP

And everytime Olin mentions this a few suggestions pop out on how this can
be efficiently implemented. For example:

http://www.dattalo.com/technical/software/pic/twist.asm

implements this formula.

;;;    A*x + B*y
;;;  ------------
;;;     A  +  B
;;;
;;; Such that A+B = 2^N

Or re-writing:

= (A*x + B*x-B*x + B*y)/(A+B)
= x + (y-x) * B/(A+B)

x == FILT
y == NEW
B/(A+B) = FP

Scott

--
> > I have an a/d tied to a fuel level sender, and am
> > trying to smooth the resultant value so that any quick
> > fluctuations in fuel level are dampened out (tilting
> > the tank, bumps, etc.)

You can change your damping time/parameters

Jan-Erik Svderholm
S:t Anna Data

--
One complementing suggestion:
median filter instead of an averaging filter for this application. It's s
bit easier that way to get quicker response. If you have space, you can then
average your median results - it may sound silly, but you can get accuracy
and fair speed without a jumping display...
> I am wondering what the best method is to average an
> a/d input in C.
> piclist-unsubscribe-requestmitvma.mit.edu

--