LearnSCADA

Part II · Chapter 9

Exceptions and Diagnostics

Most of the time a request succeeds. This chapter is about the rest of the time: the complete list of exception codes, what each is really telling you, and the diagnostic tools that let you test a serial line and read a device's own error counters.

By the end of this chapter you can

  • Read any exception response and name the fault behind it.
  • Go from symptom (data, exception, or silence) to the right place to look.
  • Run a loopback test with the Diagnostics function (0x08).
  • Read a device's communication counters and say what they point to.

The exception response, once more

When a server understands a request but can't carry it out, it replies with an exception response. It takes the original function code, sets the high bit (adds 0x80), and follows it with one exception code byte naming the problem. A failed Read Holding Registers (0x03) comes back as 0x83; a failed Write Single Coil (0x05) as 0x85. No normal function code uses that high bit, so its presence is an unmistakable signal that what follows is an error report, not data.

An exception response in full. The client asks server 1 for four holding registers starting at address 500, sending 01 03 01 F4 00 04 04 07. The server has registers 0 to 99 only, and replies 01 83 02 C0 F1. Below, function code 03, binary 0000 0011, is shown becoming 83, binary 1000 0011: only the top bit has changed. Exception code 02 means Illegal Data Address. Client asks for 500–503 Server 1 registers 0–99 no such register 01 03 01 F4 00 04 04 07 01 83 02 C0 F1 request 03 = 0 0 0 0 0 0 1 1 reply 83 = 1 0 0 0 0 0 1 1 ↑ high bit set 02 = Illegal Data Address: there is no register 500 here
Figure 9.1 · An exception response in full: the requested function code with its high bit set (0x03 becomes 0x83), then one exception code byte naming the fault.
Address Exception CRC
01server 1 8303 + 80 02exception C0 F1CRC

An exception response is always this short: address, marked function code, exception code, CRC. The spec's own example, from server 17, is 11 83 02 C1 34.

The exception codes

A modest list covers everything a device can report. The first three are by far the most common day to day; the gateway codes appear only when a gateway sits in the path.

CodeNameWhat it tells you
01Illegal FunctionThis device doesn't implement that function code
02Illegal Data AddressThat address doesn't exist here: check your addressing
03Illegal Data ValueThe quantity or value is outside the allowed range
04Server Device FailureAn unrecoverable fault occurred inside the device
05AcknowledgeAccepted, but it needs time: poll again shortly
06Server Device BusyBusy now: resend the request later
08Memory Parity ErrorA memory error during a file-record operation
0AGateway Path UnavailableA gateway has no path to the target: misconfigured or overloaded
0BGateway Target Device Failed to RespondThe gateway sent the request on, but the target never replied (often shortened to "Gateway No Response")

Three of these deserve a closer word.

  • Illegal Data Address (02) is the beginner's constant companion. It almost always means an addressing mistake: a forgotten reference-number conversion, a count that runs past the end of a table, or the wrong table entirely.
  • Illegal Data Value (03) doesn't mean "I dislike this number." It means the quantity or value broke this request's rules: 200 registers when the limit is 125, or something other than 0xFF00 / 0x0000 written to a coil.
  • Acknowledge (05) and Server Device Busy (06) aren't failures at all. They're timing signals: wait and try again rather than give up.

From symptom to cause

Combine the three outcomes from Chapter 3 with these codes and you have a fast first-pass diagnosis for almost any Modbus problem:

  • Normal response: the path works. Wrong-looking data is a scaling or interpretation question for the register map.
  • Exception: the device is alive and listening, so look at what you asked. 01: it lacks that function. 02: fix the address. 03: fix the quantity or value.
  • Silence: the device isn't hearing you, so look at the connection: wiring, unit address, serial settings, power.
A first-pass diagnostic path. From "send a request" three branches lead down. Data back leads to the register map: scaling, interpretation, word order. An exception leads to the request: 01 function, 02 address, 03 quantity or value. Silence leads to the connection: wiring, unit address, serial settings, power. A marker follows each branch in turn. Send a request Data back Exception Silence The register map scaling interpretation word order, data type The request 01 wrong function 02 fix the address 03 fix quantity / value The connection wiring, termination unit address serial settings, power
Figure 9.3 · A first-pass diagnostic path. The kind of reply (data, an exception, or silence) points you straight at the right place to look: the register map, the request, or the physical connection.

This one decision is the spine of Modbus troubleshooting, and Chapter 16 fleshes it out with tools and worked cases. The point to carry forward: Modbus is unusually diagnosable. The protocol nearly always tells you which of three worlds your problem lives in, and that alone eliminates most of the guesswork.

The Diagnostics function

Beyond exceptions, serial Modbus has a dedicated Diagnostics function, code 0x08, for testing a link and reading a device's internal health counters. It's a serial-line tool: over TCP the network provides its own diagnostics, but on RS-485 it's genuinely useful. After the function code comes a two-byte sub-function that selects the test, then a two-byte data field.

The most immediately useful sub-function is the simplest. Sub-function 0x0000, Return Query Data, is a loopback test: the client sends some arbitrary data and the server must send the exact same data straight back.

