Implementing SFC Type Actions in Siemens PCS7 Steps

David Krause17 min read
HMI ProgrammingSiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Implementing SFC Type Actions in Siemens PCS7 Steps

Siemens PCS7 extends the IEC 61131-3 Sequential Function Chart (SFC) language with a class-based type system. SFC Types expose the Actions (technological) and Conditions (technological) tabs, which act as the typed interface between the chart logic and the underlying control blocks. Actions are placed on Steps and invoke commands; Conditions are placed on Transitions and read statuses. Both rely on the Control Module Type (CMT) and, for inter-phase orchestration, on the CmdStatLib global command and status library. This reference documents the action model in depth: object hierarchy, the meaning of the VOID data type, IF-ELSE syntax, the PCS7 V9.0 to V9.1 nesting restriction, role assignment, commissioning checks, and field-proven troubleshooting.

1. SFC Type Object Model

PCS7 organises batch and continuous phase logic into a three-tier type model. The tiers are object types in the master data library, instanced into the project:

Tier Object Purpose Source of Commands/Statuses
Asset class CMT (Control Module Type) Class template for a single asset (valve, motor, PID, dosing) SFC interface tab on the CMT (commands such as SetAuto, SetManual, SetStart)
Phase class EPHT (Equipment Phase Type) Reusable phase logic that drives one CMT Bound CMT via role assignment
Unit class EMT (Equipment Module Type) Reusable unit logic that orchestrates several phases (EPHTs or child EMTs) CmdStatLib (global commands such as SetReadyTC, StartTC, StopTC)

When the type is instanced, the instance inherits the Actions and Conditions defined on the type. The Actions tab is editable on the SFC Type and read-only on the SFC Instance. To change the action body for a deployed chart, edit the type in the master data library, recompile, and re-download the instance DBs.

2. Why the Type Model Exists

Without a type layer, an SFC would have to call block inputs directly with hard-coded instance names. That approach does not scale: a phase template for "start motor in auto" would have to be copied for every motor, and any change to the phase logic would be repeated in every copy. The type model resolves this with two abstractions:

  • Role – a placeholder symbol inside the type's action body. A role reads like a call to a real CMT (Motor.SetStart();) but the target is unbound at compile time.
  • Role assignment – a property on the EM/Phase instance that binds each role to a concrete CM instance DB in the project. At download time, the SFC compiler resolves the placeholder against the bound CM and generates direct calls.

Roles are typed. A role declared as Motor will only accept CMs whose type is a motor CMT. The SFC editor rejects the assignment otherwise, catching configuration errors at compile time.

3. Actions versus Conditions

Technological Actions and Conditions are the only fields in the SFC Type configuration dialog that expose commands and statuses. Their placement and type are fixed:

Element Placement Direction Return Type Body Contains
Action (technological) Step body Output (command) VOID CMT command calls, output assignments, IF-ELSE branches, block FB calls
Condition (technological) Transition body Input (status read) BOOL CMT status reads, comparison operators, boolean combinations

The placement rule is enforced by the SFC editor: a Condition on a Step is rejected at compile, and an Action on a Transition is rejected the same way. The asymmetry is the type-system enforcement of "actions do, conditions decide".

4. The VOID Data Type

All technological Actions are declared with the VOID return type. In the IEC 61131-3 type system, VOID denotes a procedure object that has no return value. Concretely:

  • An Action body is a procedure. It runs for its side effects (calling commands, setting outputs) and produces nothing the SFC runtime can assign.
  • You cannot bind a VOID action to a tag. There is no L-value to assign into.
  • You can write multiple statements inside a VOID action, including local FB calls, IF-ELSE branches, and assignment statements. The SFC compiler synthesises them into a method whose return type is omitted from the call site.
  • A Condition is BOOL by contrast. The transition must evaluate to TRUE or FALSE to release the step; the chart engine reads the boolean result.
Why VOID matters: A common mistake is to treat an Action as a function and try to assign its result. The compiler will reject the assignment because there is no return value. If you need a computed value, put the calculation on the EPHT/EMT interface as a tag, compute it inside the action body, and let the action write to the tag.

5. Action Execution Semantics

An Action is attached to a step and is governed by the step's SFC qualifiers. The execution lifecycle is:

  1. Step activation. The SFC runtime enters the step. Any action with the N qualifier (non-stored) begins executing immediately.
  2. Processing cycle. For as long as the step is active and the action carries no L (time-limited) or D (time-delayed) qualifier, the action body is re-evaluated on every SFC scan. This is the polled mode: the command is re-issued on every cycle until the owning step becomes inactive.
  3. Stored actions (S / R qualifiers). An action attached with S latches into the step's stored-action set and continues to execute on every scan until an R qualifier on the same or a later step removes it. S and R are the digital latching pair used for set/reset semantics.
  4. Step deactivation. When the transition fires, the step leaves. Any non-stored action is removed from the active set. Termination qualifiers in the step (a single R action or a separate Termination action) execute once on exit.

