Dale Botkin wrote: > > FILT <-- FILT*(1-F) + NEW*F > > Man, here is where I run into a wall. I am totally unfamiliar > with digital filtering techniques. What is F? Is it the inverse > of the number of samples added to the accumulator? I keep thinking > I can see how this works, but then I plug it into Excel and it > doesn't work. Should've gone for that engineering degree. Dale: The people who've been posting on this subject presumably have engineering degrees, yet they haven't been able to explain the filter clearly enough for you to understand. Don't wish for a degree; it'll only make you part of the problem. Here's how the filter works: You want to average a series of values. As you learned in grade school, this is accomplished by adding up the values, then dividing the sum by the number of values in the series. For example: Given the 8-element series 3, 5, 7, 1, 8, 4, 2, 2: 3 + 5 + 7 + 1 + 4 + 2 + 2 = 24. 24/8 = 3, so the average (or "mean") is 3. Easy, right? In your system, you have a continuous stream of new values coming in, and you want to average a "window" of the most-recent of them. In your example, you used 20 as the size of the window, but for convenience, I'll use 8. Let's say that you received the values 3, 5, 7, 1, 8, 4, 2, 2, as above, but then a new value -- 11 -- comes in, so the full series is: 3 5 7 1 8 4 2 2 11 The sum was 24, and you want to discard the oldest value and add the newest... So you subtract 3 from 24 and get 21, then you add 11 and get 32. You then divide 32 by 8 and get an average of 4. When the NEXT value came in, you'd subtract 5 from 32, add the new value, and divide by 8 again... And you'd repeat this forever. This is all pretty straightforward until you actually try to code it, at which point you'll find that you have to store as many samples as you want to average, since you need to know which one to discard when a new sample comes in. In this case, only 8 samples need to be stored, but if you wanted to average 256 samples, you'd need more RAM than is available in most PICs. This sucks; we need to store all our received samples in a big array just so we'll be able to look up the number to subtract from our sum each time. If we could just CALCULATE that number without having to look it up, we wouldn't need the big storage array, right? Well, we can't calculate it EXACTLY, but if we have a blinding flash of inspiration, we might figure out that ON AVERAGE, the number we subtract IS THE MEAN. In other words, the series: 3 5 7 1 8 4 2 2 has a sum of 24 and a mean of 3, so it's "equivalent" to the series: 3 3 3 3 3 3 3 3 which also has a sum of 24 and a mean of 3. Therefore... If we know the sum and the mean, we can subtract the mean from the sum, then add the new sample to get a new sum. We then find the new mean by dividing the new sum by the window size (8 in this example). The number we subtract will sometimes be smaller than the number we "should have" discarded, and sometimes it'll be larger, but ON AVERAGE, it'll be correct... And if you model this algorithm against the "true" average (with a QuickBASIC program or an Excel spreadsheet or whatever, you'll see that it tracks very closely. Ok... This new algorithm can be expressed as: Old Sum - Old Mean + New Sample New Mean = ------------------------------- Window Size The old sum is equal, of course, to the old mean times the window size, so we can rewrite it as: (Old Mean * Window Size) - Old Mean + New Sample New Mean = ------------------------------------------------ Window Size Simplifying: Old Mean * (Window Size - 1) + New Sample New Mean = ----------------------------------------- Window Size So for my example, it's: Old Mean * 7 + New Sample New Mean = ------------------------- 8 At this point, it'd probably be instructive to notice that this is equivalent to: New Mean = Old Mean * 7/8 + New Sample * 1/8 and if we call the mean "FILT" and assign a constant F to the value 1/8, it becomes: FILT <-- FILT * (1-F) + NEW*F which is the equation which you (previously) didn't understand. Anyway, the point of all this is that if you pick a window size that's a power of 2, the division by window size and the multiplication by (window size - 1) are trivially easy, AND... It doesn't matter how big your window size is; you can have an arbitrarily-large window size without suffering more than a tiny penalty in RAM usage and code complexity. In fact, if you choose a window size of 256, the division completely DISAPPEARS; it doesn't take ANY code to perform. To see the code required to perform this filtering algorithm with a window size of 256 (as I recall, it required less than 20 words of non-looped code), search the PICLIST archives; I posted it a few months ago. -Andy === Andrew Warren - fastfwd@ix.netcom.com === Fast Forward Engineering - San Diego, California === http://www.geocities.com/SiliconValley/2499 -- http://www.piclist.com hint: PICList Posts must start with ONE topic: [PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads