Hello everyone! Today we are going to do something very practical—writing a fully functional cylinder control program for the Siemens S7-1200 PLC using SCL language. Even if you have only previously worked with Ladder Diagram (LAD), it doesn’t matter; I will explain it in detail, ensuring you can understand and follow along. Once you do, you will experience the power and elegance of SCL language.
Why use SCL to control cylinders?
Imagine a device with 10 or even 20 cylinders. If you write each one using Ladder Diagram, the program will be long and messy, making maintenance a headache later on. SCL is a language similar to high-level programming languages (like PASCAL or C), with a clear structure, particularly suitable for handling complex logic and repetitive functions. We can package all the control logic for a cylinder into a “Function Block” (FB), so in the future, each cylinder only needs to call this block and fill in different parameters—it’s a one-time effort!
1. First, let’s define the “blueprint”: variable declaration
Before we start writing the logic, we need to think about what “interfaces” and “internal components” this cylinder block will need. Create a new FB in TIA Portal, select SCL as the language, and give it an intuitive name, such as `FB_Cylinder`.
Next, we define the variables in the interface area, which is the most critical step.
1. Input: This is like the “sensory organs” of this function block, used to receive external signals.
`ManualMode` (Bool): Manual mode switch. When set to 1, this cylinder enters manual mode.
`AutoMode` (Bool): Automatic mode switch. When set to 1, this cylinder enters automatic mode.
`ExtendCmd` (Bool): Signal for the “extend” button in manual mode.
`RetractCmd` (Bool): Signal for the “retract” button in manual mode.
`SensorExtend` (Bool): Signal from the sensor connected to the cylinder’s extended position. When the cylinder is fully extended, this signal will change to 1.
`SensorRetract` (Bool): Signal from the sensor connected to the cylinder’s retracted position. When the cylinder is fully retracted, this signal will change to 1.
`TimeOut` (Time): A time parameter used to set the timeout for the cylinder’s action. For example, if the cylinder extends and does not receive the extended position signal within 5 seconds, it indicates a potential jam and should trigger an error.
2. Output: This is like the “executive organs” of this function block, used to control external devices.
`ValveExtend` (Bool): Controls the electromagnetic valve coil for extending the cylinder. When this signal is set to 1, the cylinder extends.
`ValveRetract` (Bool): Controls the electromagnetic valve coil for retracting the cylinder. When this signal is set to 1, the cylinder retracts. (Note: If it is a single-coil double-acting valve, the logic will differ; this example uses a double-coil.)
`IsExtended` (Bool): Status feedback indicating to the external program, “I am now fully extended.”
`IsRetracted` (Bool): Status feedback indicating to the external program, “I am now fully retracted.”
`Error` (Bool): Alarm signal. If the cylinder action times out or another error occurs, this signal will be set to 1.
3. InOut: We won’t use this here, so it remains empty for now.
4. Static: This is the “internal memory” of the function block, used to remember certain states, such as timers.
`TON_Timer` (TON): An instance of a delay timer, which we will use to determine action timeouts.
`CurrentState` (Int): An integer used to record the current state of the cylinder. This is the core of our state machine implementation.
2. Start “sculpting” the logic: SCL code writing
Now we will write the core logic. We will adopt the “state machine” programming concept, which is a very advanced and useful method in PLC programming. Simply put, it allows the cylinder to be in a clearly defined state at any moment (for example: idle, extending, retracting), and then switch between different states based on conditions and commands.
We write the following code in the code editing area of the FB:
// Part 1: Handle valve control in manual mode with interlocking to prevent simultaneous extension and retraction
IF ManualMode THEN
ValveExtend := ExtendCmd AND NOT ValveRetract; // Extend if the extend button is pressed and the retract valve is not energized
ValveRetract := RetractCmd AND NOT ValveExtend; // Retract if the retract button is pressed and the extend valve is not energized
END_IF;
// Part 2: Handle automatic mode using a state machine
IF AutoMode THEN
CASE #CurrentState OF
// State 0: Idle state
0:
ValveExtend := FALSE;
ValveRetract := FALSE;
#Error := FALSE; // Reset error
// If there is no error, prepare to enter the automatic loop
IF NOT #Error THEN
#CurrentState := 10; // Switch to “Preparing to Extend” state
END_IF;
// State 10: Preparing to extend – here you can add preconditions for allowing extension, such as safety light curtain not triggered
10:
#CurrentState := 20; // Unconditionally enter the extending state
// State 20: Extending
20:
ValveExtend := TRUE; // Open the extend valve
ValveRetract := FALSE;
// Start the timer to monitor for timeouts
#TON_Timer(IN := NOT #SensorExtend, PT := #TimeOut);
IF #SensorExtend THEN // If the extend position sensor is activated
ValveExtend := FALSE; // Close the valve
#TON_Timer(IN := FALSE); // Reset the timer
#CurrentState := 30; // Enter “Extension Complete” state
ELSIF #TON_Timer.Q THEN // If the timer has timed out, indicating a timeout
ValveExtend := FALSE; // Emergency close the valve
#Error := TRUE; // Trigger an error
#CurrentState := 0; // Return to idle state, waiting for error reset
END_IF;
// State 30: Extension complete, wait for a period (can add delay as needed)
30:
// Assume we wait for 2 seconds
#TON_Timer(IN := TRUE, PT := T#2S);
IF #TON_Timer.Q THEN
#CurrentState := 40; // Switch to “Preparing to Retract” state
END_IF;
// State 40: Preparing to retract
40:
#CurrentState := 50; // Unconditionally enter the retracting state
// State 50: Retracting
50:
ValveRetract := TRUE; // Open the retract valve
ValveExtend := FALSE;
#TON_Timer(IN := NOT #SensorRetract, PT := #TimeOut);
IF #SensorRetract THEN // If the retract position sensor is activated
ValveRetract := FALSE; // Close the valve
#TON_Timer(IN := FALSE);
#CurrentState := 60; // Enter “Retract Complete” state
ELSIF #TON_Timer.Q THEN // Timeout check
ValveRetract := FALSE;
#Error := TRUE;
#CurrentState := 0;
END_IF;
// State 60: Retract complete, wait for a period
60:
#TON_Timer(IN := TRUE, PT := T#2S);
IF #TON_Timer.Q THEN
#CurrentState := 10; // Loop back to “Preparing to Extend” state, starting the next cycle
END_IF;
END_CASE;
END_IF;
// Part 3: Update status feedback signals, effective in both manual and automatic modes
IsExtended := SensorExtend;
IsRetracted := SensorRetract;
3. How to use this powerful function block?
Writing the FB is just the first step; we also need to call it in OB1 (the main cyclic organization block).
1. Open OB1 in the project tree.
2. Find your newly created `FB_Cylinder` in the right-side “Instructions” window and drag it into the program segment.
3. A dialog box will pop up, prompting you to specify a background data block (Instance DB) for this FB call, such as `DB_Cylinder1`, which the system will generate automatically.
4. Now, you can associate the pins of this block with your actual I points, M points, or buttons on the HMI.
`ManualMode` -> Connect to a manual mode selection switch on an HMI
`AutoMode` -> Connect to an automatic mode selection switch on an HMI
`ExtendCmd`/`RetractCmd` -> Connect to buttons on the HMI that control this cylinder
`SensorExtend`/`SensorRetract` -> Connect to your actual input addresses, such as `I0.0` and `I0.1`
`ValveExtend`/`ValveRetract` -> Connect to your actual output addresses, such as `Q0.0` and `Q0.1`
`TimeOut` -> You can write a fixed time, such as `T#5S` (5 seconds)
4. Summary and Advanced Considerations
As you can see, this block is complete. Its benefits include:
Modularity: One block controls one cylinder, with a clear structure.
Reusability: For however many cylinders are on the device, just call this block that many times, assigning different background DBs and interface addresses, and the program size hardly increases.
Powerful functionality: Includes manual/automatic switching, interlocking, timeout alarms, and status feedback, making it very comprehensive.
Easy maintenance: If you want to modify the logic for all cylinders, you only need to change this one place inside the FB, and all instances calling it will automatically update.
Of course, this is just a basic framework; you can continue to add more features on this basis, such as:
Adding startup conditions in states 10 and 40 (Preparing to Extend/Retract), such as “only allow actions when the safety door is closed.”
Adding a `Reset` pin for manually resetting errors after a fault occurs.
Adding a stop function for the cylinder at an intermediate position.
I hope this detailed tutorial helps you open the door to SCL programming. The most important thing is to practice by typing it out in TIA Portal, downloading it to the PLC, and simulating it to test the smooth logic of state machine programming. Once you get used to it, you will definitely love it! If you encounter any issues, feel free to discuss.
Follow this account to learn more about Siemens PLC and SCL programming knowledge!