OOP PLC Output Control: Resolving Cyclic Safety Logic

Jason IP2 min read
Best PracticesOther ManufacturerPLC Hardware
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

In cyclic PLC execution, a method call does not behave like a temporary output command. If Start writes TRUE to retained function-block state or directly to %Q, stopping the method call does not automatically write FALSE. Resolve this by separating command requests from the final physical-output assignment and by evaluating interlocks every scan.

Separate command state from the physical output

Methods such as Start and Stop should modify an internal request such as bControlOutput. The cyclic function-block implementation should be the only code that assigns bDigitalOutput AT %Q*. This creates one deterministic write point and prevents a later method call from bypassing an earlier safety reset.

FUNCTION_BLOCK FB_ControlSomeActuator
VAR
    fbInterlockx2 : I_Interlock;
    bControlOutput : BOOL;
    bDigitalOutput AT %Q* : BOOL;
END_VAR

// Cyclic final arbitration and the only physical-output write
bDigitalOutput := bControlOutput AND fbInterlockx2.IsSafe;

Start can set bControlOutput, while Stop can reset it. The physical output still drops whenever IsSafe is false, regardless of whether the command request remains set.

Avoid order-dependent safety-reset methods

A separate SafetyReset method creates a call-order hazard: another call to Start could set the output afterward in the same scan. Do not rely on making the reset method the last call. Instead, perform final arbitration after command processing and prohibit command methods from writing the mapped output.

  1. Collect automatic, manual, HMI, and method-based requests into internal Boolean state.
  2. Select the permitted request according to the current control mode.
  3. Evaluate the interlock object cyclically.
  4. Assign the physical output once from the selected request and IsSafe.

Encapsulate interchangeable interlock logic

Define interlock implementations behind I_Interlock and expose an IsSafe property. A two-input implementation can require both inputs; a later three-input implementation can replace it without changing the conveyor or actuator output equation. Input objects may similarly hide normally open and normally closed interpretation behind a shared interface.

Layer Responsibility Must not do
Command methods Set or reset internal requests Write %Q directly
I_Interlock implementation Calculate IsSafe from its inputs Depend on command call order
Cyclic actuator implementation Select the request and perform the final output assignment Allow multiple competing output writers

Unify manual, automatic, and HMI control

Keep manual and automatic sources behind a common control boundary, whether implemented with I_ManualControl, I_AutoControl, and I_Control or with ordinary function-block inputs. When manual mode is active, select the manual request and block the automatic request before final arbitration. Do not allow both sources to write the actuator output.

For HMI/SCADA systems that cannot invoke methods or access properties, expose ordinary command and status variables as an adapter. Convert those variables into the same internal requests used by method-capable clients. Both client types then share one mode-selection, interlock, and output-assignment path.

FAQ

Why does a PLC output stay on after I stop calling the Start method?

The earlier method call wrote persistent state or the mapped output, and no later execution wrote FALSE. Write methods to internal request state and calculate the physical output cyclically.

Where should PLC interlocks be checked in an OOP function block?

Evaluate the interlock cyclically and use bDigitalOutput := bControlOutput AND fbInterlockx2.IsSafe; as the final, single output assignment. This removes dependence on whether Start or a reset method ran last.

How can one PLC object support both method-capable and tag-only HMIs?

Map tag-only HMI commands into the same internal request variables used by methods. Keep mode selection, interlock evaluation, and the %Q write inside the cyclic actuator implementation.

Back to blog