s7-SCL-scripts/rate-limmiter.md
2026-06-01 09:40:17 +00:00

2.2 KiB

FUNCTION "FC_RateLimiter" : Void { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 VAR_INPUT analog_input : Real; // Raw input signal (setpoint or feedback) pos_slew_rate : Real := 10.0; // Max allowed increase per PLC scan (engineering units) neg_slew_rate : Real := 10.0; // Max allowed decrease per PLC scan (engineering units) enable : Bool := TRUE; // Enable rate limiting reset : Bool := FALSE; // Reset: output snaps to input immediately END_VAR

VAR_OUTPUT rate_limited_output : Real; // Slew-rate limited output END_VAR

VAR prev_output : Real; // Previous output value (retains between scans) initialized : Bool := FALSE; // First-run initialization flag END_VAR

VAR_TEMP delta : Real; // Calculated change from previous output max_rise : Real; // Clamped positive limit for this cycle max_fall : Real; // Clamped negative limit for this cycle END_VAR

BEGIN // Handle reset: snap output to input immediately IF #reset THEN #rate_limited_output := #analog_input; #prev_output := #analog_input; #initialized := TRUE; RETURN; END_IF;

// Bypass if disabled: pass-through mode
IF NOT #enable THEN
	#rate_limited_output := #analog_input;
	#prev_output := #analog_input;
	RETURN;
END_IF;

// Initialize on first run to avoid startup transient
IF NOT #initialized THEN
	#rate_limited_output := #analog_input;
	#prev_output := #analog_input;
	#initialized := TRUE;
	RETURN;
END_IF;

// Ensure slew rates are non-negative
#max_rise := ABS(#pos_slew_rate);
#max_fall := ABS(#neg_slew_rate);

// Calculate desired change
#delta := #analog_input - #prev_output;

// Apply asymmetric slew limiting
IF #delta > #max_rise THEN
	// Rising too fast: limit to max rise
	#rate_limited_output := #prev_output + #max_rise;
ELSIF #delta < -#max_fall THEN
	// Falling too fast: limit to max fall
	#rate_limited_output := #prev_output - #max_fall;
ELSE
	// Within allowed slew range: pass through
	#rate_limited_output := #analog_input;
END_IF;

// Store for next scan
#prev_output := #rate_limited_output;

END_FUNCTION