Truncated match.
PICList
Thread
'Average reading of a fluctuating A/D signal?'
2000\05\19@082250
by
Quentin
My A/D input signal is such that I will always have a +/ 10 fluctuation
in my register value. Can somebody tell me how to get an average reading
over say 5 A/D samples?
Thanks
Quentin
2000\05\19@082716
by
Martin Hill
How about adding four readings together and then doing two right
shifts? Or a low pass filter on the input.
Martin
> My A/D input signal is such that I will always have a +/ 10 fluctuation
> in my register value. Can somebody tell me how to get an average reading
> over say 5 A/D samples?
>
> Thanks
> Quentin
2000\05\19@105914
by
Spehro Pefhany

At 02:01 PM 5/19/00 +0200, Quentin wrote:
>My A/D input signal is such that I will always have a +/ 10 fluctuation
>in my register value. Can somebody tell me how to get an average reading
>over say 5 A/D samples?
If your readings are periodic, one method is to pick a constant 'a'
and do value = (1a) * value + a*reading
(you might also use a flag to preload value=reading the first time.
This forms a low pass filter, and more recent values have a higher weight
than previous values. It has the advantage that it only uses one ram
location and you get a value every A/D conversion.
If you just want to take a bunch of readings in succession and average
them, just add n values together and then divide by n. Obviously you
need to avoid overflow during the add, so you might use 16 bit math
for an 8/10/12 bit A/D reading with 256/64/16 values or less being
averaged.
Best regards,
=======================================
Spehro Pefhany "it's the network..." "The Journey is the reward"
spam_OUTspeffTakeThisOuTinterlog.com Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog Info for designers: http://www.speff.com
Contributions invited>The AVRgcc FAQ is at: http://www.bluecollarlinux.com
=======================================
2000\05\19@110913
by
Scott Dattalo

On Fri, 19 May 2000, Spehro Pefhany wrote:
{Quote hidden}> At 02:01 PM 5/19/00 +0200, Quentin wrote:
> >My A/D input signal is such that I will always have a +/ 10 fluctuation
> >in my register value. Can somebody tell me how to get an average reading
> >over say 5 A/D samples?
>
> If your readings are periodic, one method is to pick a constant 'a'
>
> and do value = (1a) * value + a*reading
>
> (you might also use a flag to preload value=reading the first time.
>
> This forms a low pass filter, and more recent values have a higher weight
> than previous values. It has the advantage that it only uses one ram
> location and you get a value every A/D conversion.
>
> If you just want to take a bunch of readings in succession and average
> them, just add n values together and then divide by n. Obviously you
> need to avoid overflow during the add, so you might use 16 bit math
> for an 8/10/12 bit A/D reading with 256/64/16 values or less being
> averaged.
I guess this is a record for repeated thread frequency. Quentin, look at the
archives from just a few days back when we were talking about this exact issue
and proposed the exact solutions you've seen posted today.
Scott
2000\05\19@111536
by
KŸbek Tony

Hi,
see my posting from last week 'Digital filtering on PIC's'
and the excellent replies it generated, other techniqes than
mentioned below.
Very simple and easy to implement is an recursive moving average
filter. First, accumulate Nnumber of samples ( preferably N should
power of two factor 2,4,8 etc as there is division involved ).
For each sample: add it in an circular buffer of the same size as N,
where X(0) is first sample X(N1) is last sample.
Then calulate the first filtered value like:
( the adding could be done while collecting them )
Y(0) = [ X(0) + X(1) + ... + X(N1)] / N
Then the next ( and consecutive ) filtered value/s can be calculated
for each new sample( where the first would be X(N) ) by using:
Y(1) = Y(0) + [ X(N)  X(0)]/N
And first the next:
Y(2) = Y(1) + [ X(N+1)  X(1)]/N
Take care though for possible negative numbers when calculating
the difference between latest and oldest sample and dividing it :).
And also to elliminate roundoff errors one could always add one to the
value to divide before the latest division by 2.
If you need buffer routines or example code, please request to
me personally.
/Tony
Tony KŸbek, Flintab AB
ÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓ
Email: .....tony.kubekKILLspam@spam@flintab.com
ÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓÓ
2000\05\19@221933
by
Dan Mulally
Quentin,
If you add five 8bit samples and use two 8 bit registers for the result
(16bits) you can then do a right shift five times on the 16 bit result to
obtain an average. You need to take into account the carry from the lo byte
to the high byte.
Dan
 Original Message 
From: "Quentin" <qscKILLspamICON.CO.ZA>
To: <.....PICLISTKILLspam.....MITVMA.MIT.EDU>
Sent: Friday, May 19, 2000 6:01 AM
Subject: Average reading of a fluctuating A/D signal?
> My A/D input signal is such that I will always have a +/ 10 fluctuation
> in my register value. Can somebody tell me how to get an average reading
> over say 5 A/D samples?
>
> Thanks
> Quentin
2000\05\19@235320
by
Spehro Pefhany

At 08:18 PM 5/19/00 0600, you wrote:
>Quentin,
>
>If you add five 8bit samples and use two 8 bit registers for the result
>(16bits) you can then do a right shift five times on the 16 bit result to
>obtain an average. You need to take into account the carry from the lo byte
>to the high byte.
>
>Dan
Unh, no. Right shifting 5 x divides by 32 (2^5).
You can add 4 numbers and rightshift twice, 8 and right shift 3 x etc.
Note that if the numbers are signed you have to do an arithmetic not logical
shift (on a 2's complement number, the leftmost bit is retained, rather than
a zero being shifted in).
Best regards,
=======================================
Spehro Pefhany "it's the network..." "The Journey is the reward"
EraseMEspeffspam_OUTTakeThisOuTinterlog.com Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog Info for designers: http://www.speff.com
Contributions invited>The AVRgcc FAQ is at: http://www.bluecollarlinux.com
=======================================
2000\05\20@032049
by
paulb
Martin Hill wrote:
> How about adding four readings together and then doing two right
> shifts?
Major error in that procedure! Should be: add four readings together,
*add two* and then do two right shifts.

Cheers,
Paul B.
2000\05\20@033721
by
Quentin
Scott Dattalo wrote:
> I guess this is a record for repeated thread frequency. Quentin, look at the
> archives from just a few days back when we were talking about this exact issue
> and proposed the exact solutions you've seen posted today.
>
> Scott
I thought it was the unsubscribe thread? :)
I did have a quick look, but did not use the correct terminology.
Thanks to all that replied.
Quentin
2000\05\21@190527
by
Tony Nixon

