# Module 2: The Message Model

> PDU vs ADU, how requests, responses, and exceptions actually look on the wire.

**Phase:** Foundations  
**Estimated time:** 6 min  
**Release status:** Published  
**Content version:** 1.0.0  
**Source:** https://learnmodbus.studioseventeen.io/lesson/message-model

## What you'll be able to do
- Distinguish PDU from ADU and identify each on the wire.
- Recognize a normal response, an exception response, and a no-response timeout.
- Predict the exception code for an illegal address or illegal function.

## Three things people get wrong
1. **Confusing 'no response' with 'exception'.** An exception is a valid Modbus reply with FC | 0x80. Silence is a transport problem.
2. **Counting bytes from the PDU when reading an RTU capture.** Subtract the address byte and the trailing 2-byte CRC first — what's left is the PDU.
3. **Reading a TCP length field as 'PDU length'.** MBAP length covers Unit ID + PDU, not the whole ADU.

## From the field
**The exception that wasn't**

A panel builder kept logging '83 02 — illegal address' and changed his register map five times. The capture eventually showed those bytes only after a 1.2-second gap from the previous frame — the gateway was timing out and returning its own error PDU. The map was right all along.

## References
- [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — PDU structure, exception codes

## Lesson

# Module 2 Lesson: The Modbus Message Model
## Learner Outcome

By the end of this module, learners can describe the Modbus request/response flow, distinguish PDU from ADU, label function/address/quantity fields in a simple request, and recognize the difference between normal responses, exception responses, and client-observed timeouts.

## Key Concepts

- The PDU is the transport-independent Modbus core: function code plus data.
- The ADU is the transport-specific wrapper used by RTU, ASCII, or Modbus TCP. In Modbus Security, the Modbus TCP ADU is carried over TLS; the PDU and MBAP meaning are unchanged here.
- A normal read request names a function code, a starting address, and a quantity.
- A normal read response echoes the function code, gives a byte count, and returns data.
- An exception response is still a Modbus response: it uses the requested function code plus `0x80` and a one-byte exception code.
- A timeout or no usable response is not a Modbus exception response.

## Key Terms

- PDU: Protocol Data Unit; the function code plus request or response data.
- ADU: Application Data Unit; the PDU plus transport-specific wrapper fields such as serial address/error check or the Modbus TCP MBAP header.
- Function code: the operation byte that tells the server what kind of read, write, or diagnostic action is being requested.
- Normal response: a valid response that follows the expected response shape for the requested function.
- Exception response: a valid Modbus response that reports the server rejected the request.
- Timeout/no usable response: a client observation that no valid Modbus response arrived before the deadline.

## Source-Grounded Explanation

### PDU Versus ADU

The Modbus PDU is the part learners should recognize across transports:

```text
Function Code | Data
```

The ADU wraps that PDU for the selected transport:

```text
RTU / serial ADU: Address | Function Code | Data | CRC
ASCII serial ADU: Address | Function Code | Data | LRC
Modbus TCP ADU:   MBAP Header | Function Code | Data
Modbus Security:  Modbus TCP ADU carried inside TLS
```

This module teaches the labels and the request/response shape. Module 11 handles RTU/ASCII frame construction, CRC/LRC details, and timing. Module 12 handles MBAP fields in detail.

### Normal Request And Response Shape

For common read requests, the client sends:

```text
function code + starting PDU address + quantity
```

For common read responses, the server sends:

```text
same function code + byte count + data bytes
```

The exact meaning of the returned data still comes from the register map. The response proves that the server returned bytes for the request. It does not prove that the bytes have the engineering meaning a dashboard claims.

### Exception Response Shape

When a server receives a parseable Modbus request but cannot process it, it can return an exception response:

```text
requested function code + 0x80, then one exception code byte
```

Example: a request using function `0x03` can fail with function byte `0x83`. The next byte identifies the exception code, such as illegal function or illegal data address.

Do not confuse this with silence. If the client observes a timeout, CRC error, wrong serial server address, wrong network path, or no valid responder, no Modbus exception response has been received.

## Practical Example: PDU-Level Read

Synthetic read request:

```text
03 00 09 00 01
```

| Byte(s) | Meaning |
|---|---|
| `03` | Function code: Read Holding Registers |
| `00 09` | Starting PDU address: `9` |
| `00 01` | Quantity: `1` register |

Teaching context:

| Example Field | Value |
|---|---|
| Source label | Synthetic teaching fixture |
| Transport | PDU shown without transport wrapper |
| Function code | `03` Read Holding Registers |
| Documented address | `40010` in a one-based `40001` style source map |
| PDU address | `9` |
| Quantity | `1` register |
| Data type | Unsigned 16-bit for this synthetic example |
| Scale/unit | raw `/10 deg C` |
| Expected normal response | `03 02 00 E0` |
| Expected decoded value | raw `224`; mapped value `22.4 deg C` after source-map scale |
| Exception example | `83 02` if the server reports illegal data address |
| Timeout example | No usable response if no valid response arrives |

Normal response:

```text
03 02 00 E0
```

| Byte(s) | Meaning |
|---|---|
| `03` | Function code echoed for success |
| `02` | Byte count |
| `00 E0` | Data bytes, raw decimal `224` |

Exception response:

```text
83 02
```

| Byte(s) | Meaning |
|---|---|
| `83` | Exception response to requested function `03` |
| `02` | Exception code: illegal data address |

## Common Pitfalls

- Calling the PDU and ADU the same thing.
- Looking for a serial CRC in a Modbus TCP ADU.
- Looking for an MBAP header in an RTU frame.
- Treating exception `83 02` as a successful function `83` response.
- Treating a timeout as an exception response.
- Assuming returned bytes prove engineering meaning without the register map.
- Jumping into CRC/LRC details before learners can label the PDU fields.

## Check-Your-Understanding

1. In `03 00 09 00 01`, which byte is the function code?
2. What is the difference between a PDU and an ADU?
3. A request uses function `04` and receives an exception. What function byte should the exception response use?
4. What does the byte count mean in `03 02 00 E0`?
5. Why is timeout/no usable response not the same as exception `83 02`?

## Source Notes

- Official basis: Modbus Application Protocol Specification for PDU structure, PDU length, function code, normal response, and exception response behavior.
- Official transport basis: Modbus over Serial Line Specification and Implementation Guide for RTU/ASCII wrapper context; Modbus Messaging on TCP/IP Implementation Guide for MBAP/TCP wrapper context; Modbus Security specification for TLS-secured TCP context.
- Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for PDU vs ADU and general frame structure, maximum Modbus PDU size, normal response vs exception response, exception codes and exception response PDU shape, RTU/ASCII frame fields, MBAP header fields, and Modbus Security TLS wrapping.
- Local course spine: `modbus-wiki.md` sections "PDU and ADU", "Transaction Flow", "Function Codes", "Common Quantity Limits", and "Exception Responses".
- Synthetic basis: request/response bytes in this module are course-authored teaching fixtures.

## Completion Checkpoint

Before moving on, learners should label one request, one normal response, one exception response, and one timeout/no-usable-response observation without mixing PDU fields with transport wrapper fields. This vocabulary supports data tables, function codes, serial frames, TCP packets, and troubleshooting later in the course.

## Reusable Assets

- [PDU/ADU frame-label worksheet](https://learnmodbus.studioseventeen.io/resource/pdu-adu-frame-label-worksheet)
- [Exception-code quick reference](https://learnmodbus.studioseventeen.io/resource/exception-code-quick-reference)
- [Module 2 response/exception lab](https://learnmodbus.studioseventeen.io/lesson/message-model?page=lab-1)
- [Module 2 quiz](https://learnmodbus.studioseventeen.io/lesson/message-model?page=quiz)

## Diagram source

```mermaid
flowchart LR
  subgraph ADU["ADU (transport-wrapped frame)"]
    direction LR
    A["Addr / MBAP"] --> P["PDU"] --> E["CRC / LRC / —"]
  end
  subgraph PDU["PDU"]
    direction LR
    F["Function Code"] --> D["Function-specific Data"]
  end
```

## Labs

### Lab 1

# Lab 10: Response And Exception Labeling
Supporting modules: 4, 14
Estimated time: 35-50 minutes
Release state: draft; final source/instructor review pending

## Learner Outcome

Learners label PDU fields, distinguish PDU from ADU wrapper fields, and classify normal response, exception response, and timeout/no usable response cases.

## Prerequisites

- Module 1 client/server mental model.
- Module 2 lesson or equivalent introduction to PDU, ADU, normal response, and exception response.
- [PDU/ADU frame-label worksheet](https://learnmodbus.studioseventeen.io/resource/pdu-adu-frame-label-worksheet)
- [Exception-code quick reference](https://learnmodbus.studioseventeen.io/resource/exception-code-quick-reference)

## Safety And Scope

This is a saved-byte/no-hardware lab. Do not connect to production devices. The frames are synthetic teaching fixtures, not captured production traffic.

## Cards

### Card A: PDU Request

```text
03 00 09 00 01
```

| Field | Expected answer |
|---|---|
| Source label | Synthetic teaching fixture |
| Type | PDU request |
| Function code | `03` Read Holding Registers |
| Starting PDU address | `0x0009` |
| Quantity | `0x0001`, one register |
| Missing wrapper | No serial address/CRC and no MBAP header shown |

### Card B: PDU Normal Response

```text
03 02 00 E0
```

| Field | Expected answer |
|---|---|
| Source label | Synthetic teaching fixture |
| Type | PDU normal response |
| Function code | `03` echoed for success |
| Byte count | `02` |
| Data bytes | `00 E0`, raw decimal `224` |
| Meaning boundary | Engineering meaning requires the source map |

### Card C: PDU Exception Response

```text
83 02
```

| Field | Expected answer |
|---|---|
| Source label | Synthetic teaching fixture |
| Type | PDU exception response |
| Original function | `03` |
| Exception function byte | `83`, meaning `03 + 0x80` |
| Exception code | `02`, illegal data address |
| Troubleshooting meaning | A server returned a Modbus exception; this is not silence |

### Card D: RTU-Style Wrapper Preview

```text
11 03 00 09 00 01 <CRC>
```

| Field | Expected answer |
|---|---|
| Source label | Synthetic wrapper preview |
| Type | ADU preview |
| Serial server address | byte `0x11` / decimal `17` |
| PDU portion | `03 00 09 00 01` |
| Error check | CRC placeholder; Module 11 verifies actual CRC bytes |
| Boundary | Do not calculate CRC in this Module 2 lab |

### Card E: Modbus TCP Wrapper Preview

```text
00 01 00 00 00 06 01 03 00 09 00 01
```

| Field | Expected answer |
|---|---|
| Source label | Synthetic wrapper preview |
| Type | Modbus TCP ADU preview |
| MBAP header | `00 01 00 00 00 06 01` |
| PDU portion | `03 00 09 00 01` |
| Boundary | MBAP fields are labeled in detail in Module 12 |

### Card F: Timeout Observation

The client sends a request and receives no usable response before timeout.

| Field | Expected answer |
|---|---|
| Source label | Synthetic teaching fixture |
| Type | Client-observed timeout/no usable response |
| Is this an exception response? | No |
| Possible causes | Wrong path, wrong serial server address, invalid wrapper, framing/checksum problem, no reachable responder |
| Next course link | Module 14 troubleshooting workflow |

## Procedure

1. Label each card as PDU request, PDU normal response, PDU exception response, ADU preview, or timeout/no usable response.
2. Circle the PDU portion in each byte string that includes one.
3. Record function code, starting PDU address, quantity, byte count, data bytes, or exception code where applicable.
4. Mark which details belong to later transport modules.
5. Answer the check questions.

## Expected Observations

- Normal responses keep the original function code and include the expected response data shape.
- Exception responses use the original function code plus `0x80` and include an exception code.
- Timeout/no usable response is a client observation, not a Modbus exception response.
- Wrapper fields such as RTU address, CRC, or MBAP data help classify the ADU but should not be mixed into the PDU answer.

## Troubleshooting Notes

- If learners call timeout "exception `02`," ask for the returned exception bytes; no bytes means no exception evidence.
- If learners label every byte as PDU, separate wrapper, function code, and data fields before interpreting the result.
- If a raw value appears, keep engineering meaning unresolved until a map supplies data type, scale, unit, and validity context.
- If an exception response appears, troubleshoot address, quantity, function support, or table selection before changing unrelated serial/TCP settings.

## Check Questions

1. Which cards are Modbus responses?
2. Which card is not a response even though the client observed a result?
3. What part of Card E is the PDU?
4. Why is Card D not enough for a CRC verification exercise?
5. What evidence still proves whether raw `224` means temperature?

## Instructor Notes

- Keep learners at the labeling level. CRC/LRC calculation belongs to Module 11.
- Treat the MBAP header as a wrapper preview only; Module 12 handles Transaction Identifier, Protocol Identifier, Length, and Unit Identifier.
- Reinforce that exception responses are valid Modbus responses, while timeout/no usable response is an observation by the client.
- Do not let the raw value become engineering meaning without a source map.

## Source Notes

- Official protocol basis: Modbus Application Protocol Specification for PDU, function code, normal response, and exception response shape.
- Official transport basis: serial-line guide and TCP messaging guide for wrapper context only.
- Synthetic basis: all lab byte strings are course-authored fixtures.

## Knowledge check

# Module 2 Quiz: The Modbus Message Model
## Questions

1. What is the Modbus PDU?
   A. The transport-independent function code plus data.
   B. Only the serial CRC.
   C. Only the TCP MBAP header.
   D. A vendor register map.

2. What is the ADU?
   A. The source document for the device.
   B. The transport-specific wrapper around the PDU.
   C. A Modbus exception code.
   D. A 32-bit data type.

3. In `03 00 09 00 01`, what is `03`?
   A. Byte count.
   B. Quantity.
   C. Function code.
   D. Exception code.

4. In normal response `03 02 00 E0`, what does `02` mean?
   A. Illegal data address.
   B. Byte count.
   C. PDU address.
   D. TCP port.

5. A request using function `03` fails with an exception response. Which function byte should appear in the exception response?
   A. `03`
   B. `04`
   C. `83`
   D. `00`

6. The client receives no usable response before timeout. Which statement is correct?
   A. The server returned exception `02`.
   B. Timeout/no usable response is a client observation, not a Modbus exception response.
   C. The request succeeded.
   D. The value must be scaled differently.

7. Why is raw data `00 E0` not enough to label a dashboard value?
   A. The source map still needs to prove type, scale, unit, and validity.
   B. Modbus cannot carry register data.
   C. All raw values are coils.
   D. TCP headers provide all engineering meaning.

## Answer Key

1. A. The PDU is the core function-code-plus-data message used across transports.
2. B. The ADU wraps the PDU for RTU, ASCII, or Modbus TCP. In Modbus Security, the Modbus TCP ADU is carried over TLS.
3. C. `03` is the function code for Read Holding Registers in this example.
4. B. In a normal read response, `02` is the byte count.
5. C. Exception responses set the high bit, so `03` becomes `83`.
6. B. A timeout means no usable response arrived; it is not the same as an exception response.
7. A. The protocol returns bytes; engineering meaning comes from the source map and validation evidence.

## Distractor Review Notes

| Question | Correct | Why The Distractors Are Wrong |
|---:|---|---|
| 1 | A | B names only one serial error-check field, C names only a TCP wrapper field, and D is source documentation rather than the Modbus message body. |
| 2 | B | A is a device source, C is a response status, and D is an interpretation layered on returned register data. |
| 3 | C | A belongs in a normal read response, B is the later quantity field, and D is an exception status rather than the requested operation. |
| 4 | B | A names an exception code, C is a request address field, and D is a transport service number rather than response data length. |
| 5 | C | A would be a normal function echo, B names a different read function, and D is not the exception function byte for function `03`. |
| 6 | B | A requires a parseable exception response, C assumes success without evidence, and D jumps to data interpretation before communication is proven. |
| 7 | A | B is false because Modbus can carry register bytes, C confuses register data with coils, and D gives TCP framing semantic meaning it does not have. |

## Instructor Notes

- Use questions 5 and 6 to separate exception response from no-response troubleshooting.
- Use question 7 to connect Module 2 back to Module 1's "protocol carries raw data; map supplies meaning" rule.

## Source Notes

- Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for PDU vs ADU and general frame structure, maximum Modbus PDU size, normal response vs exception response, exception codes and exception response PDU shape, RTU/ASCII frame fields, MBAP header fields, and Modbus Security TLS wrapping.
- Synthetic byte examples remain course-authored fixtures until simulator or packet-capture evidence is version-pinned.

---
_Learn Modbus · learnmodbus.studioseventeen.io · Module 2/16 · v1.0.0 · Exported for offline / agent use._