Because an action is re-evaluated each scan, an IF condition THEN command is polled, not edge-detected. If the condition stays TRUE for many scans, the command is re-issued each cycle. This is normally safe because most APL commands are idempotent on repeat issuance – the operator station acknowledges the mode change once and subsequent calls are no-ops at the operator layer. The polling is what makes the action resilient against transient glitches: a momentary loss of the command is re-asserted the next scan.

6. IF-ELSE Syntax and the V9.0 Nesting Bug

The action editor accepts structured text. A two-branch action in an EPHT reads like:

// Drive inlet valve and pump from the SFC action
IF Material.SP = 0 THEN
    Valve1.SetClose();
ELSE
    Valve1.SetOpen();
END_IF;

IF Valve1.FbkOpn = 1 THEN
    Pump1.SetStart();
ELSE
    Pump1.SetStop();
END_IF;

Important syntax rules:

  • Branches – Each THEN/ELSE arm may contain one statement, or a BEGIN ... END_BLOCK block of multiple statements. The semicolon terminates the statement.
  • ELSIF – Use ELSIF for multi-way branches; ELSEIF is also accepted by some PCS7 versions but ELSIF is the canonical spelling.
  • No inline variable declarations inside the action body. Declare locals on the EPHT/EMT interface of the type (the Interface tab in the SFC Type properties). The action body can only reference interface inputs, instance DB tags, and direct block I/O.
  • Nesting limit. Nested IF-ELSE inside actions is a known weak point in PCS7 V9.0. The compiler accepts the code, but the generated action block can take the wrong branch when the action is stored (S qualifier) or when a nested branch crosses a step-qualifier change within one SFC cycle. The published workaround is to refuse nested IF-ELSE in production action bodies. The fix is targeted for PCS7 V9.1.
Field guidance: Flatten nested logic. Convert IF A THEN IF B THEN C into IF A AND B THEN C, or move the nested decision into a separate FC/FB called from the action. Verify on PCS7 V9.1 before relying on the nested form.

7. The CMT Command and Status Surface

A CMT command is a wrapper around one or more block-contact bits. The SFC does not manipulate the bits directly; it calls the command and the APL routes the call to the correct internal structure. The default motor CMT, for example, exposes:

Command Drives Block Input Semantics
SetAuto ModLiOp = 1, AutModLi = 1 Request automatic mode
SetManual ModLiOp = 1, AutModLi = 0 Request manual mode
SetStart Start-up sequence trigger Start the motor in current mode
SetStop Stop trigger Stop the motor
SetReset ResetCmd = 1 (pulse) Clear latched faults

The CMT SFC interface tab is where these commands are added. When a new command is required, do not wire to the block input from SFC; add the command on the CMT interface so all instances of the type get the new command automatically. The standard SFC command set for valves, motors, and PID controllers is shipped in the PCS7 master data library under APL blocks > SFC interface; do not edit these shipped blocks in place – copy them into the project master data library and extend the copies.

8. The CmdStatLib for EMT-to-EMT Commands

Equipment Module Types orchestrate child Equipment Modules and Equipment Phases. The communication between a parent EM and a child EM uses the CmdStatLib, a global library of standardised commands and statuses shipped with PCS7. Default commands in the CmdStatLib include:

Command Function Status Function
SetReadyTC Move child to Ready state ReadyST Child is Ready
SetIdleTC Move child to Idle state IdleST Child is Idle
StartTC Run the child phase RunST Child is Running
StopTC Stop the child phase StoppedST Child is Stopped
HoldTC Pause the child phase HeldST Child is Held
ResumeTC Resume after Hold CompletedST Child finished its phase
AbortTC Abort the child phase AbortedST Child aborted
CompleteTC Acknowledge completion ReadyToStartST Child ready to start
ResetTC Reset child faults ErrorST Child has an error

The parent EM writes to the TC (transition command) inputs of the child EM instance, and reads from the ST (status) outputs. This is how the SFC runtime propagates commands up and down the EM hierarchy without needing direct FBs in the parent.

9. Role Assignment: Binding Types to Instances

The role is the bridge between the type and the project. To bind a role:

  1. Open the SFC instance (the EM or Phase in the project hierarchy).
  2. Switch to the Role assignment tab. The roles declared on the type are listed with the role's type (e.g., Motor, Valve).
  3. For each role, select the concrete CM instance DB in the project. The dropdown is filtered by CMT type, so only compatible CMs are offered.
  4. Compile the SFC instance. The compiler emits direct calls to the bound CM in the synthesised action body.