Quentin wrote:
>
> My A/D input signal is such that I will always have a +/ 10 fluctuation
> in my register value. Can somebody tell me how to get an average reading
> over say 5 A/D samples?
>
> Thanks
> Quentin
Heres a simple setup using the FSR. Averages for 8 readings though.
CBLOCK
Average: 8h
tempH
tempL
ENDC
movlw Average ; initialise FSR
movwf FSR
...
;
; PLACE A2D RESULTS INTO A ROTATING BUFFER
;
movf ADRES,W
movwf INDF
incf FSR
movlw Average + 8h
xorwf FSR,W
btfss STATUS,Z
goto NFSR
movlw Average
movwf FSR
NFSR ...
;
; AVERAGE OUT THE 8 STORED VALUES WHEN A RESULT IS NEEDED
;
movlw Average
movwf FSR
clrf tempH
clrf tempL
avLoop movf INDF,W ; add up 8 word values
addwf tempL
btfsc STATUS,C
incf tempH
incf FSR
movlw Average + 10h
xorwf FSR,W
btfss STATUS,Z
goto avLoop
movlw Average
movwf FSR
bcf STATUS,C ; div result by 8
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
bcf STATUS,C
rrf tempH
rrf tempL
....

Best regards
Tony
http://www.picnpoke.com
salesspam_OUTpicnpoke.com
2000\05\21@194131
by
Tony Nixon
"Paul B. Webster VK2BZC" wrote:
>
> Hello Tony.
>
> > Heres a simple setup using the FSR. Averages for 8 readings though.
>
> Can't see the add 4 to temp before the divide by 8. Did you forget
> it?
> 
> Cheers,
> Paul B.
Not sure??? It's Monday morning :)
but I did muck this up. (It was originally for 8 x 16 bit values.)
avLoop movf INDF,W ; add up 8 byte values
addwf tempL
btfsc STATUS,C
incf tempH
incf FSR
movlw Average +8h
>>>(wrong)>>> movlw Average + 10h
xorwf FSR,W
btfss STATUS,Z
goto avLoop

