OpenPLC

OpenPLC

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

06 - Diagnostics

06 - Diagnostics

Two blocks, and neither of them puts anything extra on the bus except when you
ask it to.

health( NODE := node );

No inputs at all. It reports and changes nothing, which is why it is safe to
drop onto a diagnostic page anywhere.

The three error counters, and what each one means

This is the part worth putting on a screen, because the difference between
them says which fault you have
, and none of them looks any different from the
application's point of view:

climbing means
CHECKSUM_ERRORS the bytes arrive and the maths does not agree. Noise, a baud rate mismatch, or a missing termination resistor
NOISE_BYTES bytes discarded while hunting for the start of a frame. A floating bus — nothing is holding the line at idle. Fit the bias resistors
FRAMING_ERRORS structurally impossible frames. Something on the bus is speaking a different protocol, or frames are being split — read FRAMING_REASON

All three flat while a device does not answer means the bytes are not
arriving at all
: wrong port, wrong wires, transmit and receive swapped, or the
device is off. That is a useful negative result and it takes two seconds to
check.

SENT and RECEIVED are frames, both directions. On a healthy client they
track each other. SENT climbing while RECEIVED stays put is nobody
answering.

PENDING is requests queued and not yet concluded. It should hover near zero
and come back down. One that climbs steadily is a program issuing requests
faster than the bus can carry them — see 10 - Scan rate.

To zero the counters, pulse RESET_STATS on the node that owns the link.

FRAMING_REASON

The first thing to read when frames go missing, and the answer to the commonest
question asked of any Modbus library: why is my RTU splitting frames.

RTU marks the end of a frame with silence — three and a half character times of
it. A USB adapter, a virtual serial port or a busy PLC scan can all destroy
that silence by delivering bytes in clumps. So the library measures the line and
picks a rule, and this pin says which rule and why, in a sentence you can read
off the screen.

On a TCP link it says so and stops there — the header carries the length, so
there is nothing to predict and nothing to measure. On an RTU-over-TCP link
it reports the RTU rule instead, which is how you tell from one pin which of
the two a terminal server actually gave you.

MODBUS_DEVICE — how one device is doing

drive( NODE := node, UNIT := 2, IDENTIFY := askOnce );

ANSWERING, SILENT and ROUND_TRIP are read off traffic you are
already making.
With POLL at 0 this block sends nothing at all, so a
screen showing thirty devices you already read costs not one extra frame.

Which means a device nobody asks anything reads as not answering. That is
literally true and thoroughly unhelpful — the device may be in perfect health
and simply have nothing to say, because nothing has spoken to it. If this block
is the only thing pointed at a device, give it a POLL:

standby( NODE := node, UNIT := 5, POLL := T#2s );

It sends the standard link test, function code 8: whatever goes out comes back
unchanged, and no register is touched. A device that does not implement FC 8
answers with an exception — which still proves it is alive and still counts
as answering, because a unit that is transmitting is a unit that is there. So
the check works even on devices that refuse it.

SILENT = -1 is not a long silence

It means this device has never answered at all, which is a different fault
from one that has gone quiet — and the two send an engineer to opposite ends of
the site:

never answered the unit id is wrong, the device was never fitted, or it is set to a different address. A commissioning fault, found at the desk with a wiring drawing
gone quiet it was answering and has stopped. A cable, a power supply, a failed device. A running fault, found in the plant

An alarm list that shows both as "no comms" throws that away. Keep them apart:

deviceMissing := (drive.SILENT < 0);              (* never there *)
deviceLost    := (drive.SILENT > 5000);           (* was, is not *)

ANSWERING is the simple form: TRUE while the device has answered within
GONE, which defaults to five seconds.

ROUND_TRIP

The number to quote when somebody asks whether a device is slow or the bus is.
It is measured, not configured.

A drive answering in 45 ms on a bus whose other devices answer in 6 ms is a
slow drive
, and no amount of changing the baud rate will help. A bus where
everything answers slowly is a bus problem. Without this number the two
arguments go round for an afternoon.

IDENTIFY — the device's own nameplate

A rising edge asks the device who it is, using function code 43 — the same
information a handheld tool shows:

drive( NODE := node, UNIT := 2, IDENTIFY := askOnce );

IF drive.IDENTIFIED THEN
    (* one scan, when the nameplate arrived *)
    logLine := CONCAT(drive.VENDOR, drive.PRODUCT);
    askOnce := FALSE;
END_IF;

Ask once at start-up and keep what comes back. It does not change.

Not every device implements it. One that does not answers with an exception,
which arrives as MODBUS_REFUSED — that is a normal answer, not a fault worth
alarming on.

Every status code

STATUS is on every block. MODBUS_OK when fine.

Accepted

MODBUS_QUEUED accepted; the outcome arrives on a later scan
MODBUS_OK it completed. This is what success looks like

Refused before anything reached the wire

These are your program's mistakes, and being told immediately is the point —
you can fix a bad request, and you cannot tell a bad request from an absent
device once it has timed out.

MODBUS_NOT_INITIALISED the link is not open. Check node.READY and node.LAST_ERROR
MODBUS_INVALID_ARGUMENT a zero count, a length past the end of the variable, a quantity Modbus disallows, or a BOOL aimed at a register list
MODBUS_NOT_MAPPED a local address with nothing bound to it
MODBUS_DUPLICATE an identical request is already outstanding. Not an error — this is what stops a held REQ flooding the bus
MODBUS_QUEUE_FULL more outstanding requests than the queue holds. You are asking faster than the bus can answer - or, if the bursts are expected, MODBUS_CONFIG's QUEUE / QUEUE_BYTES are too small
MODBUS_UNKNOWN_UNIT the destination is not reachable
MODBUS_SUPERSEDED a newer write to the same address replaced this one before it went out. Not an error
MODBUS_CANCELLED discarded by a restart

Concluded on the wire

MODBUS_TIMEOUT nothing answered, after every retry. The device is off, unplugged, at a different address, or on a different baud rate
MODBUS_REFUSED the device answered and said no. The wiring works — the address or the function code is wrong for that device
MODBUS_ACKNOWLEDGED the device took the job and is still doing it. Poll, do not retry — retrying sends a second copy of a command already running
MODBUS_BUSY the device is busy. Retry later
MODBUS_GATEWAY_PATH_UNAVAILABLE a bridge has no route to that unit. A problem with the bridge
MODBUS_GATEWAY_TARGET_FAILED the route exists and the device did not answer. A problem with the device
MODBUS_LINK_DOWN the transport is not usable. On a block other than the node, this also means the NODE pin has no started node behind it
MODBUS_CHECKSUM_ERROR a reply arrived corrupt
MODBUS_PROTOCOL_ERROR a reply arrived and made no sense

MODBUS_REFUSED is the most encouraging failure on this list. It means
frames are going out, arriving, being understood and being answered. Everything
below the application layer works, and you are arguing about an address.

Next: 07 - Block reference

Last updated 2 hours ago
Was this helpful?
Thanks!