> > new filt val <-- - /256 + val/256 > > Ok, I decided to try your solution since it seems good and also it is a = > bit > of a challenge to see if I can get it to work! > So far I seem to have everything working but the filter. That is = > behaving really weird. > It counts up when I'd expect it do count down, and vice versa. This statement leads me to believe you have a misconception here. Filters don't "count". They yield a sortof "running average" of the input. > And the = > low byte is=20 > just plain nuts... I suspect its the divide routine that is bad ? This doesn't sound right either. To divide an unsigned integer by 256, you shift it right 8 bits, which is one byte. It doesn't require a "divide routine" to divide your 16 bit integer by 256. The high byte of the 16 bit integer already is the quotient. That's why I suggested a divide by 256. > ; When we come here we have done 255 samples, 1 byte each for Chan A & = > B. I meant to filter EACH PULSE, not once after you've already done 255 samples. > ; The new sample value is available in sampleA > ; Now calculate the filtered values: new =3D old - old/256 + input/256 > ; Filtered output should be in FilterAH, FilterAL when done here Let's walk thru an example of a few pulses using a single filter stage. The 16 bit unsigned value LEVEL is the official "live" copy of the level that is updated as each pulse is received: level res 2 ;current tank level, 16 bit unsigned, low byte stored first Therefore, LEVEL = 65535 is the maximum level. This would be indicated by a continuous stream of 1 bits from the sensor. LEVEL = 0 is the minimum level, which is indicated by a continuous stream of 0 bits. To pick something, let's say that the current value of LEVEL is 975Ah = 38746. This indicates a level of 38746 / 65535 = .59 full. This also implies that the sensor is sending about 59 one bits and 41 zero bits out of every 100 bits. Now lets walk thru the process of receiving the next bit, which happens to be a 1 bit. First, we have to subtract LEVEL/256 from LEVEL. This is real easy, since LEVEL/256 is merely the high byte of LEVEL: movf level+1, w ;get LEVEL/256 subwf level+0 ;calculate the low byte skip_nborr ;no borrow from high byte ? decf level+1 ;propagate the borrow Since LEVEL was 975Ah, we did 975Ah - 97h = 96C3h, which is now the value of LEVEL. Now we have to add /256 into LEVEL. Since the input value is derived from a single bit, there are only two possible input values. A bit value of 1 indicates the maximum level which is represented by FFFFh, and a 0 bit indicates a level of 0000h. In this case, the input bit is 1, so we have to add FFFFh/256 = FFh: movlw h'FF' ;get value to add into LEVEL for a 1 input bit addwf level+0 ;calculate the low byte of the sum skip_ncarr ;no carry into the high byte ? incf level+1 ;propagate the carry Note that if the input bit had been zero, you would just skip this section because adding 0000h into LEVEL is simply leaving it alone. Before the add, level was 96C3h. FFh was added to this to yield 97C2h = 38850. Therefore the single 1 input bit caused the assumed level to increase from 38746/65535 = .5912 to 38850/65535 = .5928. If the input bit had been a 0 instead of a 1, LEVEL would have dropped to 96C3h/65535 = 38595/65535 = .5889. Note how each input bit adjusts LEVEL by a small amount. This will cause LEVEL to vary smoothly and reflect a sortof "running average" of recent sensor output. This kind of filter also introduces a lag, which I think is very acceptable from you earlier statements. If the level had been at minimum for a long time, then a long string of 0 bits would have been received, which would cause LEVEL to eventually go to 0. Now suppose there was an instantaneous jump to maximum of the value being measured (I know this is probably not possible, but this is to illustrate the filter response). This would result in a continuous stream of 1 bits. Starting from 0, LEVEL would get to 1/2 full scale (32768) after about 175 input bits, and to 80% full scale after about 410 input bits. Note also that the high byte of LEVEL can be used at any time as the live 0 to 255 tank level. The low byte is needed for performing the filter operation, but can be ignored for using the LEVEL value in other code. In fact, after only one filter stage with a filter fraction of 1/256, the low byte will appear to jump around randomly. You have at most 8 "good" output bits of the filter. Think of the low byte only as internal filter state in this case. Since you can tolerate a much slower response than this example, I would use two such filters cascaded. The first stage is exactly as described by this example. The second stage takes the output of the first stage as input instead of either 0 or 65535. You would then use the high byte of the second filter stage as the "official" 0 to 255 tank level value in the rest of the code. The two stage filter would yield a cleaner and less noisy value than the single stage filter. The step response of the two stage filter would be a little slower, but still well within your requirements as I understand them. The 50% step response time would be a bit over 400 samples, and the 80% response time at about 760 samples. ******************************************************************** Olin Lathrop, embedded systems consultant in Littleton Massachusetts (978) 742-9014, olin@embedinc.com, http://www.embedinc.com -- http://www.piclist.com hint: The PICList is archived three different ways. See http://www.piclist.com/#archives for details.