__Averaging 16 bit values without using 32 bit math__The typical way to average numbers is to add them all together and then divide by the number of samples.

However, adding several 16 bit numbers isn't easy to do in PBP because the largest variable size is 16 bits (Word).

While 32 bit or larger math is possible with PBP, sometimes it's just not worth writing the extra code.

In this case the solution is simple... Do the division first.

This simple idea yields several benefits:

- It eliminates the 32 bit math.
- It allows you to keep a running average. After each sample, the new average is available.

Otherwise you may have to wait for many samples to be taken before getting a new average value. - Response times can be improved for rapid changes in the data.

The calculation goes as follows:

- Simply choose the number of samples that you want to average and assign it to AvgCount
- Divide to current average (ADavg) by AvgCount and subtract that number from ADavg
- Divide the new Value by AvgCount and add that number to the average.

So if your AvgCount is 16 then it Reduces the average by 1/16 then adds 1/16th of the new number.

One effect of averaging can be a long delay before it "Catches up" to fast changing data. For instance, when you turn on power, it may be several seconds before the average shows the correct value of the initial data. It seems to slowly count up until finally reaching the target.

By assigning a value to FAspread you can allow it to "Catch Up" if the difference between the average and the new Value is greater that the specified amount. This will improve the appearance of the displayed numbers considerably.

( for 10 bit A/D a FAspread of 200 may be suitable, but it really depends on your application)

One drawback of "Dividing first" is that when the difference between the average and the new Value is less than the number of samples (AvgCount), the numbers being added (Value/AvgCount) are too small to make a difference due to the truncating of integer math. To overcome this, the RealClose section was added to reduce the number of samples being averaged when the two numbers are very close to each other. If you're averaging less than 8 samples, change it to (AvgCount/2) instead of (AvgCount/4)

Code:

' This routine will keep a "Running Average" ' Instead of adding a bunch of values together and then dividing by the number of samples, ' it averages each sample into the final result immediately. ' This eliminates the need for 32 bit math. ' To allow it to "Catch up" to large changes, set the FAspread to an acceptable range. ' Simply place the new number in VALUE and GoSub AVERAGE ' The Average will be returned into the same variable VALUE Symbol AvgCount = 16 ' = Number of samples to average Symbol FAspread = 1000 ' = Fast Average threshold +/- Dim ADavg as WORD Dim Value as WORD Average: If Value = ADAVG Then Nochange If ABS (Value - ADavg) > FAspread Or Value < AVGCount Then Fastavg If ABS (Value - ADavg) < AVGCount Then RealClose ADavg = ADavg - (ADavg/AVGCount) ADavg = ADavg + (Value/AVGCount) Fastavg: ADavg = Value GoTo avgok Realclose: ADavg = ADavg - (ADavg/(AVGCount/4)) ADavg = ADavg + (Value/(AVGCount/4)) Avgok: Value = ADAVG Nochange: return

Code:

Value = Value - (Value/AvgCount) Value = Value + (Raw/Avgcount)

**RAW**is the input value and

**Value**is the averaged output value.

Note that even though this last example uses less code, it will run slower because it has to do all of the math for each pass.

Article by Rcurl