Log in

View Full Version : Moving Average and DIV32



Dick Ivers
- 29th September 2012, 02:32
Hello all,
I'm trying to calculate the the moving average of a word size variable. The formula I'm using is listed below and is standard as far as I can tell. New values of watts are added to the average when a counter is incremented by 1 in my program.


wattsAvg = (wattsAvg*counter + watts)/(counter + 1) 'moving average of watts

The results obtained are correct as as long as the numbers stay within word size limits. However, that is not the case as my numbers can range as follows:
counter : 0 to 400
watts : up to 7500 max

I think the problem would be solved with longs, but these require an 18F part. I'm using a 16F1823 as I need very small size device. I tried DIV32 as follows;

dummy = wattsAvg*counter + watts
wattsAvg = div32 (counter + 1)
This does not work. Apparently you cannot mix multiplication and addition on the dummy line. The result is always zero.

Grateful for any ideas.

aratti
- 29th September 2012, 10:35
Since you are averaging then it does not make any difference if you do your calculation on the whole number or on the difference from the average. Flag if the difference is negative, so you will know that it will be a subtraction and work with the difference, that being smaller will never overflow your word.

Cheers

Al.

Acetronics2
- 29th September 2012, 12:26
With a little help from our Friend Darrel ...


' 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


AvgCount CON 16 ' = Number of samples to average
FAspread CON 1000 ' = Fast Average threshold +/-
ADavg VAR WORD
Value VAR WORD

' -=-=-=-=-=-= Average Analog values -=-=-=-=-=-=-=-=-=-=
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)
GoTo AVGok
FastAvg:
ADavg = Value
GoTo AVGok
RealClose:
ADavg = ADavg - (ADavg/(AvgCount/4))
ADavg = ADavg + (Value/(AvgCount/4))
AVGok:
Value = ADavg ' Put Average back into Value
NoChange:
Return



found here: http://www.pbpgroup.com/modules/wfsection/article.php?articleid=7

Dick Ivers
- 29th September 2012, 15:18
Guys,
This seems to work per your suggestions:

if watts = wattsAvg then
wattsAvg = watts
endif

if watts > wattsAvg then
wattsAvg = wattsAvg + (watts - wattsAvg)/(counter + 1)
endif

if watts < wattsAvg then
wattsAvg = wattsAvg + (wattsAvg - watts)/(counter + 1)
endif

Dick Ivers
- 29th September 2012, 16:53
Disregard my last post. Upon retest the code shown did not work.

Dick Ivers
- 29th September 2012, 18:54
Please disregard this whole inquiry. I'm going down the wrong track.