Moving average filter ...

Hello -

I'm trying to implement a 'smart' moving average algorithm, which consumes as little memory (RAM) as possible.

Imagine two 8bits registers reg_8_hi and reg_8_lo. These two registes can be combined into a 16bit register, reg_16.

Algortihm is;

1 - Samples are added to reg_16. 2 - High order of reg_16, reg_8_hi is subtracted from reg_16. 3 - Average value is high order of reg_16, reg_8_hi. 4 - Registers are preloaded with reg_8_hi = 127, and reg_8_lo = 255. Which is 'best guess' on average.

Code: void MovingAvg(uchar sample) { reg_16 += sample; //add sample

reg_8_hi = reg_16 >> 8; //get high order reg_16 -= reg_8_hi; //subtract high order from total

reg_8_hi = reg_16 >> 8; //new high order (average) reg_8_lo = reg_16 & 0xFF; //new loworder }

A statement is that # of samples is size of reg_8_lo (8 bit = 255 samples),

Questions are now:

1 - is this a valid moving average algortithm ?

2 - does this algorithm have a name ?

3 - if I need lower number of samples can this algorithm be changed to; reg_8_hi and reg_3_lo. Which would then give me 8 samples. Reason for this question is that if I do;

Code: void MovingAvg(uchar sample) { reg_16 += sample; //add sample

reg_8_hi = reg_16 >> 3; //get high order reg_16 -= reg_8_hi; //subtract high order from total

reg_8_hi = reg_16 >> 3; //new high order (average) reg_3_lo = reg_16 & 0x07; //new loworder }

I get an error on the average calculation, which I'm not really able to compensate for.

Any comments ?

Best regards

Reply to
group
Loading thread data ...

It looks like you are trying to invent a 1-st order exponential averager:

y += (x - y) >> shift

This is not the same thing as the moving average, although it is certainly useful algorithm.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

snipped-for-privacy@dreamfabric.dk wrote:

Reply to
Vladimir Vassilevsky

How does such an averager compare to:

y = y * (1-f) + x * f

Meindert

Reply to
Meindert Sprang

Isn't it obvious that both equations are identical?

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

It's obvious that they are very similar, but the first seems to imply an integer representation and the second not (floating point or scaled integer maybe). I certainly isn't clear to me that the rounding is identical.

--
Peter
Reply to
Peter Dickerson

If you take x >> n to be x / (2^n) they are exactly the same mathematically. Part of me wants to insist that calling them different is picking nits -- but I suppose there are cases where one is better than the other.

I agree that the first one implies integer arithmetic (certainly it does in C, and you'd have to be a bit warped to want to define a '>>' operator for floating point in C++).

I think the rounding behavior would be quite different if y were an integer; normally if you're designing a filter like this, however, you want to design it so that the rounding doesn't matter; if you do so successfully then the _details_ of rounding won't matter either.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" gives you just what it says.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

reg_8_hi;

reg_8_lo = reg_16

reg_8_hi;

reg_3_lo = reg_16

As Vladimir mentioned you have rediscovered the 1-st order exponentially decaying filter. This is going to respond with

out(n) = sum from k = n-7 to n (in(k) (7/8)^(k-n))

So you'll never get an exact moving average.

If you choose a shift-varying difference equation you can get an average over some interval, but you can't get a _moving_ average.

What you have is a simple case of an infinite impulse response (IIR in the literature) filter, where a moving average filter is a simple case of a finite impulse response (FIR in the literature) filter.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" gives you just what it says.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

averager:

No it wasn't at first, but I did the math and indeed, you're right. Nice example of how to transform some DSP code into what works on simple 8 bitters. This should be in the book "Hackers Delight" :-)

Meindert

Reply to
Meindert Sprang

I don't think that equation is right - as you say below, he has an IIR, not an FIR (I suppose rounding will make it technically an FIR).

I like to think of these things as an approximate digital RC filter - they have a similar effect on the signals, and are just as easy to implement.

Reply to
David Brown

guess'

h order reg_16 -=3D

h order (average)

;

h order reg_16 -=3D

h order (average)

o
y
e

of

i anf=F8rselstegn -

Gentlemen -

Thank you so much for your input. Very helpful.

I kind of like the "exponential averager", however what worries me is the static error I'm left with. Is there a way to minimize this?

If I do this:

Code: void MovingAvg(uchar sample) { reg_16 +=3D sample; //add sample

reg_8_hi =3D reg_16 >> 3; //get high order reg_16 -=3D reg_8_hi; //subtract high order from total

reg_16 +=3D sample >> 6; //add a fraction to compenstae for error ??

reg_8_hi =3D reg_16 >> 3; //new high order (average) reg_3_lo =3D reg_16 & 0x07; //new loworder }

And add a fraction of the input directly to the output, will I then ruin everything, or ... ? (It seems to be working just great !!)

Best regards

Reply to
group

Nope. If you take take an apple to be an orange then it contains more vitamin C, but then we have a different animal, I mean fruit. Different rounding behaviour, different behaviour for negatives.

peter

Reply to
Peter Dickerson

You should separate the main idea from the minor technical details of the implementation.

VLV

Reply to
Vladimir Vassilevsky

Vladimir Vassilevsky escreveu:

[snipped]

And bear with the difference between expected and actual results?

Reply to
Cesar Rabak

Dangit, you're right. It should be an infinite sum, in(n-k) * (7/8)^k, k from 0 to infinity.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" gives you just what it says.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

-=

(average)

-=

(average)

Don't call it an "exponential averager" unless you're trying to make people think -- it's very commonly known as a 1st-order lowpass filter.

If you implement it correctly the only long-term error will be from quantization and truncation effects -- mathematically the filter has zero DC error (it just takes forever for the error to settle all the way to zero).

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" gives you just what it says.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

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.