Simple Moving Average of Summation / Offsets

I wrote a simple moving average with a moving window of Temperatures, read as a voltage between 0 and 10 V.

The algorithm works correctly, but it has a problem when, depending on what temperatures first fill the window, the moving average will have an offset for any values ​​that are not close to this value. For example, running this program using temp. a sensor connected to room temperature gives 4.4 V or 21.3 C. Although, if I turn off the temperature. the sensor drops to 1.4 V and the moving average remains 1.6 V. This offset decreases as the window size increases. How to remove this offset even for small window sizes, for example. 20?

REM SMA Num Must be greater than 1 #DEFINE SMANUM 20 PROGRAM 'Program 3 - Simple Moving Average Test CLEAR DIM SA(1) DIM SA0(SMANUM) : REM Moving Average Window as Array DIM LV1 DIM SV2 LV0 = 0 : REM Counter SV0 = 0 : REM Average SV1 = 0 : REM Sum WHILE(1) SA0(LV0 MOD SMANUM) = PLPROBETEMP : REM add Temperature to head of window SV1 = SV1 + SA0(LV0 MOD SMANUM) : REM add new value to sum IF(LV0 >= (SMANUM)) : REM check if we have min num of values SV1 = SV1 - SA0((LV0+1) MOD SMANUM) : REM remove oldest value from sum SV0 = SV1 / SMANUM : REM calc moving average PRINT "Avg: " ; SV0 , " Converted: " ; SV0 * 21.875 - 75 ENDIF LV0 = LV0 + 1 : REM increment counter WEND ENDP 

(Note that this is written in ACROBASIC for Parker ACR9000)

Exit - temperature sensor installed

 Raw: 4.43115 Avg: 4.41926 Converted: 21.6713125 Raw: 4.43115 Avg: 4.41938 Converted: 21.6739375 Raw: 4.43359 Avg: 4.41963 Converted: 21.67940625 Raw: 4.43359 Avg: 4.41987 Converted: 21.68465625 Raw: 4.43359 Avg: 4.42012 Converted: 21.690125 Raw: 4.43359 Avg: 4.42036 Converted: 21.695375 Raw: 4.43359 Avg: 4.42061 Converted: 21.70084375 

... remove the temperature sensor while the program is running

 Raw: 1.40625 Avg: 1.55712 Converted: -40.938 Raw: 1.40381 Avg: 1.55700 Converted: -40.940625 Raw: 1.40625 Avg: 1.55699 Converted: -40.94084375 Raw: 1.40625 Avg: 1.55699 Converted: -40.94084375 Raw: 1.40381 Avg: 1.55686 Converted: -40.9436875 Raw: 1.40381 Avg: 1.55674 Converted: -40.9463125 Raw: 1.40625 Avg: 1.55661 Converted: -40.94915625 

After removing the sensor, a noticeable bias appears between the original and the moving average.

The offset also occurs in the reverse order:

Exit - Start a program with a remote tempo sensor.

 Raw: 1.40381 Avg: 1.40550 Converted: -44.2546875 Raw: 1.40625 Avg: 1.40550 Converted: -44.2546875 Raw: 1.40625 Avg: 1.40549 Converted: -44.25490625 Raw: 1.40625 Avg: 1.40549 Converted: -44.25490625 Raw: 1.40625 Avg: 1.40548 Converted: -44.255125 Raw: 1.40625 Avg: 1.40548 Converted: -44.255125 

... connect the temperature sensor while the program is running

 Raw: 4.43848 Avg: 4.28554 Converted: 18.7461875 Raw: 4.43848 Avg: 4.28554 Converted: 18.7461875 Raw: 4.43848 Avg: 4.28554 Converted: 18.7461875 Raw: 4.43848 Avg: 4.28554 Converted: 18.7461875 Raw: 4.43848 Avg: 4.28554 Converted: 18.7461875 Raw: 4.43359 Avg: 4.28530 Converted: 18.7409375 

Again, a noticeable bias appears between the original and the moving average after attaching the sensor.

0
source share
1 answer

The problem is that the value that was subtracted from the sum was not really the oldest value in the array - the oldest value was actually overwritten with the new value in the first line of the WHILE . This was the second largest value that was subtracted from the sum.

EDIT The average and summing variable has been changed to a 64-bit floating point to lose the accuracy of time loss in the OP tip.

Ensuring that the first value is first subtracted (as soon as the array is full) gives the expected answer:

 PROGRAM 'Program 3 - Simple Moving Average Test CLEAR DIM SA(1) DIM SA0(SMANUM) : REM Moving Average Window as Array DIM LV1 DIM DV2 LV0 = 0 : REM Counter DV0 = 0 : REM Average DV1 = 0 : REM Sum WHILE(1) IF(LV0 >= (SMANUM)) : REM check if we have min num of values DV1 = DV1 - SA0(LV0 MOD SMANUM) : REM remove oldest value from sum ENDIF SA0(LV0 MOD SMANUM) = PLPROBETEMP : REM add Temperature to head of window DV1 = DV1 + SA0(LV0 MOD SMANUM) : REM add new value to sum IF(LV0 >= (SMANUM)) : REM check if we have min num of values DV0 = DV1 / SMANUM : REM calc moving average PRINT "Avg: " ; DV0 , " Converted: " ; DV0 * 21.875 - 75 ENDIF LV0 = LV0 + 1 : REM increment counter WEND 

I do not have a working BASIC environment, but I tested it in Python and received the same incorrect output for code equivalent to your version, and the expected output for code equivalent to the version I inserted above.

+1
source

Source: https://habr.com/ru/post/1479609/


All Articles