From 88e893e4ad1d0fd01c2a0d9069c6e4d89eaca40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dejan=20Ro=C5=BEi=C4=8D?= Date: Fri, 20 Feb 2026 12:54:24 +0100 Subject: [PATCH] added new files for filtering --- Exponential-Moving-Average.txt | 27 +++++++++++++++++ Weighted Moving Average (WMA).txt | 49 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 Exponential-Moving-Average.txt create mode 100644 Weighted Moving Average (WMA).txt diff --git a/Exponential-Moving-Average.txt b/Exponential-Moving-Average.txt new file mode 100644 index 0000000..bb846d4 --- /dev/null +++ b/Exponential-Moving-Average.txt @@ -0,0 +1,27 @@ +#Faster response than SMA, no large buffer needed. The alpha parameter (0.0–1.0) controls smoothing — lower = more smoothing. + +FUNCTION_BLOCK FB_EMA +VAR_INPUT + xEnable : BOOL; + rInput : REAL; + rAlpha : REAL := 0.1; // Smoothing factor: 0 = max smooth, 1 = no filter +END_VAR +VAR_OUTPUT + rOutput : REAL; +END_VAR +VAR + xFirst : BOOL := TRUE; +END_VAR + +IF NOT xEnable THEN + xFirst := TRUE; + rOutput := rInput; + RETURN; +END_IF; + +IF xFirst THEN + rOutput := rInput; + xFirst := FALSE; +ELSE + rOutput := rAlpha * rInput + (1.0 - rAlpha) * rOutput; +END_IF; \ No newline at end of file diff --git a/Weighted Moving Average (WMA).txt b/Weighted Moving Average (WMA).txt new file mode 100644 index 0000000..075e6f5 --- /dev/null +++ b/Weighted Moving Average (WMA).txt @@ -0,0 +1,49 @@ +#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; \ No newline at end of file