caspershes - 2 days ago

I spend most of my time reviewing other people's CODESYS projects before commissioning,
and two kinds of defects keep showing up. Both compile clean. Both read fine.

One is in the code. A pause timer whose own input gets cleared inside the branch
the timer is supposed to gate:

rampDelay(IN := run_2);
IF NOT run_2 OR rampDelay.Q THEN
    run_1 := TRUE;
    run_2 := FALSE;      // the timer's own input, cleared right here
ELSE
    run_1 := FALSE;
    run_2 := FALSE;
END_IF

Next scan IN is FALSE, the timer resets, the condition is true again, and the second
pump starts immediately. A 30-second ramp delay that actually lasts one task cycle.
The setpoint is on the HMI, the operator turns it, and nothing changes.

The other is not in the code at all. On one site the outdoor temperature read 0.0 Β°C
in mild weather. The ST was correct, the variable was bound to the channel β€” but the
channel's sensor type was left at "disabled", so nothing was ever digitised. Same class:
a module with Disable_module = TRUE, or an analog output bound to a variable while its
mode is off. Nothing in the project reports any of this, and the code review never looks
there, because the configuration lives in the device tree and not in the POUs.

That second class is what pushed me to parse the .export format rather than PLCopenXML
alone β€” the export carries the device tree and the visualization, so "nothing ever writes
this alarm variable" stops being a guess and becomes a fact you can check against the
screen bindings.

Three things about the format that cost me time, in case they save you some:

  • the same device parameter can appear three times (template, internal copy, actual
    configuration) β€” the last occurrence is the one in effect;
  • the enum value of a parameter is not in the parameter itself, it is one level down
    in BaseType/Value;
  • a channel counts as used when a variable is bound to SensorValueN.SensorValue β€”
    InputStatus is a bad indicator, people deliberately bind it on spare inputs.

So the question. What else would you check automatically, given both the code and the
device tree?
I am collecting rules from sites, not from style guides, and the
configuration side feels largely unexplored.

For what it is worth, the checker I use for this is free and runs offline (single exe,
no install, nothing uploaded anywhere): https://github.com/caspershes/plc-lint β€” 43 rules
at the moment, reads .export and PLCopenXML. Happy to add rules people here suggest.