49 lines
1.2 KiB
Plaintext
49 lines
1.2 KiB
Plaintext
|
|
#More recent samples have higher weight. Better step response than SMA.
|
||
|
|
|
||
|
|
FUNCTION_BLOCK FB_WMA
|
||
|
|
VAR_INPUT
|
||
|
|
xEnable : BOOL;
|
||
|
|
rInput : REAL;
|
||
|
|
iWindowSize : INT := 8; // Max 16
|
||
|
|
END_VAR
|
||
|
|
VAR_OUTPUT
|
||
|
|
rOutput : REAL;
|
||
|
|
END_VAR
|
||
|
|
VAR
|
||
|
|
arBuffer : ARRAY[0..15] OF REAL;
|
||
|
|
iIndex : INT := 0;
|
||
|
|
iCount : INT := 0;
|
||
|
|
iWin : INT;
|
||
|
|
rWeightSum : REAL;
|
||
|
|
rValSum : REAL;
|
||
|
|
i : INT;
|
||
|
|
iPos : INT;
|
||
|
|
rWeight : REAL;
|
||
|
|
END_VAR
|
||
|
|
|
||
|
|
IF NOT xEnable THEN
|
||
|
|
iIndex := 0; iCount := 0; rOutput := rInput;
|
||
|
|
RETURN;
|
||
|
|
END_IF;
|
||
|
|
|
||
|
|
iWin := MIN(MAX(iWindowSize, 1), 16);
|
||
|
|
|
||
|
|
// Store newest sample
|
||
|
|
arBuffer[iIndex] := rInput;
|
||
|
|
iIndex := (iIndex + 1) MOD iWin;
|
||
|
|
IF iCount < iWin THEN iCount := iCount + 1; END_IF;
|
||
|
|
|
||
|
|
// Calculate weighted sum (weight = position, newest = highest)
|
||
|
|
rWeightSum := 0.0;
|
||
|
|
rValSum := 0.0;
|
||
|
|
FOR i := 0 TO iCount - 1 DO
|
||
|
|
// Most recent sample is at (iIndex - 1), going back
|
||
|
|
iPos := (iIndex - 1 - i + iWin * 2) MOD iWin;
|
||
|
|
rWeight := INT_TO_REAL(iCount - i); // Newest gets weight=iCount, oldest=1
|
||
|
|
rValSum := rValSum + arBuffer[iPos] * rWeight;
|
||
|
|
rWeightSum := rWeightSum + rWeight;
|
||
|
|
END_FOR;
|
||
|
|
|
||
|
|
IF rWeightSum > 0.0 THEN
|
||
|
|
rOutput := rValSum / rWeightSum;
|
||
|
|
END_IF;
|