下面代码为西门子博图的一个实例功能块的SCL程序代码。
实例:PID_Temp_Multizone
FUNCTION_BLOCK "SimMultizone"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
velocity : SInt; // Mass transport velocity in %
ambTemp : Real := 20.0; // Ambient temperature
reset : Bool; // Reset block
cycle : Real := 0.1; // Cyclic interrupt time in seconds
END_VAR
VAR_OUTPUT
error : Bool; // Error occurred (block stopped working)
statusID : UInt; // Error source (see comment)
status : Word; // Error code (see comment)
maxReached : Bool; // Output of "LSim_PT1" or "LSim_PT2aper" has reached max. limit
minReached : Bool; // Output of "LSim_PT1" or "LSim_PT2aper" has reached min. limit
END_VAR
VAR_IN_OUT
zones : Array[1..#MAX] of "typeZone"; // Zone parameters
END_VAR
VAR
statZ : Array[1..#MAX] of "typeDynState"; // Internal parameters for calculation
instPT2Z : Array[1..#MAX] of "LSim_PT2aper"; // LSim_PT2aper instances
instHeatZ : Array[1..#MAX] of "LSim_PT1"; // LSim_PT1 instances for heating
instCoolZ : Array[1..#MAX] of "LSim_PT1"; // LSim_PT1 instances for cooling
END_VAR
VAR_TEMP
tempIndex : DInt;
tempKFor : Real;
tempKBack : Real;
END_VAR
VAR CONSTANT
MAX : DInt := 3; // Numbers of zones
TMLAG_HEATER : Real := 5.0; // Time constant for PT1 (heating)
TMLAG_COOLER : Real := 10.0; // Time constant for PT1 (cooling)
GAIN_ZONE : Real := 5.0; // Gain factor for PT2 (temperature)
TMLAG1_ZONE : Real := 20.0; // Time constant 1 for PT2 (temperature)
TMLAG2_ZONE : Real := 3.0; // Time constant 2 for PT2 (temperature)
K_BACK_MIN : Real := 0.1; // Minimum coupling constant backwards
K_FOR_MAX : Real := 0.3; // Maximum coupling constant forwards
K_INT : Real := 0.2; // Coupling constant internal
PT2_MAX_OUT : Real := 1000.0; // Maximum output limit for PT2 (temperature)
PT2_MIN_OUT : Real := -1000.0; // Minimum output limit for PT2 (temperature)
END_VAR
BEGIN
//===================================================================
// SIEMENS AG
// (c)Copyright 2016 All Rights reserved
//-------------------------------------------------------------------
// Tested with: S7-1200 CPU FW >= V4.2 or S7-1500 CPU FW >= V2.0
// Engineering: STEP7 V14 (TIA Portal)
// Restrictions: OB cyclic interrupt
// Requirements: SIMATIC Memory Card for using S7-1500 CPU
// Functionality: Simple simulation of coupled thermal zones
//---------------------------------------------------------------------
// Change log table:
// Version Date Expert in charge Changes applied
// 01.00.00 12.10.2016 DF CS SD CCC OS1 First released version
//=====================================================================
// Inputs:
// heating and cooling input (0..100%) for all zones
// via #instPidTempX.OutputHeat and #instPidTempX.OutputCool
// Outputs:
// the simulated temperatur for all zones
// via #zones[X].simMultizone.output
// Error handling:
// error source #statusID = z*10 + n*1; z =zone
// n = 1: FB "LSim_PT1" (instHeatZ[z])
// n = 2: FB "LSim_PT1" (instCoolZ[z])
// n = 3: FB "LSim_PT2aper" (instPT2Z[z])
//
// Example: #statusID = 21
// -> error source: FB "LSim_PT1" (instHeatZ[2])
//
// error code #status
// -> see comment #status of error source
//=====================================================================
REGION PT1
FOR #tempIndex := 1 TO #MAX DO
// Simulation of Heating and Cooling actuator logic for each thermal zone
REGION heat
// Zone Heater dynamics (PT1) 0..100%, tmLag1 = 5sek
#instHeatZ[#tempIndex](input := #zones[#tempIndex].pidTemp.outputHeat,
tmLag1 := #TMLAG_HEATER,
cycle := #cycle,
reset := #reset);
IF (#instHeatZ[#tempIndex].error = TRUE) THEN
#error := TRUE;
#statusID := 10 * DINT_TO_UINT(#tempIndex) + 1;
#status := #instHeatZ[#tempIndex].status;
RETURN;
END_IF;
END_REGION
REGION cool
// Zone Cooler dynamics (PT1) 0.100%, tmLag1 = 10sek
#instCoolZ[#tempIndex](input := #zones[#tempIndex].pidTemp.outputCool,
tmLag1 := #TMLAG_COOLER,
cycle := #cycle,
reset := #reset);
IF (#instCoolZ[#tempIndex].error = TRUE) THEN
#error := TRUE;
#statusID := 10 * DINT_TO_UINT(#tempIndex) + 2;
#status := #instCoolZ[#tempIndex].status;
RETURN;
END_IF;
END_REGION
// generate inputvariable for thermal simulation area zone
#statZ[#tempIndex].uInp := #instHeatZ[#tempIndex].output
- #instCoolZ[#tempIndex].output
+ #zones[#tempIndex].simMultizone.disturbance;
END_FOR;
END_REGION
REGION factors
//===================================================================================
// calculating the forward and backward coupling factors as a factor of
// fore example mass transport
//===================================================================================
#tempKFor := ((#K_FOR_MAX - #K_INT) / 100.0) * SINT_TO_REAL(#velocity) + #K_INT;
#tempKFor := LIMIT(MN := #K_BACK_MIN, IN := #tempKFor, MX := #K_FOR_MAX);
#tempKBack := ((#K_BACK_MIN - #K_INT) / 100.0) * SINT_TO_REAL(#velocity) + #K_INT;
#tempKBack := LIMIT(MN := #K_BACK_MIN, IN := #tempKBack, MX := #K_FOR_MAX);
FOR #tempIndex := 1 TO #MAX DO
#statZ[#tempIndex].kFor := #tempKFor;
#statZ[#tempIndex].kBack := #tempKBack;
END_FOR;
END_REGION
REGION coupling
//===================================================================================
// dynamic simulation of at least 3 thermal coupled zones
// Connection logic between thermal zones
//===================================================================================
//First zone: previous zone doesn't exist -> (#statZ[z-1].y * #statZ[z-1].kFor)= 0
#statZ[1].u := #statZ[1].uInp
- (2 * (#statZ[1].y * #statZ[1].kInt))
+ (#statZ[2].y * #statZ[2].kBack);
FOR #tempIndex := 2 TO (#MAX - 1) DO
// 1 < zone < max: #statZ[z].u := #statZ[z].uInp
// + (#statZ[z-1].y * #statZ[z-1].kFor)
// - (2 * (#statZ[z].y * #statZ[z].kint))
// + (#statZ[z+1].y * #statZ[z+1].kBack);
#statZ[#tempIndex].u := #statZ[#tempIndex].uInp
+ (#statZ[(#tempIndex - 1)].y * #statZ[(#tempIndex - 1)].kFor)
- (2 * (#statZ[#tempIndex].y * #statZ[#tempIndex].kInt))
+ (#statZ[(#tempIndex + 1)].y * #statZ[(#tempIndex + 1)].kBack);
END_FOR;
//Last zone: next Zone doesn't exist -> (#statZ[z+1].y * #statZ[z+1].kBack);)= 0
#statZ[#MAX].u := #statZ[#MAX].uInp
+ (#statZ[(#MAX - 1)].y * #statZ[(#MAX - 1)].kFor)
- (2 * (#statZ[#MAX].y * #statZ[#MAX].kInt));
END_REGION
REGION PT2
FOR #tempIndex := 1 TO #MAX DO
// dynamic Simulation of zone (PT2)
#instPT2Z[#tempIndex](input := #statZ[#tempIndex].u,
tmLag1 := #TMLAG1_ZONE,
tmLag2 := #TMLAG2_ZONE,
gain := #GAIN_ZONE,
cycle := #cycle,
maxOut := #PT2_MAX_OUT,
minOut := #PT2_MIN_OUT,
reset := #reset,
output => #statZ[#tempIndex].y);
IF (#instPT2Z[#tempIndex].error = TRUE) THEN
#error := TRUE;
#statusID := 10 * DINT_TO_UINT(#tempIndex) + 3;
#status := #instPT2Z[#tempIndex].status;
RETURN;
END_IF;
// Output of simulation model adding ambient temperature
#zones[#tempIndex].simMultizone.output := #statZ[#tempIndex].y + #ambTemp;
END_FOR;
END_REGION
FOR #tempIndex := 1 TO #MAX DO
//Reached handling (PT1 & PT2)
IF #instHeatZ[#tempIndex].maxReached OR #instCoolZ[#tempIndex].maxReached OR #instPT2Z[#tempIndex].maxReached THEN
#maxReached := TRUE;
END_IF;
IF #instHeatZ[#tempIndex].minReached OR #instCoolZ[#tempIndex].minReached OR #instPT2Z[#tempIndex].minReached THEN
#minReached := TRUE;
END_IF;
END_FOR;
IF (#reset = TRUE) THEN
#maxReached := FALSE;
#minReached := FALSE;
END_IF;
END_FUNCTION_BLOCK