Address Function code Sub-function and data CRC
01server 1 08diagnostics 00 00return query data A5 37test data DA 8DCRC
The loopback diagnostic. The client sends 01 08 00 00 A5 37 DA 8D: Diagnostics, sub-function 0000, test data A5 37. A healthy server returns the identical eight bytes, and the client compares: A5 37 sent, A5 37 received, so the whole path is proven. Client sends A5 37 Server 1 echoes it back request 01 08 00 00 A5 37 DA 8D 01 08 00 00 A5 37 DA 8D response sent A5 37 = received A5 37 ✓ the whole path works
Figure 9.4 · The loopback diagnostic. The client sends arbitrary data with sub-function 0x0000; a healthy server returns it unchanged, proving the whole communication path is sound.

If the echo matches, you've proven the full round trip: the wiring, the serial settings, the addressing, and both devices' ability to frame and check a message. That's wonderfully reassuring when you're bringing a new bus to life, because it isolates the communication path from any question about register maps or data meaning.

The diagnostic counters

A serial Modbus device quietly keeps counters about its own communication, and other Diagnostics sub-functions read them. They turn "the bus is flaky" into hard numbers. The most telling:

Sub-functionCounterWhy it matters
0x000BBus message countTotal frames the device saw on the bus
0x000CBus communication error countFrames with a bad CRC: noise or wiring
0x000DBus exception error countRequests it answered with an exception
0x000EServer message countFrames actually addressed to this device
0x000A(Clear counters)Resets the counters to start a clean test

To read a counter, send its sub-function with a data field of 00 00; the response carries the count in that field. Reading the CRC error count from server 1, and a reply reporting 37 errors:

01server 1 08diagnostics 00 0CCRC error count 00 00data 0 20 08CRC
01server 1 08echo 00 0Csub-function 00 25count = 37 E1 D3CRC
The internal counters of server 1. Six frames pass along the bus: to unit 1, to unit 2, to unit 1 damaged by noise, to unit 1 asking for an illegal address, to unit 3, and to unit 1. Server 1 sees them all. Its bus message count climbs to 6, its CRC error count to 1, its exception count to 1, and its server message count to 3. Client RS-485 bus Server 1 listens to every frame Bus messages CRC errors Exceptions Server messages 0x000B 0x000C 0x000D 0x000E 0 1 2 3 4 5 6 0 1 0 1 0 1 2 3 to unit 1 to unit 2 unit 1 · noise hit unit 1 · bad address to unit 3 to unit 1
Figure 9.5 · The counters a serial device maintains: total messages, CRC errors, exceptions, and messages meant for it. (Simplified: replies on the bus are left out.) Reading them turns "the bus seems flaky" into specific numbers.

Read together, these counters are diagnostic gold:

  • A steadily climbing communication error count points straight at electrical trouble (noise, a missing termination resistor, a marginal connection) because it counts frames that arrived with a broken CRC.
  • A high exception error count points instead at a software or configuration problem: the device receives frames cleanly but refuses them.
  • Comparing the bus message count with the server message count shows how much of the bus traffic is even meant for this device.

A common workflow: clear the counters with sub-function 0x000A (01 08 00 0A 00 00 C0 09), run the system for a while, then read them back to see exactly what went wrong and how often. The counters are 16 bits wide and wrap after 65,535, so read them often enough on a busy bus.

Counter interpreter

Enter the counts you read back after clearing the counters and letting the system run.

    Read Exception Status

    One more small serial function rounds out the toolkit: Read Exception Status, code 0x07. The request is just the address and function code; the response returns a single byte of eight device-specific status bits. What those bits mean is defined by each device (over-temperature, a calibration fault, a low battery), so you need the manual to read them.

    01server 1 07read exc. status 41 E2CRC
    01server 1 07echo 6Dstatus bits E3 DDCRC

    Here the status byte 6D is 0110 1101: bits 0, 2, 3, 5 and 6 are set, and only the device manual says what each one means. The value of the function is its brevity: a quick "are you healthy?" poll that costs almost nothing, useful for keeping a light eye on a device between fuller reads. (The name is historical: these status bits have nothing to do with exception responses.)

    RTU frame decoder

    Examples to paste: 01 83 02 C0 F1, 01 08 00 0C 00 25 E1 D3, 01 08 00 0A 00 00 C0 09, 01 07 6D E3 DD, 01 85 03 02 91, 11 03 06 AE 41 56 52 43 40 49 AD, 01 01 01 0D 90 4D, 01 10 00 10 00 02 04 00 0A 01 02 52 F0. Change one digit to see a CRC failure.

    Check your understanding

    1. A device replies 01 86 03 …. What happened?

    0x86 − 0x80 = 0x06, Write Single Register. Exception 03 means the value broke the device's rules, for example it's out of range for that register.

    2. A request comes back with exception 06, Server Device Busy. What should the client do?

    05 and 06 are timing signals, not failures. The device heard you and is asking you to try again shortly.

    3. A loopback test (sub-function 0x0000) returns the exact data you sent. What has it proven?

    A matching echo proves the whole communication path. It says nothing about register meanings, which is exactly why it's useful for isolating the link.

    4. After clearing the counters, the CRC error count climbs steadily while the exception count stays at zero. Where do you look?

    Bad CRCs mean frames are being damaged in transit. Exceptions would point to configuration; here the requests are fine but the wire isn't.