- Simulation code for Rockwell (simulation_routine_ST.L5X called before the PID routine):
// First Scan Initialization
IF S:FS THEN
// Process parameters
SIMULATION_SampleTime := 0.5; // [s]
SIMULATION_Process_Tau := 150.0; // [s]
SIMULATION_Process_Gain := 1.136; // PV/CV = 100.0/88.0
SIMULATION_Process_DeadTime := 30.0; // [s]
SIMULATION_Process_Lag_Out := 20.0; // [degC]
SIMULATION_Disturbance_Period := 240.0; // [s]
SIMULATION_Disturbance_Angle := 0.0; // [rad]
SIMULATION_Disturbance_Amplitude := 0.2; // [degC]
SIMULATION_Disturbance_Load := 0.0; // [degC]
SIMULATION_Disturbance_Load_Tau := 10.0; // [s]
SIMULATION_Disturbance_Load_Ramp := 0.0;
SIMULATION_Disturbance := 0.0;
SIMULATION_Min_PV := 20.0; // [degC]
SIMULATION_2PI := 6.28318531; //[rad]
SIMULATION_DeadTime_SampleTime_Ratio := 0;
SIMULATION_Delay_Index := 0;
SIMULATION_SIZE_DELAY_BUFFER_ARRAY := 500;
// Valve disturbance modes enabled and parameters
SIMULATION_Enable_ActuatorLag := 0;
SIMULATION_Enable_Stiction := 0;
SIMULATION_Enable_NonLinearity := 0;
SIMULATION_Stiction_S := 1.5; // Deadband [%]
SIMULATION_Stiction_J := 0.8; // Jump [%]
SIMULATION_Actuator_Tau := 2.0; // [s]
SIMULATION_Actuator_Offset := 0.1; // [%]
SIMULATION_Valve_Curve_Exp := 2.0; // [%]
SIMULATION_Delayed_CV := 0.0; // [%]
SIMULATION_Target_CV := 0.0;
SIMULATION_Lagged_CV := 0.0;
SIMULATION_Actual_CV := 0.0;
SIMULATION_Effective_CV := 0.0;
FOR i := 0 TO SIMULATION_SIZE_DELAY_BUFFER_ARRAY - 1 Do
SIMULATION_Delay_Buffer[i] := 0.0;
END_FOR;
END_IF;
// VALVE DYNAMICS
// Valve Stiction (Choudhury Model)
IF SIMULATION_Enable_Stiction THEN
IF ABS(PID_CV - SIMULATION_Target_CV) >= (SIMULATION_Stiction_S / 2.0) THEN
IF (PID_CV - SIMULATION_Target_CV) > 0.0 THEN
SIMULATION_Target_CV := PID_CV - ((SIMULATION_Stiction_S / 2.0) - SIMULATION_Stiction_J);
ELSE
SIMULATION_Target_CV := PID_CV + ((SIMULATION_Stiction_S / 2.0) - SIMULATION_Stiction_J);
END_IF;
END_IF;
IF SIMULATION_Target_CV < 0.0 THEN
SIMULATION_Target_CV := 0.0;
END_IF;
ELSE
SIMULATION_Target_CV := PID_CV;
END_IF;
// Actuator Lag and Offset (Euler - First Order Lag Filter)
IF SIMULATION_Enable_ActuatorLag THEN
SIMULATION_Lagged_CV := SIMULATION_Lagged_CV + (SIMULATION_SampleTime / SIMULATION_Actuator_Tau) * ((SIMULATION_Target_CV - SIMULATION_Actuator_Offset) - SIMULATION_Lagged_CV) ;
IF SIMULATION_Lagged_CV < 0.0 THEN
SIMULATION_Lagged_CV := 0.0;
END_IF;
ELSE
SIMULATION_Lagged_CV := SIMULATION_Target_CV;
END_IF;
// Non-Linear Flow Characteristic (Power Law Curve)
IF SIMULATION_Enable_NonLinearity THEN
IF SIMULATION_Lagged_CV > 0.0 THEN
SIMULATION_Actual_CV := 100.0 * ((SIMULATION_Lagged_CV / 100.0) ** SIMULATION_Valve_Curve_Exp);
ELSE
SIMULATION_Actual_CV := 0.0;
END_IF;
IF SIMULATION_Actual_CV < 0.0 THEN
SIMULATION_Actual_CV := 0.0;
END_IF;
ELSE
SIMULATION_Actual_CV := SIMULATION_Lagged_CV;
END_IF;
SIMULATION_Effective_CV := SIMULATION_Actual_CV;
// FOPDT PROCESS SIMULATION
// Cyclic Disturbance wave
SIMULATION_Disturbance_Angle := SIMULATION_Disturbance_Angle + ((SIMULATION_SampleTime / SIMULATION_Disturbance_Period) * SIMULATION_2PI);
IF SIMULATION_Disturbance_Angle >= SIMULATION_2PI THEN
SIMULATION_Disturbance_Angle := SIMULATION_Disturbance_Angle - SIMULATION_2PI;
END_IF;
SIMULATION_Disturbance := SIN(SIMULATION_Disturbance_Angle) * SIMULATION_Disturbance_Amplitude;
// Write CV to dead-time buffer
SIMULATION_Delay_Buffer[SIMULATION_Delay_Index] := SIMULATION_Effective_CV;
// Read CV from dead-time buffer
SIMULATION_DeadTime_SampleTime_Ratio := SIMULATION_Process_DeadTime / SIMULATION_SampleTime;
SIMULATION_Delayed_CV := SIMULATION_Delay_Buffer[(SIMULATION_Delay_Index - SIMULATION_DeadTime_SampleTime_Ratio + SIMULATION_SIZE_DELAY_BUFFER_ARRAY) MOD SIMULATION_SIZE_DELAY_BUFFER_ARRAY];
// Increment buffer index
SIMULATION_Delay_Index := (SIMULATION_Delay_Index + 1) MOD SIMULATION_SIZE_DELAY_BUFFER_ARRAY;
// Process Lag (Euler - First Order Lag Filter)
SIMULATION_Process_Lag_Out := SIMULATION_Process_Lag_Out + (SIMULATION_SampleTime / SIMULATION_Process_Tau) * ((SIMULATION_Process_Gain * SIMULATION_Delayed_CV) - SIMULATION_Process_Lag_Out);
// Load Disturbance Lag (Euler - First Order Lag Filter)
SIMULATION_Disturbance_Load_Ramp := SIMULATION_Disturbance_Load_Ramp + (SIMULATION_SampleTime / SIMULATION_Disturbance_Load_Tau) * (SIMULATION_Disturbance_Load - SIMULATION_Disturbance_Load_Ramp);
// Combine outputs
PID_PV := SIMULATION_Disturbance + SIMULATION_Process_Lag_Out + SIMULATION_Disturbance_Load_Ramp;
IF PID_PV < SIMULATION_Min_PV THEN
PID_PV := SIMULATION_Min_PV;
END_IF;
- PID block configuration and trend to validate the process simulation:
- Simulation code for Schneider (simulation.xst):
(* First Scan Initialization *)
IF FIRST_TASKRUN_RESET THEN
(* Process Parameters *)
SIMULATION_SampleTime := 0.5; (* [s] *)
SIMULATION_Process_Tau := 150.0; (* [s] *)
SIMULATION_Process_Gain := 1.136; (* PV/CV = 100.0/88.0 *)
SIMULATION_Process_DeadTime := 30.0; (* [s] *)
SIMULATION_Process_Lag_Out := 20.0; (* [degC] *)
SIMULATION_Disturbance_Period := 240.0; (* [s] *)
SIMULATION_Disturbance_Angle := 0.0; (* [rad] *)
SIMULATION_Disturbance_Amplitude := 0.2; (* [degC] *)
SIMULATION_Disturbance_Load := 0.0; (* [degC] *)
SIMULATION_Disturbance_Load_Tau := 10.0; (* [s] *)
SIMULATION_Disturbance_Load_Ramp := 0.0;
SIMULATION_Disturbance := 0.0;
SIMULATION_Min_PV := 20.0; (* [degC] *)
SIMULATION_2PI := 6.28318531; (* [rad] *)
SIMULATION_Delay_Index := 0;
SIMULATION_SIZE_ARRAY := 500;
(* Valve disturbance modes enable and parameters *)
SIMULATION_Enable_ActuatorLag := FALSE;
SIMULATION_Enable_Stiction := FALSE;
SIMULATION_Enable_NonLinearity := FALSE;
SIMULATION_Stiction_S := 1.5; (* Deadband [%] *)
SIMULATION_Stiction_J := 0.8; (* Jump [%] *)
SIMULATION_Actuator_Tau := 2.0; (* [s] *)
SIMULATION_Actuator_Offset := 0.1; (* [%] *)
SIMULATION_Valve_Curve_Exp := 2.0; (* [%] *)
SIMULATION_Delayed_CV := 0.0; (* [%] *)
SIMULATION_Target_CV := 0.0;
SIMULATION_Lagged_CV := 0.0;
SIMULATION_Actual_CV := 0.0;
SIMULATION_Effective_CV := 0.0;
(* PID parameters *)
PIDFF_PARA.pv_inf := 0.0;
PIDFF_PARA.pv_sup := 110.0;
PIDFF_PARA.out_inf := 0.0;
PIDFF_PARA.out_sup := 100.0;
PIDFF_PARA.out_min := 0.0;
PIDFF_PARA.out_max := 100.0;
PIDFF_PARA.kp := 2.5;
PIDFF_PARA.ti := t#60s;
PIDFF_PARA.td := t#12s;
(* Clear buffer array *)
FOR i := 0 TO SIMULATION_SIZE_ARRAY -1 BY 1 DO
SIMULATION_Delay_Buffer[i] := 0.0;
END_FOR;
END_IF;
(* VALVE DYNAMICS *)
(* Valve Stiction (Choudhury Model) *)
IF SIMULATION_Enable_Stiction THEN
IF ABS(PID_CV - SIMULATION_Target_CV) >= (SIMULATION_Stiction_S / 2.0) THEN
IF (PID_CV - SIMULATION_Target_CV) > 0.0 THEN
SIMULATION_Target_CV := PID_CV - ((SIMULATION_Stiction_S / 2.0) - SIMULATION_Stiction_J);
ELSE
SIMULATION_Target_CV := PID_CV + ((SIMULATION_Stiction_S / 2.0) - SIMULATION_Stiction_J);
END_IF;
END_IF;
IF SIMULATION_Target_CV < 0.0 THEN
SIMULATION_Target_CV := 0.0;
END_IF;
ELSE
SIMULATION_Target_CV := PID_CV;
END_IF;
(* Actuator Lag and Offset (Euler - First Order Lag Filter) *)
IF SIMULATION_Enable_ActuatorLag THEN
SIMULATION_Lagged_CV := SIMULATION_Lagged_CV + (SIMULATION_SampleTime / SIMULATION_Actuator_Tau) * ((SIMULATION_Target_CV - SIMULATION_Actuator_Offset) - SIMULATION_Lagged_CV) ;
IF SIMULATION_Lagged_CV < 0.0 THEN
SIMULATION_Lagged_CV := 0.0;
END_IF;
ELSE
SIMULATION_Lagged_CV := SIMULATION_Target_CV;
END_IF;
(* Non-Linear Flow Characteristic (Power Law Curve) *)
IF SIMULATION_Enable_NonLinearity THEN
IF SIMULATION_Lagged_CV > 0.0 THEN
SIMULATION_Actual_CV := 100.0 * EXPT_REAL_REAL((SIMULATION_Lagged_CV / 100.0),SIMULATION_Valve_Curve_Exp);
ELSE
SIMULATION_Actual_CV := 0.0;
END_IF;
IF SIMULATION_Actual_CV < 0.0 THEN
SIMULATION_Actual_CV := 0.0;
END_IF;
ELSE
SIMULATION_Actual_CV := SIMULATION_Lagged_CV;
END_IF;
SIMULATION_Effective_CV := SIMULATION_Actual_CV;
(* FOPDT PROCESS SIMULATION *)
(* Cyclic Disturbance wave*)
SIMULATION_Disturbance_Angle := SIMULATION_Disturbance_Angle + (( SIMULATION_SampleTime / SIMULATION_Disturbance_Period) * SIMULATION_2PI);
IF SIMULATION_Disturbance_Angle >= SIMULATION_2PI THEN
SIMULATION_Disturbance_Angle := SIMULATION_Disturbance_Angle - SIMULATION_2PI;
END_IF;
SIMULATION_Disturbance := SIN(SIMULATION_Disturbance_Angle) * SIMULATION_Disturbance_Amplitude;
(* Write CV to dead-time buffer *)
SIMULATION_Delay_Buffer[SIMULATION_Delay_Index] := SIMULATION_Effective_CV;
(* Read CV FROM dead-time buffer *)
SIMULATION_Delayed_CV := SIMULATION_Delay_Buffer[(SIMULATION_Delay_Index - REAL_TO_DINT (IN := SIMULATION_Process_DeadTime / SIMULATION_SampleTime) + SIMULATION_SIZE_ARRAY) MOD SIMULATION_SIZE_ARRAY];
(* Increment buffer index *)
SIMULATION_Delay_Index := (SIMULATION_Delay_Index + 1) MOD SIMULATION_SIZE_ARRAY;
(* Process Lag (Eurler - First Order Lag Filter *)
SIMULATION_Process_Lag_Out := SIMULATION_Process_Lag_Out + (SIMULATION_SampleTime / SIMULATION_Process_Tau) * ((SIMULATION_Process_Gain * SIMULATION_Delayed_CV) - SIMULATION_Process_Lag_Out);
(* Load Disturbance Lag (Eurler - First Order Lag Filter *)
SIMULATION_Disturbance_Load_Ramp := SIMULATION_Disturbance_Load_Ramp + (SIMULATION_SampleTime / SIMULATION_Disturbance_Load_Tau) * (SIMULATION_Disturbance_Load - SIMULATION_Disturbance_Load_Ramp);
(* Combine the lag process output with the sine wave disturbance *)
PID_PV := SIMULATION_Disturbance + SIMULATION_Process_Lag_Out + SIMULATION_Disturbance_Load_Ramp;
IF PID_PV < SIMULATION_Min_PV THEN
PID_PV := SIMULATION_Min_PV;
END_IF;
- Schneider PIDFF configuration and trend:
- Simulation code for Siemens (simulation.scl FB called before the PID routine):
FUNCTION_BLOCK "SIMULATION"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR
SIMULATION_SampleTime : Real;
SIMULATION_Process_Tau : Real;
SIMULATION_Process_Gain : Real;
SIMULATION_Process_DeadTime : Real;
SIMULATION_Process_Lag_Out : Real;
SIMULATION_Disturbance_Period : Real;
SIMULATION_Disturbance_Angle : Real;
SIMULATION_Disturbance_Amplitude : Real;
SIMULATION_Disturbance_Load : Real;
SIMULATION_Disturbance_Load_Tau : Real;
SIMULATION_Disturbance_Load_Ramp : Real;
SIMULATION_Disturbance : Real;
SIMULATION_Delayed_CV : Real;
SIMULATION_2PI : Real;
SIMULATION_Delay_Index : DInt;
SIMULATION_SIZE_DELAY_BUFFER_ARRAY : DInt;
SIMULATION_Delay_Buffer : Array[0..499] of Real;
SIMULATION_Min_PV : Real;
SIMULATION_Effective_CV : Real;
SIMULATION_Enable_ActuatorLag : Bool;
SIMULATION_Enable_Stiction : Bool;
SIMULATION_Enable_NonLinearity : Bool;
SIMULATION_Stiction_S : Real;
SIMULATION_Stiction_J : Real;
SIMULATION_Actuator_Tau : Real;
SIMULATION_Actuator_Offset : Real;
SIMULATION_Valve_Curve_Exp : Real;
SIMULATION_Target_CV : Real;
SIMULATION_Lagged_CV : Real;
SIMULATION_Actual_CV : Real;
END_VAR
VAR_TEMP
i : DInt;
END_VAR
BEGIN
// First Scan Initialization
IF "FIRSTSCAN_TP".Q THEN
// Process parameters
#SIMULATION_SampleTime := 0.5; // [s]
#SIMULATION_Process_Tau := 150.0; // [s]
#SIMULATION_Process_Gain := 1.136; // PV/CV = 100.0/88.0
#SIMULATION_Process_DeadTime := 30.0; // [s]
#SIMULATION_Process_Lag_Out := 20.0; // [degC]
#SIMULATION_Disturbance_Period := 240.0; // [s]
#SIMULATION_Disturbance_Angle := 0.0; // [rad]
#SIMULATION_Disturbance_Amplitude := 0.2; // [degC]
#SIMULATION_Disturbance_Load := 0.0; // [degC]
#SIMULATION_Disturbance_Load_Tau := 10.0; // [s]
#SIMULATION_Disturbance_Load_Ramp := 0.0;
#SIMULATION_Disturbance := 0.0;
#SIMULATION_Min_PV := 20.0; // [degC]
#SIMULATION_2PI := 6.28318531; //[rad]
#SIMULATION_Delay_Index := 0;
#SIMULATION_SIZE_DELAY_BUFFER_ARRAY := 500;
// Valve disturbance modes enabled and parameters
#SIMULATION_Enable_ActuatorLag := FALSE;
#SIMULATION_Enable_Stiction := FALSE;
#SIMULATION_Enable_NonLinearity := FALSE;
#SIMULATION_Stiction_S := 1.5; // Deadband [%]
#SIMULATION_Stiction_J := 0.8; // Jump [%]
#SIMULATION_Actuator_Tau := 2.0; // [s]
#SIMULATION_Actuator_Offset := 0.1; // [%]
#SIMULATION_Valve_Curve_Exp := 2.0; // [%]
#SIMULATION_Delayed_CV := 0.0; // [%]
#SIMULATION_Target_CV := 0.0;
#SIMULATION_Lagged_CV := 0.0;
#SIMULATION_Actual_CV := 0.0;
#SIMULATION_Effective_CV := 0.0;
FOR #i := 0 TO #SIMULATION_SIZE_DELAY_BUFFER_ARRAY - 1 DO
#SIMULATION_Delay_Buffer[#i] := 0.0;
END_FOR;
END_IF;
// VALVE DYNAMICS
// Valve Stiction (Choudhury Model)
IF #SIMULATION_Enable_Stiction THEN
IF ABS("PID_CV" - #SIMULATION_Target_CV) >= (#SIMULATION_Stiction_S / 2.0) THEN
IF ("PID_CV" - #SIMULATION_Target_CV) > 0.0 THEN
#SIMULATION_Target_CV := "PID_CV" - ((#SIMULATION_Stiction_S / 2.0) - #SIMULATION_Stiction_J);
ELSE
#SIMULATION_Target_CV := "PID_CV" + ((#SIMULATION_Stiction_S / 2.0) - #SIMULATION_Stiction_J);
END_IF;
END_IF;
IF #SIMULATION_Target_CV < 0.0 THEN
#SIMULATION_Target_CV := 0.0;
END_IF;
ELSE
#SIMULATION_Target_CV := "PID_CV";
END_IF;
// Actuator Lag and Offset (Euler - First Order Lag Filter)
IF #SIMULATION_Enable_ActuatorLag THEN
#SIMULATION_Lagged_CV := #SIMULATION_Lagged_CV + (#SIMULATION_SampleTime / #SIMULATION_Actuator_Tau) * ((#SIMULATION_Target_CV - #SIMULATION_Actuator_Offset) - #SIMULATION_Lagged_CV);
IF #SIMULATION_Lagged_CV < 0.0 THEN
#SIMULATION_Lagged_CV := 0.0;
END_IF;
ELSE
#SIMULATION_Lagged_CV := #SIMULATION_Target_CV;
END_IF;
// Non-Linear Flow Characteristic (Power Law Curve)
IF #SIMULATION_Enable_NonLinearity THEN
IF #SIMULATION_Lagged_CV > 0.0 THEN
#SIMULATION_Actual_CV := 100.0 * ((#SIMULATION_Lagged_CV / 100.0) ** #SIMULATION_Valve_Curve_Exp);
ELSE
#SIMULATION_Actual_CV := 0.0;
END_IF;
IF #SIMULATION_Actual_CV < 0.0 THEN
#SIMULATION_Actual_CV := 0.0;
END_IF;
ELSE
#SIMULATION_Actual_CV := #SIMULATION_Lagged_CV;
END_IF;
#SIMULATION_Effective_CV := #SIMULATION_Actual_CV;
// FOPDT PROCESS SIMULATION
// Cyclic Disturbance wave
#SIMULATION_Disturbance_Angle := #SIMULATION_Disturbance_Angle + ((#SIMULATION_SampleTime / #SIMULATION_Disturbance_Period) * #SIMULATION_2PI);
IF #SIMULATION_Disturbance_Angle >= #SIMULATION_2PI THEN
#SIMULATION_Disturbance_Angle := #SIMULATION_Disturbance_Angle - #SIMULATION_2PI;
END_IF;
#SIMULATION_Disturbance := SIN(#SIMULATION_Disturbance_Angle) * #SIMULATION_Disturbance_Amplitude;
// Write CV to dead-time buffer
#SIMULATION_Delay_Buffer[#SIMULATION_Delay_Index] := #SIMULATION_Effective_CV;
// Read CV from dead-time buffer
#SIMULATION_Delayed_CV := #SIMULATION_Delay_Buffer[(#SIMULATION_Delay_Index - REAL_TO_DINT(#SIMULATION_Process_DeadTime / #SIMULATION_SampleTime) + #SIMULATION_SIZE_DELAY_BUFFER_ARRAY) MOD #SIMULATION_SIZE_DELAY_BUFFER_ARRAY];
// Increment buffer index
#SIMULATION_Delay_Index := (#SIMULATION_Delay_Index + 1) MOD #SIMULATION_SIZE_DELAY_BUFFER_ARRAY;
// Process Lag (Euler - First Order Lag Filter)
#SIMULATION_Process_Lag_Out := #SIMULATION_Process_Lag_Out + (#SIMULATION_SampleTime / #SIMULATION_Process_Tau) * ((#SIMULATION_Process_Gain * #SIMULATION_Delayed_CV) - #SIMULATION_Process_Lag_Out);
// Load Disturbance Lag (Euler - First Order Lag Filter)
#SIMULATION_Disturbance_Load_Ramp := #SIMULATION_Disturbance_Load_Ramp + (#SIMULATION_SampleTime / #SIMULATION_Disturbance_Load_Tau) * (#SIMULATION_Disturbance_Load - #SIMULATION_Disturbance_Load_Ramp);
// Combine outputs
"PID_PV" := #SIMULATION_Disturbance + #SIMULATION_Process_Lag_Out + #SIMULATION_Disturbance_Load_Ramp;
IF "PID_PV" < #SIMULATION_Min_PV THEN
"PID_PV" := #SIMULATION_Min_PV;
END_IF;
END_FUNCTION_BLOCK
- Siemens PID_Compact configuration and trend:













No comments:
Post a Comment