A missing role assignment is the single most common cause of "the action compiles but does nothing at runtime". The SFC editor's cross-reference view highlights roles that are referenced in the action body but not bound in the role assignment table.

10. Working Example: EPHT for a Material-Triggered Pump

The end-to-end build for a single EPHT that turns on a pump only when a tank valve is open and material setpoint is non-zero:

  1. Open the master data library and create a CMT Pump1_Typ (or use the standard motor CMT). Verify the SFC interface has SetAuto, SetStart, SetStop.
  2. Create the EPHT PhaseRunPump1_Typ.
  3. Open the SFC editor. Add steps: Init, Ready, Running, Stopping, and transitions between them.
  4. On the Ready step, open Step Properties > Actions (technological) and add an action named DriveToAuto with VOID return type. Body: Pump1.SetAuto();
  5. On the Running step, add an action named ConditionalStart. Body:
    IF Material.SP <> 0 AND Valve1.FbkOpn = 1 THEN
        Pump1.SetStart();
    ELSE
        Pump1.SetStop();
    END_IF;
  6. On the Stopping step, add an action ForceStop with body Pump1.SetStop();. This runs once on step entry because the step has no continuous processing – it is the safe-state.
  7. Compile the master data library.
  8. Instantiate the EPHT in the project as PhaseRunPump1_Inst. Open its role assignment, bind the Pump1 role to the project's Pump1_Inst CM and the Valve1 role to Valve1_Inst.
  9. Compile and download. Force the Init step active from the SFC panel; the pump should transition to Auto, then Run on the Running step.

11. Verification and Commissioning

After download, run the following checks to confirm the actions are wired correctly:

  1. Step activation. Open the SFC in online mode. Force the owning step active. The step's Active LED turns green and the Step number and Step time indicators start updating.
  2. Mode propagation. In the APL block faceplate of the bound CM, the Aut/Man indicator should change in the same scan as the step activation. A delay of more than one cycle points to a wrong role or a missing command on the CMT interface.
  3. Action qualifiers. In the SFC trace, each step shows its action qualifiers (N, S, R, P, L, D). A non-stored action shows no qualifier letter. A stored action shows the qualifier next to the action name.
  4. Diagnostics view. Open the SFC faceplate on the OS and switch to the diagnostic view. The Active step, Step time, and Active actions are listed. The OS faceplate is the closest view to what the operator sees; it is also where interlocks and SFC error codes are reported.
  5. Cross-reference. Use the SFC cross-reference (right-click on a command in the action) to verify that the call resolves to a single instance DB. Multiple targets indicate a role bound to the wrong type.

12. Troubleshooting Matrix

Symptom Likely Root Cause Diagnostic Fix
Action code does not compile; "unknown identifier" on a command Command not exposed on CMT SFC interface Open the CMT > SFC interface tab; verify the command is present and named exactly as referenced Add the command to the CMT interface or correct the spelling in the action
Action compiles but command has no effect at runtime Role assignment missing or bound to wrong CM Open the EM instance > Role assignment tab; verify each role is mapped to a concrete CM instance DB Bind the role to the correct CM; recompile the instance
Action fires but condition never becomes TRUE Status read uses wrong DB path; FB call is missing an instance parameter Cross-check the status symbol against the CMT SFC interface; use the SFC cross-reference Correct the status reference; ensure the CMT block is in the same chart's scope
Mode toggles between Auto and Manual each scan Two actions in two steps both call SetAuto / SetManual; race between active steps Review all actions; identify conflicting commands on adjacent steps Move conflicting actions to mutually exclusive steps or remove duplicate calls
Nested IF-ELSE produces wrong branch Known PCS7 V9.0 compiler bug with stored/nested actions Reproduce in offline simulation; check the SFC trace Flatten the logic; upgrade to PCS7 V9.1
Action tab is greyed out Editor opened on an SFC instance, not the SFC type Title bar of the SFC editor; the type/instance distinction Open the master data library copy of the type and edit there
CmdStatLib command missing in the dropdown CmdStatLib not added to the project master data Open the master data library; verify CmdStatLib is present and compiled Add CmdStatLib from the PCS7 default library; recompile
Compile error: "action must be VOID" Action declared with a non-VOID return type, e.g. BOOL Open the action declaration; check the return type field Set the return type to VOID; if a value is needed, write it to an interface tag
Action runs once and then nothing on subsequent scans Action qualifier is P (pulse) or L (time-limited) Check the qualifier column on the step Change the qualifier to N for continuous processing

13. Cross-Platform Note: SFC Actions Beyond PCS7