Best regards
Tony
http://www.picnpoke.com
@spam@salesKILLspampicnpoke.com
2000\05\21@221149
by
Scott Dattalo

On Mon, 22 May 2000, Tony Nixon wrote:
{Quote hidden}>
>
> CBLOCK
> Average: 8h
> tempH
> tempL
> ENDC
>
> movlw Average ; initialise FSR
> movwf FSR
>
> ...
> ;
> ; PLACE A2D RESULTS INTO A ROTATING BUFFER
> ;
> movf ADRES,W
> movwf INDF
> incf FSR
> movlw Average + 8h
> xorwf FSR,W
> btfss STATUS,Z
> goto NFSR
>
> movlw Average
> movwf FSR
>
> NFSR ...
If you have only 8 samples, and you were willing to align the array on a mod 8
boundary, then advancing the pointer could be done easily:
incf fsr,w
andlw 7
addlw Average
movwf fsr
if you don't wish to align the array, then try this instead:
incf fsr,w
addlw Average
andlw 7
addlw Average
movwf fsr
{Quote hidden}>
> ;
> ; AVERAGE OUT THE 8 STORED VALUES WHEN A RESULT IS NEEDED
> ;
> movlw Average
> movwf FSR
> clrf tempH
> clrf tempL
>
> avLoop movf INDF,W ; add up 8 word values
> addwf tempL
> btfsc STATUS,C
> incf tempH
>
> incf FSR
> movlw Average + 10h
> xorwf FSR,W
> btfss STATUS,Z
> goto avLoop
>
> movlw Average
> movwf FSR
> bcf STATUS,C ; div result by 8
> rrf tempH
> rrf tempL
> bcf STATUS,C
> rrf tempH
> rrf tempL
> bcf STATUS,C
> rrf tempH
> rrf tempL
Again, I think the best way to maintain a running average is by subtracting the
oldest value and adding in the newest. Here's something I'll whip out as fast as
I can type it  which means there's a good chance for a thinko.
; avg_lo:avg_hi  16bit cumulative sum of last 8 samples
; samples  a circular array that holds the last 8 samples
; assume that samples and avg_lo:avg_hi are initialized to zero
;
; FSR is initialized to the start of samples
;
; W = newest sample
AVERAGE:
addwf avg_lo,f ;add newest sample to the average
skpnc
incf avg_hi,f
xorwf indf,f ; swap oldest and newest samples
xorwf indf,w
xorwf indf,f
subwf avg_lo,f ;remove the oldest sample from the average
skpc
decf avg_hi,f
incf fsr,w ;advance the sample pointer
addlw sample
andlw 7
addlw sample
movwf fsr
return
There  no more looping through all of the data after every sample is acquired.
Now, I'm assuming that the division is not needed at every iteration. I tend to
put off the difficult stuff as long as possible  often times, the intermediate
calculations are more than sufficient.
But, if you want, then this is how I'd do it:
rrf avg_hi,w
movwf temp_hi
rrf avg_lo,w
movwf temp_lo
rrf temp_hi,f
rrf temp_lo,f
rrf temp_hi,f
rrf temp_lo,w
and if you wanted rounding:
skpnc
addlw 1
(You don't need to worry about clearing the carry because the average is
guranteed to be less than or equal to 255.)
Scott
More... (looser matching)
 Last day of these posts
 In 2000
, 2001 only
 Today
 New search...