A condition answers one precise question
Before writing a complicated expression, say the question it should answer. “May this carton be released?” is useful. “Is everything okay?” is usually too vague. The first question gives you a decision boundary; the second invites every unrelated status bit into one unreadable expression.
For the teaching cell, release requires a completed fill, an available downstream path, and a filling head confirmed clear. Any one missing condition prevents release. That gives us AND.
ReleasePermitted := FillComplete
AND DownstreamReady
AND HeadClear;
This expression has no memory. If DownstreamReady changes, the result changes when evaluated again. It does not remember that downstream was ready earlier, or that a release had already begun. Those are separate requirements that may need stored state.
Read AND and OR as sets of allowed situations
AND requires all its operands to be true. OR requires at least one to be true. Ordinary Boolean OR includes the case where both are true; it does not mean “one or the other, but never both.”
Suppose a teaching station may receive a start request from a local button or a supervisory interface. LocalStart OR RemoteStart is true when either source requests and also when both request. Whether both sources should be accepted depends on mode and command ownership, not on the definition of OR.
| LocalStart | RemoteStart | OR result | AND result |
|---|---|---|---|
| False | False | False | False |
| False | True | True | False |
| True | False | True | False |
| True | True | True | True |
Four rows are cheap to inspect. Use them before guessing. Three Boolean inputs produce eight combinations; four produce sixteen. For larger decisions, split the expression into named concepts and inspect those concepts independently.
Parentheses preserve the sentence you meant
Consider a requirement: local or remote start is allowed, but only with the station ready. Write the grouping explicitly:
StartAllowed := (LocalStart OR RemoteStart) AND StationReady;
Without the intended grouping, a reader may understand the code differently, and operator precedence may produce an unintended expression. Parentheses are inexpensive documentation even when precedence already gives the desired result.
Now add local and remote modes. The requirement becomes: accept the local request in Local mode, or the remote request in Remote mode; either route still requires readiness.
SelectedStart := (LocalMode AND LocalStart)
OR (RemoteMode AND RemoteStart);
StartAllowed := SelectedStart AND StationReady;
This makes a further requirement visible: should LocalMode and RemoteMode ever both be true? An enumerated mode can avoid an impossible combination. If separate bits come from external equipment, explicitly diagnose contradictory selection rather than letting both command paths operate accidentally.
Invert meaning carefully
NOT (A AND B) is true whenever at least one required condition is absent. NOT A AND NOT B is true only when both are absent. They are different questions.
For our release conditions, the reasons to block release can be written as:
ReleaseBlocked := NOT FillComplete
OR NOT DownstreamReady
OR NOT HeadClear;
That is the inverse of the earlier ReleasePermitted. Keeping the individual reasons also lets the interface say what is missing. Do not show only a red “blocked” lamp when the program already knows which conditions are false.
Be careful with names such as NotStopped, NoFaultNotActive, or DisableInhibit. Negation stacked into both the name and the expression makes review slower. Prefer a positive, defined meaning such as PressureAdequate or a clear abnormal condition such as PressureFault.
Boundaries are part of the logic
For a mass target of 2.0 kg, MassKg > 2.0 does not become true at exactly 2.0. MassKg >= 2.0 does. That difference can matter even if the real measurement is noisy. Test below, at, and above each boundary.
Range checking needs the same discipline. If a valid teaching parameter is 1 through 20 inclusive, the invalid condition is “less than 1 OR greater than 20.” Using AND there would require a number to be below 1 and above 20 simultaneously.
ParameterInvalid := (BatchTarget < 1) OR (BatchTarget > 20);
A noisy physical value also needs a policy for repeated threshold crossing. Hysteresis uses different thresholds for turning a request on and off. Filtering changes the signal used by the decision. A delay requires persistence over time. These solve different problems; do not add all three without understanding the delay they introduce.
Separate a permissive from an instruction to act
A release may be permitted while no release has been requested. If ConveyorCmd := ReleasePermitted, the conveyor could run simply because the cell happens to be ready. The command also needs the sequence's intent.
ConveyorCmd := ReleaseRequested AND ReleasePermitted;
For this teaching model, ReleaseRequested comes from the active sequence state. The condition says that requested action is currently allowed. Keeping both names prevents readiness from turning into motion by accident.
The same distinction applies to a reset: “fault can be reset” is not the same as “operator has requested reset.” A good Boolean name tells you whether it represents capability, demand, observation, or result.
The misconception: shorter code is clearer code
An expression can be mathematically correct and still be hard to maintain. Saving three lines by folding mode selection, pressure checks, state checks, and fault checks into one formula creates a difficult diagnostic surface.
Break it at meaningful boundaries, not arbitrary lengths. ModeRequest, ProcessPermissive, and MotionRequest each describe a question somebody may need to answer during a fault. Fifty temporary variables named Condition1 through Condition50 provide no such help.
When reviewing an expression, say a counterexample aloud: “If the head is not clear but everything else is true, can this output turn on?” Then calculate that case. Counterexamples catch errors that a casual reading misses.
Try it
A mixer may run in Auto when an automatic mixing step requests it, or in Manual while a jog button is held. In either case, the lid-closed status and drive-ready status are required operational permissives. Write the expression. Then identify a case that exposes this incorrect version:
MixerCmd := AutoMixRequest
OR ManualJog AND LidClosed AND DriveReady;
The lid status in this exercise is an ordinary observation. Do not treat this example as a protective safety implementation.
Work through the answer
One clear version first selects the request and then applies the shared conditions:
MixerRequest := (AutoMode AND AutoMixRequest)
OR (ManualMode AND ManualJog);
MixerPermitted := LidClosed AND DriveReady;
MixerCmd := MixerRequest AND MixerPermitted;
The incorrect expression allows AutoMixRequest to make the result true independently of the lid and drive conditions. Set AutoMixRequest true and LidClosed false to expose it immediately. It also omits explicit mode ownership.
You can now evaluate a decision from present conditions. Remembering with intent adds the missing ingredient when a momentary request must have a lasting effect.