20 SCL Execution Order Questions
Twenty structured text questions with instant feedback, designed to train the part that really catches people out in SCL: execution order.
When people say they are struggling with SCL, the problem is often not the syntax itself. Most engineers can learn IF, CASE, assignments, timers, and function calls quickly enough. The harder part is learning to read the code in the same order the PLC executes it. That means understanding what gets solved first, what gets overwritten later, when a state change affects the next scan instead of the current one, and why a value that looks obvious on the screen can still be wrong once data types, feedbacks, and sequence timing come into play. In other words, the real skill is not just reading text. It is reading behaviour.
That is why this article is built around execution-order questions instead of passive explanation. Each problem forces the reader to decide what the PLC actually does, not what they vaguely expect it to do. Some questions look simple on purpose, because simple-looking code is exactly where bad assumptions slip through unnoticed. Others lean into timers, state logic, signal handling, and structure, because all of those areas become much easier once execution order is understood properly. If someone can work through these questions calmly and explain the answer in sequence, they are starting to read SCL the right way.
How to use this article: answer each question before you read the explanation. The goal is not to memorise tricks. The goal is to build the habit of reading SCL in execution order, scan by scan, line by line.
Try The Questions
What is the final value of MotorRunCmd at the end of this scan?
Assume StartPB := TRUE, StopPB := FALSE, and FaultActive := TRUE.
IF StartPB THEN MotorRunCmd := TRUE; END_IF; IF StopPB OR FaultActive THEN MotorRunCmd := FALSE; END_IF;
Why: SCL executes from top to bottom every scan. The first IF sets MotorRunCmd to TRUE, but the second IF is also true, so the later assignment changes it to FALSE.
Lesson: when multiple conditions can write to the same command, order matters. A cleaner pattern is often to calculate permissives and stop conditions separately, then write the final command once.
How many times does this code increment BoxCount?
Assume BoxAtSensor stays TRUE for four consecutive scans.
IF BoxAtSensor THEN BoxCount := BoxCount + 1; END_IF;
Why: the PLC evaluates this IF every scan. If BoxAtSensor stays true for four scans, the assignment runs four times.
Lesson: if the requirement is to count one physical event, you usually need a rising edge detector such as R_TRIG or equivalent previous-state logic.
Which branch runs when Temperature := 82.0?
IF Temperature > 60.0 THEN FanSpeed := 1; ELSIF Temperature > 80.0 THEN FanSpeed := 2; ELSE FanSpeed := 0; END_IF;
Why: an IF / ELSIF / ELSE chain stops on the first true condition. Since 82 is greater than 60, the first branch executes and the ELSIF is never evaluated for action.
Lesson: always order branches from most specific to least specific when thresholds overlap. In this case, the > 80.0 check should come before the > 60.0 check.
What value ends up in Ratio after this assignment?
GoodParts := 5; RejectParts := 2; Ratio := GoodParts / RejectParts;
Assume GoodParts and RejectParts are INT, and Ratio is REAL.
Why: both operands are integers, so the division is solved as integer math first. That produces 2, which is then stored into the REAL tag as 2.0.
Lesson: when you need a fractional result, cast at least one operand before dividing, for example Ratio := INT_TO_REAL(GoodParts) / RejectParts;.
What happens to ConveyorRun in this timer example?
Assume StartCmd is true for 2 seconds, then goes false. The timer preset is 3 seconds.
StartDelay(IN := StartCmd, PT := T#3s); IF StartDelay.Q THEN ConveyorRun := TRUE; ELSE ConveyorRun := FALSE; END_IF;
Why: a TON only sets Q when IN stays true continuously for the full preset time. If StartCmd drops at 2 seconds, the elapsed time resets and Q never becomes true.
Lesson: timers are scan-driven function blocks. Their behaviour only becomes intuitive when you think about what remains true, for how long, across repeated scans.
What is the final value of Step after this scan?
Assume Step := 0 before the code executes.
CASE Step OF 0: Step := 1; 1: Step := 2; END_CASE;
Why: the CASE selects its branch from the value at entry. Changing the state variable inside the branch does not cause the next branch to run in the same statement.
Lesson: this is one reason CASE-based state machines are predictable. One active state is solved per scan unless you deliberately code around that.
What value ends up in Percent?
Assume Raw is INT and Percent is REAL.
Raw := 13824; Percent := Raw / 27648 * 100.0;
Why: integer math happens first, so the ratio is truncated before it ever touches the REAL multiplier.
Lesson: scaling analog values is one of the easiest places to get believable but wrong numbers. Cast early, not at the end.
How many counts does this code add while the sensor stays high for four scans?
PartEdge(CLK := PartSensor); IF PartEdge.Q THEN PartCount := PartCount + 1; END_IF;
Why: R_TRIG-style logic turns a maintained signal into a one-scan pulse on the rising edge.
Lesson: this is the safer pattern for part counts, button edges, and one-shot commands coming from field devices.
What happens to HighLevel when the tank sits at 77.0?
Assume HighLevel was already TRUE before this scan.
IF TankLevel >= 80.0 THEN HighLevel := TRUE; ELSIF TankLevel <= 75.0 THEN HighLevel := FALSE; END_IF;
Why: hysteresis creates a hold band. The tag only changes when the signal moves above the upper threshold or below the lower threshold.
Lesson: this is one of the simplest ways to stop analog thresholds chattering around a single setpoint.
Which tag should the HMI use to show that the motor is actually running?
MotorCmd := StartReq;
MotorRunning := MotorRunFb;
MotorHealthy := MotorCmd AND MotorRunFb;Assume the HMI label is meant to represent real field status, not just a requested command.
Why: commands tell you what the PLC asked for. Feedback tells you what the field device actually did.
Lesson: a lot of misleading status pages happen because an HMI is bound to command bits instead of feedback-based status.
What happens in this state machine when StartCmd is true?
Assume State := 0 before the scan starts.
CASE State OF 0: IF StartCmd THEN State := 10; END_IF; 10: MotorCmd := TRUE; END_CASE;
Why: the active state is chosen at entry to the CASE. Changing State inside the branch affects the next scan, not the rest of the current branch selection.
Lesson: this one-scan separation is a big part of what makes well-structured state logic easy to debug.
Does the pump command turn on in the same scan that the valve-open feedback arrives?
Assume State := 20 and ValveOpenFb := TRUE.
CASE State OF 20: ValveOpenCmd := TRUE; IF ValveOpenFb THEN State := 30; END_IF; 30: PumpCmd := TRUE; END_CASE;
Why: the current scan finishes the state 20 branch. The sequence does not jump forward and solve state 30 outputs halfway through the same CASE.
Lesson: this is exactly why state machines make behaviour visible. One state owns one slice of behaviour per scan.
What happens to HeaterCmd if a fault appears in state 30?
Assume State := 30 and FaultActive := TRUE.
CASE State OF 30: IF FaultActive THEN State := 900; END_IF; HeaterCmd := TRUE; 900: HeaterCmd := FALSE; END_CASE;
Why: once state 30 is selected, that branch runs to completion. Moving the state variable to 900 does not immediately switch branch logic.
Lesson: this is one of the reasons people often separate transition decisions from output assignments inside each state.
Does Ready turn on in the same scan that the fault resets?
Assume State := 900, ResetCmd := TRUE, and FaultActive := FALSE.
CASE State OF 900: IF ResetCmd AND NOT FaultActive THEN State := 0; END_IF; 0: Ready := TRUE; END_CASE;
Why: the active CASE branch was 900 when the scan entered. The ready logic in state 0 is for the next pass.
Lesson: clean state machines make these one-scan transitions obvious instead of hiding them in scattered booleans.
Which transition condition is strongest for moving from Opening to Open?
Assume ValveOpenCmd is the PLC output request, ValveOpenFb is a real open-position feedback, OpenPB is an operator pushbutton, and OpenTimer.Q is just a timeout completion bit.
// State 20 = Opening ValveOpenCmd := TRUE; // What should decide the move to State 30 = Open?
Why: state transitions should be tied to the evidence that matters most. In field equipment, that is usually feedback, not just command intent.
Lesson: this is part of what makes state machines trustworthy. The transitions reflect actual equipment behaviour, not hopeful assumptions.
Which pattern is usually clearer for a final run command?
Why: one-write patterns reduce ambiguity. You can still build rich logic, but the final command is easy to inspect and reason about.
Lesson: structure is not just cosmetic. It changes how easy a project is to maintain and troubleshoot later.
For mutually exclusive operating modes, which representation is usually strongest?
Why: a single source of truth removes impossible combinations like Auto and Manual both being true together.
Lesson: many maintainability problems come from representation choices, not from syntax mistakes.
If a higher-level sequence wants the valve to open, which interface is better?
Why: command interfaces protect the internal behaviour of the module. Higher-level logic tells the asset what it wants, not how to implement it.
Lesson: this is a core habit in reusable equipment design and one of the reasons structured projects scale better.
Where should a reusable pump start timeout normally live?
Why: behaviour should usually live with the object that owns it. That keeps interfaces clean and avoids rebuilding the same rules in multiple places.
Lesson: good structure is often just good ownership made explicit.
Which HMI binding is usually the strongest long-term choice for a stable “Pump Running” indicator?
Assume all four tags belong to the same pump object. The HMI needs one tag that other screens, summaries, and diagnostics can trust over time. TempRunLatch is an internal latch, Status.Running is a public status bit, StartButton is an operator input, and InternalSeqStep is an internal sequence state.
Why: public status structures give the HMI a stable, deliberate interface instead of forcing it to depend on fragile internal details.
Lesson: that kind of discipline matters more as soon as the project grows beyond one engineer and one machine.
What These Questions Are Really Testing
Each question is simple on purpose. None of them asks you to memorise obscure Siemens syntax. They are testing something much more important.
- Whether you understand that SCL executes in sequence, not all at once.
- Whether you can read timers, edges, and one-scan behaviour the way the PLC actually solves them.
- Whether you separate commands, feedbacks, and typed values clearly enough to trust the result.
- Whether you understand how CASE-style state logic behaves across scans.
- Whether you can recognise stronger structure, cleaner interfaces, and better ownership patterns in real code.
If you get some of these wrong, that is not a sign you are bad at programming. It usually means you are still reading the code through the wrong mental model. That is exactly the kind of gap these small exercises are designed to fix.
Learn More
Want More Practical PLC Learning Content?
If this style of explanation is useful, my PLC and HMI Development book goes much deeper into scan behaviour, language choice, troubleshooting, and writing logic that other engineers can actually maintain.
Get the Book