Part I · Chapter 3
The Request–Response Cycle
Every Modbus exchange is a small, predictable ritual: a question with a known shape, and an answer that is either the data you wanted, a clear refusal, or nothing at all.
By the end of this chapter you can
- Name the three parts of every request.
- Tell a normal response, an exception response, and silence apart, and say what each one points to.
- Explain timeouts, broadcast, and why a client polls in a loop.
The shape of a request
Every request carries three things:
- Which server: the unit address (also called unit ID, or slave address in older documents).
- What to do: the function code, a small number that means "read holding registers," "write a single coil," and so on.
- The data the operation needs: usually a starting address and a quantity, plus any values to write.
In plain language, the running example for this course says: "Server 1, perform function 3 (read holding registers), starting at address 0, for a quantity of 4." The server doesn't need to know what the registers mean. It hands back whatever is in those four slots.
The function code plus its data is the PDU (protocol data unit): the heart of the message, unchanged whichever transport carries it. The unit address and error check are wrapping added by the transport, which Part II examines byte by byte.
The shape of a normal response
When all goes well, the response echoes the function code and then supplies the result. A read returns a byte count followed by the data. A write usually echoes the address and value that were written, as confirmation the command took effect.
The echo is more useful than it looks: the client can confirm the server performed the operation it asked for, and a write's echo is positive proof the exact value was accepted.
When the server says no: exceptions
Sometimes a server understands a request perfectly but can't honor it: the address doesn't exist, the value is out of range, or the function isn't implemented. It doesn't stay silent and doesn't pretend to succeed. It sends an exception response.
An exception is marked so it can't be mistaken for success. The server sets the high bit of the function code, which adds 0x80: a failed 0x03 comes back as 0x83, a failed 0x05 as 0x85. One exception code byte follows, naming the problem.
| Code | Name | What it usually means |
|---|---|---|
| 01 | Illegal Function | The device doesn't support this function code |
| 02 | Illegal Data Address | That address doesn't exist on this device |
| 03 | Illegal Data Value | The value or quantity is out of the allowed range |
| 04 | Server Device Failure | An unrecoverable error occurred in the device |
| 06 | Server Device Busy | The device is busy; try again later |
| 0B | Gateway No Response | A gateway reached the target but got no reply |
Illegal Data Address (02) is the one beginners meet most, and it's almost always the addressing trap from Chapter 2 in disguise: a 4xxxx reference number that wasn't converted to its zero-based address.
The third outcome: silence
The outcome that puzzles newcomers most is no reply at all. Silence is not a refusal; it means the request never reached a working server, or the answer never made it back. The cause might be a miswired or unplugged cable, a unit address with no device behind it, mismatched serial settings, or a device that's switched off. The server never received an intelligible request, so it has nothing to say.
| Outcome | What it means | Where to look |
|---|---|---|
| Normal response | Everything worked | If the data looks wrong: scaling and interpretation (the register map) |
| Exception | The server is present and listening, but refuses this request | What you asked for, especially the address |
| Silence | The conversation isn't happening at all | The connection: wiring, unit address, serial settings, power |
Timeouts, retries, and one question at a time
Because silence is possible, a client can't wait forever. Every client uses a timeout: after sending a request it waits a set interval (often a fraction of a second to a couple of seconds), then declares the request failed. Many clients retry a few times before reporting the device unreachable, since an occasional lost message on a noisy line is normal.
On a serial bus, the timeout also enforces good manners. The client sends one request, waits for the response or the timeout, and only then sends the next. It never has two questions outstanding on the same bus, because one shared pair of wires can't carry two answers without collision. That discipline makes serial Modbus easy to reason about, and it's also why reading many devices takes time.
Modbus TCP relaxes this slightly: a TCP client may have several requests in flight and uses a small identifier in each message to match answers to questions (Chapter 7). Within any single exchange the logic is the same: ask, then wait for the answer, the exception, or the timeout.
Broadcasting to everyone
On a serial network, unit address 0 is reserved for broadcast. A write sent to unit 0 is meant for every server at once, for example to set the same parameter in all devices. Since no single device owns the reply, a broadcast draws no response. The client gives up its usual proof that the command took effect, so broadcast is used sparingly and only for writes.
The polling loop
A client rarely sends one request and stops. It polls: it works through a list of things it needs to know (these registers from device 1, those coils from device 2, that measurement from device 3), handles each reply, and then starts again from the top, refreshing its picture of the system several times a second or several times a minute.
Polling is simple and predictable: at any moment the client knows exactly which exchange is happening. But data is only as fresh as the loop is fast, and a slow or unreachable device can hold up the whole cycle while the client waits out its timeout. Designing a good loop (what to read, how often, and how to keep one stalled device from starving the rest) is real work, and Part IV returns to it.
Polling scheduler
| t (s) | Requests sent in this tick |
|---|
Check your understanding
1. A read of holding registers (0x03) fails. What function code comes back in the exception response?
The server sets the high bit, adding 0x80 to the original code: 0x03 + 0x80 = 0x83.
2. You send a clean request and get exception 02. What should you suspect first?
An exception proves the link works. 02 means the address doesn't exist on this device, usually the reference-number trap from Chapter 2.
3. A request draws no reply at all. Where do you look?
Silence means the conversation isn't happening. There's no exception code to read, so check the physical and configuration path.
4. Why does a write to unit address 0 get no response?
Unit 0 is the serial broadcast address. Every server acts on the write, and none replies.