Other IEC 61131-3 SFC implementations use the same underlying language and a similar distinction between step actions and IEC actions, but differ in how the action body is bound to instance blocks. The Beckhoff TwinCAT 3 SFC documentation is explicit: an action written in SFC must not contain a step that has the same name as the step to which the action is assigned, and "IEC actions" and "step actions" are separate element types. In TwinCAT the action body is plain structured text with direct variable access; the role-binding layer that PCS7 uses to call CMT commands does not exist – TwinCAT references instance symbols directly.

The qualifier set (N, S, R, L, D, P, SD, DS, SL) is consistent across vendors, which means a phase logic model expressed in PCS7 can be ported to TwinCAT or CODESYS, but the command-call code must be rewritten. Roles are a PCS7 concept, not an IEC 61131-3 concept. The cross-vendor pattern to recognise is: actions in the SFC step drive a process object through a typed command interface, the chart polls the command set, and a status interface on the same object is read by a transition. The exact syntax varies; the engineering pattern is stable.

14. Performance and Determinism Considerations

Every action body runs on every SFC cycle while the step is active. Two consequences follow:

  • Action count matters. An SFC with 30 active steps and 10 actions per step is re-evaluating 300 action bodies per cycle. Keep action bodies small. Move heavy computation to a separate FC/FB called from the action, so the action body is a one-line call.
  • Polling commands is cheap. Re-issuing a command that is already latched at the operator level is a no-op at the OS; the cost is a single block input write per scan. Do not add edge detection to avoid re-issues; the polling is what makes the action self-healing against transient glitches.

For high-priority charts (interlocks, safety-related phases), use the SFC priority setting on the OB to give the chart a shorter cycle time than the default 100 ms. The SFC runtime executes charts in priority order within each OB1 pass.

15. Naming and Library Conventions

PCS7 enforces naming through the master data library, but the following conventions make the type hierarchy easier to maintain:

  • Suffix CMTs with _Typ and instances with _Inst. The Type/Instance suffix makes the role-assignment dropdown unambiguous.
  • Suffix EPHTs with _PhTyp and EMTs with _EmTyp. The phase/unit distinction should be visible in the SFC editor title bar.
  • Prefix actions with their purpose: Drive_, Force_, Sense_. Force_ actions are used in safe-state steps that override any other action; the prefix makes them searchable.
  • Keep one action per step per concern. A step that needs to drive a motor and read a status should not collapse them into a single action; the action calls the CMT command, the condition reads the status. The separation is what makes the chart readable in online mode.

16. Frequently Asked Questions

Are SFC Actions executed every cycle?

Yes. A non-stored action in a step is re-evaluated on every SFC scan for as long as the step is in the Processing qualifier. A stored (S qualifier) action runs once on step activation and is held until cleared by an R qualifier on the same or a later step. A pulse (P qualifier) action runs exactly once on activation.

What does the VOID data type mean in an Action?

VOID is the IEC 61131-3 declaration for a procedure object that has no return value. The action runs for its side effects (calling commands, setting outputs) and produces no value the chart can assign. You cannot use a VOID action in an expression; if you need a computed value, compute it inside the action body and write it to an interface tag.

Why is the Actions tab read-only on my SFC?

You are editing an SFC instance, not the SFC type. The Actions (technological) and Conditions (technological) tabs are editable only on the type object (EPHT or EMT) in the master data library. Edit the type there, recompile the master data library, and the change propagates to every instance.

Why is my command not reaching the asset at runtime?

The role assignment is missing or bound to the wrong CM instance. Open the EM instance properties, switch to the role assignment tab, and verify that every role used in the action is mapped to a concrete CM. The SFC cross-reference view highlights unresolved roles; the compile log reports "role not bound" if the assignment is missing entirely.

Can I use nested IF-ELSE inside an Action?

Avoid nested IF-ELSE in PCS7 V9.0 – the compiler accepts it, but the generated code can take the wrong branch with stored actions. The behaviour is corrected in PCS7 V9.1. As a rule, refactor nested logic into flat branches with AND-combined conditions, or move the nested decision into a separate FC/FB called from the action body.

What is the difference between a CMT command and a direct block input write?

A CMT command is a typed wrapper around one or more block-contact bits. The SFC calls the command, and the APL routes the call to the correct internal structure. Writing to a block input directly bypasses the command surface, which means interlocks and operator acknowledgements built into the command are not exercised. Always use the command surface from SFC; reserve direct block input writes for non-SFC code such as the OS faceplate.

How do I call a child EM from a parent EM Action?

Use the CmdStatLib commands such as SetReadyTC, StartTC, and StopTC on the child EM instance. The parent writes to the TC inputs of the child and reads the ST outputs. Add CmdStatLib to the project master data library if it is not already present, and ensure the child EM is instanced and reachable from the parent's scope.

Back to blog