s7-SCL-scripts/Weighted Moving Average (WMA).txt

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;