> > I would recommend a different approach. Sample as fast as you > > possibly can, then run the result thru a one or two pole low pass > > filter. You only need to store one number per pole, not one number > > per sample in the average. This type of filter (gaussian) is better > > at squashing high frequencies than the box filter you described, > > requires less state, and is generally easier to implement. The main > > drawback is the slower response, which sounds like can be much slower > > than 60Hz from your description. Make the time constant as long as > > you can tolerate to maximize the random noise reduction. It seems I > > end up doing at least a single pole filter in 90% of the projects > > that measure an analog voltage. The trick is to make the filter > > fraction a power of 2 so that it can be done with bit shifting, and > > the rest is real easy. > > You mean a software filter? Got any slick ways of performing this > trick? As I said, I would use either a single pole or double pole filter (which is really just two single pole filters cascaded). Note that for the single pole Butterworth filter FILT = (1 - F)*FILT + F*NEW the multiply by F becomes just a right shift when F = 2**(-N) where N >= 0. Rearranging the equation to FILT = FILT - F*FILT + F*NEW shows that all you need to do is two shifts and two adds. Here is one of my math library routines that perform this operation. You won't be able to assemble it outside my environment, but the algorithm should be obvious enough: ; Subroutine FILT ; ; Filter the value in REGB into REGA. REGB will be left unchanged. The ; filter fraction in bits is in REG8. REG8 must be zero or a positive ; number which determines the weighting fraction of the new value in ; REGB. This is a single pole filter operation described by the ; following equations: ; ; W = 2 ** -N ; RESULT = OLD * (1 - W) + NEW * W ; ; W is the weighting fraction for the new value in REGB. W is determined ; from N, which is the REG8 value. REGA contains OLD on entry, and ; contains RESULT on return. ; extern shiftrlb ;shift right logical of REGB by REG8 bits extern suba ;subtract REGA - REGB into REGA extern adda ;add REGA + REGB into REGA .filt code glbsub filt, regfb ; ; Remove the W fraction of REGA from itself. REGA is copied into ; REGB, REGB is then shifted the selected amount right and subtracted ; from REGA. ; movf rega+0, w ;copy REGA into REGB movwf regb+0 movf rega+1, w movwf regb+1 movf rega+2, w movwf regb+2 movf rega+3, w movwf regb+3 gcall shiftrlb ;shift REGB right to make fraction to sub from old val gcall suba ;subtract the fraction of the original value from itself ; ; Add the W fraction of the new value in REGB into REGA to make the final ; filtered result. ; popregs regfb > >tore the original REGB value movlw 4 ;diddle stack pointer so old REGB back on the stack subwf stackp gcall shiftrlb ;shift REGB right to make fraction of new value gcall adda ;add fraction of new value into REGA to make final value leaverest ***************************************************************** Olin Lathrop, embedded systems consultant in Devens Massachusetts (978) 772-3129, olin@cognivis.com, http://www.cognivis.com -- http://www.piclist.com hint: To leave the PICList mailto:piclist-unsubscribe-request@mitvma.mit.edu