Zum Inhalt

Boolean Logic and Markers

Boolean Logic

A FUP network with contacts usually becomes one Boolean assignment.

xboDriveStartAllowed :=
    xboOperatorStartRequest
    AND xboDriveReady
    AND NOT xboEmergencyStopActive
    AND NOT xboTripActive;

Use parentheses when the expression mixes AND and OR.

xboAlarmActive :=
    (xboHighTemperature OR xboLowOilPressure)
    AND xboMachineRunning;

Prefer one clear assignment over many small marker steps when the expression is still readable.

Markers And Reset Logic

A marker is simply a Boolean memory. In SCL, the important question is always: when is it set, and when is it reset?

Set Without Reset

IF inCounter > 4 THEN
    _xboCounterExceeded := TRUE;
END_IF;

This value latches forever after the first time inCounter > 4 becomes true. That may be correct for an alarm latch, but it is wrong for a normal live condition unless another part of the code resets it.

Set With Reset

IF inCounter > 4 THEN
    _xboCounterExceeded := TRUE;
ELSE
    _xboCounterExceeded := FALSE;
END_IF;

This follows the condition every cycle. When the counter drops back to 4 or lower, the marker is reset.

Direct Assignment

_xboCounterExceeded := (inCounter > 4);

For simple live conditions, this is usually best. It has an obvious reset condition because the complete value is recalculated every cycle.

Latch With Named Reset

Use explicit latch logic when the memory is intentional.

IF xboResetAlarm THEN
    _xboAlarmLatched := FALSE;
ELSIF xboAlarmCondition THEN
    _xboAlarmLatched := TRUE;
END_IF;

This makes the priority visible. In this example, reset wins over set because it is checked first.

Marker overuse

Too many markers make code hard to reason about, especially when the reset condition is far away from the set condition. If the logic starts to describe steps or modes, use a state machine.

Edge Detection

FUP often has rising edge boxes. In SCL, store the previous value and compare it with the current value.

_xboStartRequestRise := xboStartRequest AND NOT _xboStartRequestLast;
_xboStartRequestLast := xboStartRequest;

The order matters. Calculate the edge first, then update the previous value for the next cycle.