Searching \ for '[PIC]: - Who is awake?' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: '- Who is awake?'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: - Who is awake?'
2000\06\15@063104 by Andrew Warren

face
flavicon
face
Plunkett, Dennis <spam_OUTPICLISTTakeThisOuTspamMITVMA.MIT.EDU> wrote:

> A short time ago there was a thread on filters, and a suggestion
> for a long term averaging filter was proposed that went along the
> lines of:-
>
> average = (((temp*width)-average)+newsample)/width

   Actually, Dennis, it was probably:

       average = (((average*width)-average)+newsample)/width

   which is usually simplified to:

       average = (average * (width-1) + newsample) / width.

> 1/ This filter assumes that the processor is a floating point

   No; the equation is EASILY implemented using integer math.  It
   works like this:

   1.  Since integer division by a power of 2 is trivial, we make
   "width" equal to a power of 2.

   2.  Since multiplication by a power of 2 is also trivial, we
   rewrite the equation thusly:

       average = ((newsample-average) + (width*average)) / width

   If we can make width = 256, the code is absurdly simple... But
   that's a special case.  Here's the code for width = 16, which is
   more representative of what'll usually be required:

   ; Written by Andrew Warren (.....fastfwdKILLspamspam@spam@ix.netcom.com).
   ;
   ;       (NEW - AVE) + 16*AVE
   ; AVE = --------------------
   ;               16

   NEW     EQU     [ANY FILE REGISTER]   ;HOLDS NEW SAMPLE [0-255].
   AVE     EQU     [ANY FILE REGISTER[   ;HOLDS THE AVERAGE [0-255].
   AVFRAC  EQU     [ANY FILE REGISTER]   ;HOLDS THE FRACTIONAL PART
                                         ;OF THE AVERAGE [0-15].
   TEMP    EQU     [ANY FILE REGISTER]   ;TEMPORARY STORAGE.

   FILTER:

           MOVLW   00001111B       ;MASK OFF ALL BUT THE FRACTIONAL
           ANDWF   AVFRAC          ;PART OF THE OLD AVERAGE
                                   ;(AVFRAC'S HI-NIBBLE CAN
                                   ;CONTAIN GARBAGE).

           MOVF    AVE,W           ;NEW = NEW - AVE.
           SUBWF   NEW             ;CARRY = 0 IF THE DIFFERENCE IS
                                   ;NEGATIVE, CARRY = 1 IF POSITIVE.

           SWAPF   AVE,W           ;HI-NIBBLE OF W = MIDDLE NIBBLE
                                   ;OF 16*AVE.

           MOVWF   TEMP            ;LO-NIBBLE OF TEMP = HI-NIBBLE
                                   ;OF 16*AVE (LO-NIBBLE OF 16*AVE
                                   ;IS ALWAYS 0000).

   ; NEW CONTAINS (NEW - AVE) AND [TEMP:W] HOLDS 16*AVE.
   ; ADD THEM TOGETHER.

           SKPC                    ;IF (NEW - AVE) WAS NEGATIVE,
           DECF    TEMP            ;ADJUST THE HI-NIBBLE OF 16*AVE.

           ANDLW   11110000B       ;W = LO-BYTE OF 16*AVE.
           IORWF   AVFRAC,W        ;(INCLUDE AVE'S FRACTIONAL
                                   ;PART).

           ADDWF   NEW,W           ;W = LO-BYTE OF
                                   ;((NEW-AVE) + 16*AVE).
                                   ;CARRY = 1 IF SUM > 255,
                                   ;CARRY = 0 OTHERWISE.

           MOVWF   AVFRAC          ;LO-NIBBLE OF AVFRAC =
                                   ;FRACTIONAL PART OF FINAL
                                   ;RESULT.  HI-NIBBLE = GARBAGE.

           ANDLW   11110000B       ;W = (LO-NIBBLE OF
                                   ;((15*AVE+NEW)/16)) * 16.

           MOVWF   AVE             ;AVE = (LO-NIBBLE OF
                                   ;((15*AVE+NEW)/16)) * 16.

           SWAPF   AVE             ;AVE = LO-NIBBLE OF
                                   ;((15*AVE+NEW)/16).

   ; AVE'S LO-NIBBLE CONTAINS THE LO-NIBBLE OF THE FINAL RESULT.
   ; AVE'S HI-NIBBLE = 0000.

           SKPNC                   ;LO-NIBBLE OF TEMP =
           INCF    TEMP            ;HI-NIBBLE OF ((15*AVE+NEW)/16).

           SWAPF   TEMP,W          ;HI-NIBBLE OF W = HI-NIBBLE OF
           ANDLW   11110000B       ;((15*AVE+NEW)/16).
                                   ;LO-NIBBLE OF W = 0000.

   ; W'S HI-NIBBLE CONTAINS THE HI-NIBBLE OF THE FINAL RESULT.
   ; LO-NIBBLE = 0000.

           IORWF   AVE             ;COMBINE THE HI- AND LO-NIBBLES
                                   ;AND STORE THE FINAL RESULT IN
                                   ;AVE.

   ; AVE CONTAINS THE NEW AVERAGE.

   See?  That wasn't too hard; just 20 words of program space and
   20 instruction cycles...  And not a single floating-point
   operation anywhere in there.

> 2/ The filter is great for downward changing signals only, as an
> upward change will not be reflected until the delta is greater
> than the width

   Untrue.  In the code above, AVFRAC accumulates deltas smaller
   than the width until their sum is large enough to affect the
   average.

> 3/ The impulse response is dependant on the width etc.

   No kidding.  Isn't that, um, THE POINT?

   -Andy


=== Andrew Warren - fastfwdspamKILLspamix.netcom.com
=== Fast Forward Engineering - San Diego, California
=== http://www.geocities.com/SiliconValley/2499

2000\06\15@084335 by Scott Dattalo

face
flavicon
face
On Thu, 15 Jun 2000, Andrew Warren wrote:

> Plunkett, Dennis <.....PICLISTKILLspamspam.....MITVMA.MIT.EDU> wrote:
>
> > A short time ago there was a thread on filters, and a suggestion
> > for a long term averaging filter was proposed that went along the
> > lines of:-
> >
> > average = (((temp*width)-average)+newsample)/width
>
>     Actually, Dennis, it was probably:
>
>         average = (((average*width)-average)+newsample)/width
>
>     which is usually simplified to:
>
>         average = (average * (width-1) + newsample) / width.

Which is EXACTLY the form discussed just a few weeks ago! E.g.:

avg = (K1*avg + K2*newsample)/(K1+K2)

In this case, K1 = 15, K2 = 1 and their sum is 16.


{Quote hidden}

<SNIP>

If you wish to generalize this then check out:

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

Which weighs in at 22 cycles for a divisor of 16. Pros: the filter coefficients
are arbitrary and the filter is scalable. Cons: The 'Average' is only 8-bits
instead of 12.


Scott

PS. I doubt it's only me, but it's really refreshing to see Andy posting PIC
code again!

2000\06\16@022902 by Nikolai Golovchenko

flavicon
face
I would use all 8 bits available in AVEFRAC for fractional part. This
will reduce the round-off error to almost nothing. And I would like to
keep the input value in NEW not changed.

Also note that the averaging algorithm works only with unsigned
values. To work with signed you need first to bias the signed number
(add 2^(n-1) or xor sign bit), then calculate the average, and remove
bias (substract 2^(n-1) or xor sign bit).

And, to increase precision (or accuracy ?) I would round the final
result before using it by:
       btfsc AVEFRAC, 7
        incf AVE, w       ;w holds rounded result

The modified routine takes also 20 instruction/cycles:
       swapf AVFRAC, w         ;AVFRAC -= AVFRAC / 16
       andlw 0x0F
       subwf  AVFRAC, f         ;(no carry check is performed -
;there is no carry)

       swapf AVE, w            ;AVE:AVFRAC -= AVE / 16
       movwf TEMP
       andlw 0xF0
       subwf AVFRAC, f
       skpc
        decf AVE, f
       movf TEMP, w
       andlw 0x0F
       subwf AVE, f

       swapf NEW, w            ;AVE:AVFRAC += NEW / 16
       andlw 0xF0
       addwf AVFRAC, f
       skpnc
        incf AVE, f
       swapf NEW, w
       andlw 0x0F
       addwf AVE, f
;AVE holds the result

Nikolai

P.S. And all that stuff could be replaced by two parts :)

-----/\/\/\----o----- to PIC ADC input
              |
            -----
            -----
              |
             ===



On Thursday, June 15, 2000 Andrew Warren wrote:
{Quote hidden}

2000\06\18@142323 by Dmitry Kiryashov

flavicon
face
Hi Andrew.

I got some time and tried to rewrite your filter code to optimize
it a little bit.

The formula can be rewritten as: Ave' = Ave + ( New - Ave )/16 ;

Used the same names for variables. TEMP cell isn't used.

I having more and more believing that 12 is some magical number
for small completed code fragments. ;)

;       Initially written by Andrew Warren (RemoveMEfastfwdTakeThisOuTspamix.netcom.com).
;       Optimized by Dmitry A. Kiryashov (spamBeGonezewsspamBeGonespamaha.ru) 06/18/2000
;       12 clocks/words

Filter:
       movfw   AVE
       subwf   NEW,F   ;NEW - AVE

       swapf   NEW,W
       andlw   0x0F    ;get /16 int part
       skpc            ;result is neg?
       iorlw   0xF0    ;yes
       addwf   AVE,F

       swapf   NEW,W
       andlw   0xF0    ;get /16 frac part
       addwf   AVFRAC,F
       skpnc
       incf    AVE,F
;
;       low nibble of AVFRAC isn't used
;       so we can utilize it for other purposes ;)

WBR Dmitry.


{Quote hidden}

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...