These are the patterns that show up again and again when a machine misbehaves for no obvious reason. None of them is hard to fix once you know to look.

1. Driving one output from several places

When two or more rungs or blocks can write the same output, the last one executed in the scan wins, and the result depends on program order rather than intent. It often passes testing because the conflicting conditions never coincide on the bench. Fix: give every output exactly one writer, and put any arbitration — manual, auto, interlock — in one clearly named block ahead of it.

2. Ignoring the power-up state

What should happen after a power cycle or a CPU restart? Retentive values, half-finished sequences and outputs that energise before anyone expects them all cause surprises. Fix: write an explicit start-up routine, define the safe state of every output, and decide deliberately which values are retentive instead of accepting the defaults.

3. Trusting analog inputs without supervision

A 4–20 mA transmitter with a broken wire reads close to 0 mA. If your scaling turns that into “0 %”, the process looks quiet and normal while the sensor is actually dead. Fix: use the live-zero of 4 mA to your advantage and raise a fault when the signal falls clearly below it or rises far above 20 mA. NAMUR NE43 treats readings below roughly 3.6 mA or above 21 mA as failures.

4. Putting timers where they might not run

On most platforms a timer only updates when the code containing it is actually executed. Place one inside a branch, a jumped section or a conditionally called block, and it can freeze or reset in ways that are hard to see. Fix: keep timers and counters in code that always scans, or know exactly how your platform treats them when they are skipped.

5. Edge detection that depends on scan timing

A rising-edge detector needs its own memory bit. Share one between two uses and one of them will occasionally miss. And any signal shorter than the scan time may never be seen at all. Fix: one edge detector per use, and use fast inputs, high-speed counters or hardware latching for anything quicker than your scan.

6. Only programming the happy path

The valve is commanded open, and the logic waits for the open limit switch. If it never arrives, the sequence waits forever and the operator sees a machine that is simply “stuck”. Fix: every commanded action should have a feedback check and a timeout, and the resulting alarm should say in plain language what was expected and what did not happen.

7. Hard-coding values that need tuning

Setpoints, delays and limits buried inside the logic can only be changed with a laptop and a download — usually at the worst possible moment. Fix: keep tunable values in a parameter block that the HMI can adjust within sensible limits, and document the defaults.

A quick audit: for any machine that has caused trouble, search the program for each of these seven patterns. Finding one is common. Finding several usually explains the callouts.
Good PLC code is not clever. It is predictable at 3 a.m. for someone who has never seen it before.