# Learn Modbus — Full Course > All 16 free public modules, diagrams, labs, and quizzes concatenated for offline reading or LLM ingestion. **Content version:** 1.0.0 ## Table of contents 1. [Module 1: What Modbus Is](#module-1-what-modbus-is) — _Published_ 2. [Module 2: The Message Model](#module-2-message-model) — _Published_ 3. [Module 3: Data Tables](#module-3-data-tables) — _Published_ 4. [Module 4: Function Codes](#module-4-function-codes) — _Published_ 5. [Module 5: Modbus Addressing](#module-5-modbus-addressing) — _Published_ 6. [Module 6: Register Maps](#module-6-register-maps) — _Published_ 7. [Module 7: Data Types](#module-7-data-types) — _Published_ 8. [Module 8: Scaling & Engineering Meaning](#module-8-scaling-engineering-meaning) — _Published_ 9. [Module 9: Serial Communication Basics](#module-9-serial-communication-basics) — _Published_ 10. [Module 10: RS-232, RS-422, RS-485](#module-10-rs-physical-layers) — _Published_ 11. [Module 11: RTU & ASCII Frames](#module-11-rtu-ascii-frames) — _Published_ 12. [Module 12: Modbus TCP](#module-12-modbus-tcp) — _Published_ 13. [Module 13: Gateways & Mixed Networks](#module-13-gateways-mixed-networks) — _Published_ 14. [Module 14: Troubleshooting Workflow](#module-14-troubleshooting-workflow) — _Published_ 15. [Module 15: Security & Safety](#module-15-security-safety) — _Published_ 16. [Module 16: Capstone: Real Device Integration](#module-16-capstone-real-device-integration) — _Published_ --- # Module 1: What Modbus Is > The mental model, why Modbus is still everywhere, and what it deliberately does not give you. **Phase:** Foundations **Estimated time:** 6 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/what-modbus-is ## What you'll be able to do - Describe Modbus as a request/response, client/server protocol with no built-in security. - Explain why Modbus is still dominant on factory floors despite its age. - List the three things Modbus deliberately does not give you. ## Three things people get wrong 1. **Treating Modbus as a network protocol.** It's an application-layer message format that rides on top of serial or TCP. 2. **Assuming the protocol enforces meaning.** Register 40001 has no defined meaning — it's whatever the vendor's map says. 3. **Expecting authentication or encryption.** Classic Modbus has none. Plan compensating controls (network segmentation, Modbus Security). ## From the field **The 40-year-old protocol you can't kill** A team replaced a 1990s line with brand-new variable-frequency drives. The shiny EtherCAT spec made the rounds — but the spec list quietly included 'Modbus TCP Unit ID 1'. Six months later, that fallback channel was the only thing keeping production data flowing while the EtherCAT master was being commissioned. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) - [Modbus.org — protocol overview](https://www.modbus.org/modbus-specifications) ## Lesson # Module 1 Lesson: What Modbus Is ## Learner Outcome By the end of this module, learners can explain what Modbus is, why it is still common in industrial systems, what clients and servers do, and what classic Modbus does not provide. ## Key Concepts - Modbus is an industrial application-layer messaging protocol. - A client initiates a request; a server responds. - Most common transactions read or write a small block of bits or 16-bit registers. - The same core PDU idea appears across RTU, ASCII, Modbus TCP, and Modbus Security / Modbus TCP over TLS, but each transport wraps it differently. - Classic Modbus is simple and widely supported, but it does not define discovery, rich semantic meaning, authentication, authorization, or encryption. ## Key Terms - Client: the requester that starts a Modbus transaction. - Server: the responder that returns data, accepts a supported write, returns an exception response, or does not produce a usable response. - PDU: Protocol Data Unit; the function code plus request or response data before a transport wrapper is added. - Transport: the way the Modbus message is carried, such as RTU, ASCII, TCP, or TLS-protected Modbus Security. - Register map: the external source that gives raw Modbus bits/registers meaning, scale, units, and safety context. ## Source-Grounded Explanation ### The Mental Model Modbus is a request/response protocol for moving process data between automation devices and software. A client asks for a specific operation, such as reading holding registers or writing a coil. A server returns data, echoes an accepted write, or returns an exception response. From the client's evidence view, a timeout or no usable response means no valid response arrived. Use `client` for the requester and `server` for the responder. Older documents and field conversations may still use `master` and `slave`, especially around serial RTU/ASCII. Learners should recognize those words as legacy field vocabulary, but this course uses client/server as the default. Modbus appears in PLCs, HMIs, drives, meters, remote I/O, sensors, gateways, SCADA systems, building automation, solar equipment, battery systems, lab devices, and simulator tools. It remains common because it is small, predictable, open, and easy to inspect. ### What Modbus Does Not Tell You Classic Modbus moves bits and 16-bit registers. It does not tell you that a value means temperature, breaker status, energy import, command authority, or grid frequency. That meaning comes from a register map, device manual, configuration notes, and field evidence. Classic Modbus also does not provide built-in authentication, authorization, encryption, discovery, subscription/event behavior, or a standardized high-level device model. Security, safety, network controls, and semantic mapping must be supplied by the surrounding system and integration process. ### First Transaction Sketch ```text Client -> Server: read holding register at a documented point Server -> Client: returned raw register value Course map: raw value + scale/unit = engineering value ``` The protocol carries the request and raw value. The map supplies the meaning. ## Practical Example A building controller reads supply-air temperature from the synthetic `lab_temperature_reading` row used again in Module 8. | Example Field | Value | |---|---| | Transport | Modbus TCP for this first sketch; RTU/ASCII wrappers come later | | Source label | Synthetic teaching fixture | | Client | Building controller, HMI, SCADA driver, test tool, or script | | Server | Controller, meter, PLC, simulator, or gateway-exposed device | | Operation | Read one holding register | | Function code | `03` Read Holding Registers | | Documented address | `40094` in a one-based `40001` style map | | Addressing preview | Module 5 will show why `40094` becomes PDU address `93` in this one-based `40001` style map | | Quantity | `1` register | | Data type | Signed 16-bit in this synthetic teaching example | | Scale/unit | raw `/10 deg C`; raw `0x7FFF` means unavailable | | Expected normal response | `03 02 00 E0` for raw `224`, which decodes to `22.4 deg C` | | Likely failure mode | Timeout/no usable response if no valid response arrives; exception `02` if the server reports an illegal data address | If the raw value is `224`, the course example decodes it as `22.4 deg C`. The protocol did not say temperature; the source map did. ## Common Pitfalls - Treating Modbus as a complete device model. - Assuming every server supports the same functions, addresses, ranges, data types, or write behavior. - Calling every responder a device even when it may be a gateway or simulator. - Treating legacy `master/slave` wording as the preferred course vocabulary. - Believing `40010` is literally sent as a wire address. - Assuming classic Modbus TCP is secure because it runs over Ethernet or inside a VPN. ## Check-Your-Understanding 1. Which side starts a normal Modbus request? 2. What does the server do after a successful read request? 3. Why do you still need a register map after you know the function code? 4. Name two things classic Modbus does not provide by itself. 5. A tool displays raw value `224`. What evidence do you need before calling it `22.4 deg C`? ## Source Notes - Official basis: Modbus Organization introduction and Modbus Application Protocol Specification for the client/server model, request/response behavior, function-code framing, and data model basics. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for application-layer client/server request/reply, PDU vs ADU and general frame structure, four primary logical data tables, normal response vs exception response, public function-code categories, serial client/server legacy terminology, and Modbus Security TLS wrapping. - Local course spine: `modbus-wiki.md` sections "What Modbus Is", "Why Modbus Endured", "Core Architecture", and "Data Model". - Field context: legacy terminology and common deployment examples are practical context, not new protocol rules. - Security boundary: classic Modbus security limitations are introduced here and taught in depth in Module 15. ## Completion Checkpoint Before moving on, learners should identify the client, server, operation, missing source evidence, and safety/security boundary in a short scenario. Use the scenario worksheet and quiz before introducing the PDU/ADU message model in Module 2. ## Reusable Assets - [Client/server scenario worksheet](https://learnmodbus.studioseventeen.io/resource/client-server-scenario-worksheet) - [Module 1 scenario lab](https://learnmodbus.studioseventeen.io/lesson/what-modbus-is?page=lab-1) - [Module 1 quiz](https://learnmodbus.studioseventeen.io/lesson/what-modbus-is?page=quiz) ## Diagram source ```mermaid flowchart LR C["Client
(HMI / SCADA / Tool)"] S["Server
(PLC / Meter / Drive)"] C -- "Request: function code + data" --> S S -- "Response: data OR exception" --> C ``` ## Labs ### Lab 1 # Lab 1: Client/Server Scenario Triage ## Learner Outcome Learners identify the client, server, requested operation, missing documentation, likely normal response, and likely failure bucket in short Modbus scenarios. A _failure bucket_ is one of the three ways a Modbus request can go wrong: **no response** (nothing valid comes back), **exception response** (the server answers with an error code), or **wrong value** (a normal-looking answer that decodes to the wrong meaning). Module 14 builds these three buckets into a full troubleshooting method; for now, just practice sorting each scenario into one of them. ## Prerequisites - No hardware required. - Module 1 lesson or equivalent overview of client/server request/response behavior. - [Client/server scenario worksheet](https://learnmodbus.studioseventeen.io/resource/client-server-scenario-worksheet) ## Safety And Scope This is a paper/no-hardware lab. Do not connect to production networks or devices. Do not write values to real equipment. Any write scenario is classified only as a risk and documentation exercise. ## Scenario Cards ### Card A: HMI Reads A Meter An HMI polls an energy meter every five seconds. The map says line voltage is at `40010`, unsigned 16-bit, scale `/10 V`. | Field | Expected learner answer | |---|---| | Client | HMI | | Server | Energy meter | | Source label | Synthetic teaching fixture | | Operation | Read one holding register | | Function code | `03` if the map row is a holding register | | Documented address | `40010` | | Addressing note | PDU address conversion is a Module 5 preview; do not treat `40010` as a wire address | | Missing evidence | Exact address convention, Unit Identifier or server address, transport path, value validity state | ### Card B: SCADA Writes A Start Bit A SCADA screen has a Start button for a pump. The device manual lists a command word but does not show the local/remote mode requirement. | Field | Expected learner answer | |---|---| | Client | SCADA system | | Server | Pump controller or gateway-exposed pump controller | | Source label | Synthetic teaching fixture | | Operation | Write command, not just a read | | Missing evidence | Command register, write function, allowed values, local/remote mode, interlocks, rollback/stop procedure, independent status feedback | | Safety decision | Stop. No real write without Module 15 write-safety review and approval. | ### Card C: Gateway Bridges TCP To Serial A test tool connects to a TCP gateway. The gateway routes requests to a serial drive. The tool gets no response. | Field | Expected learner answer | |---|---| | Client | Test tool | | Visible TCP endpoint | TCP gateway endpoint | | Downstream addressed server/responder | Serial drive, if the route is correct | | Source label | Synthetic teaching fixture; gateway preview for Module 13 | | Missing evidence | Unit Identifier route, serial server address, baud/parity/stop bits, gateway mode, timeout settings | | Likely bucket | No response until a valid responder or exception is proven | ### Card D: Raw Value Without A Map A script reads holding register offset `9` and prints raw value `224`. | Field | Expected learner answer | |---|---| | Client | Script | | Server | Device or simulator responding to the script | | Source label | Synthetic teaching fixture | | Operation | Read holding register | | Missing evidence | Documented address, type, scale, unit, validity conditions, source label | | Correct conclusion | Raw `224` is not yet temperature, pressure, speed, or status without the map. | ## Procedure 1. For each card, identify the client and server. 2. Name the requested operation: read bits, read registers, write bit, write register, or unknown. 3. Record the documentation still needed before interpreting the value or authorizing a write. 4. Predict the normal response shape at a high level: returned data, write echo, or exception response. If none arrives, record timeout/no usable response from the client view. 5. Mark one safety or source boundary for each scenario. 6. Complete the worksheet answer key. ## Expected Observations - A client initiates each request; a server responds or fails to provide a usable response. - A successful read proves that a value was returned from the selected table/address path, not that the raw value has engineering meaning. - A write echo proves the protocol response shape only. It does not prove the physical process changed state. - Gateway scenarios may hide the final server behind a TCP endpoint, so the visible endpoint is not always the final device that owns the data. ## Troubleshooting Notes - If the learner cannot identify the client and server, stop before changing address, scale, or byte-order assumptions. - If a response is missing, record timeout/no usable response instead of inventing an exception code. - If a raw value is returned without a register map, mark the engineering meaning as unresolved. - If a write scenario appears, require safety, authorization, rollback, and independent feedback evidence before treating it as real-device work. ## Check Questions 1. Why is "server" not always the same thing as the physical field device? 2. What does a successful read response prove, and what does it not prove? 3. Why does a write scenario require more evidence than a read-only scenario? 4. Why is a raw value not enough to create a dashboard label? ## Instructor Notes - Accept "master/slave" only when a learner is quoting legacy field language; normalize the answer back to client/server. - Do not let learners jump to byte-order or scaling fixes before they identify the source map and requested operation. - Use Card B to set up Module 15: a write echo is not physical process proof. - Use Card C to preview Module 13: the TCP endpoint may be a gateway, not the final server. ## Source Notes - Official protocol basis: Modbus Application Protocol Specification for client/server request/response behavior and function-code roles. - Local course basis: `modbus-wiki.md` Module 1 and `course-phase-drafts/phase-1-modbus-foundations.md`. - Field note: gateway and write-safety examples are scenario fixtures that preview later modules; they are not product-specific behavior. ## Knowledge check # Module 1 Quiz: What Modbus Is ## Questions 1. In modern course terminology, which side starts a normal Modbus request? A. Server B. Client C. Register D. Coil 2. What does classic Modbus primarily move? A. Rich semantic device objects. B. Bits and 16-bit registers using request/response messages. C. Encrypted event streams. D. Vendor manuals. 3. A device returns raw value `224` from a register. What is still needed before displaying it as `22.4 deg C`? A. Source-map evidence for data type, scale, unit, and validity. B. A different Ethernet cable. C. A Modbus Security certificate. D. Nothing; all registers are temperature by default. 4. Which statement is most accurate? A. Classic Modbus includes built-in authentication and authorization. B. Classic Modbus defines discovery and semantic device models. C. Classic Modbus is simple and inspectable, but surrounding documentation and controls supply meaning and safety context. D. Modbus only works on serial networks. 5. Older Modbus documents may use `master/slave`. How should this course handle that language? A. Use it as the default vocabulary. B. Ignore it completely. C. Recognize it as legacy field/document language and use client/server as the modern default. D. Treat it as a different protocol. 6. A SCADA screen sends a command to a pump controller. Why is this different from a read-only polling example? A. Writes may change process state and need safety, permission, rollback, and independent-status evidence. B. Writes are impossible in Modbus. C. Reads are always unsafe and writes are always safe. D. Commands do not use function codes. ## Answer Key 1. B. The client initiates a normal request; the server responds. 2. B. Classic Modbus moves bits and 16-bit registers; higher-level meaning comes from documentation and integration evidence. 3. A. Raw value alone is not enough; the register map or reviewed source must supply type, scale, unit, and validity. 4. C. Modbus is useful because it is simple, but it is low-context and needs surrounding documentation and controls. 5. C. Learners should recognize legacy terms but use client/server as the course default. 6. A. Writes require safety review because a protocol-level response does not prove the intended physical state. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A reverses the request/response roles, and C/D name data model items rather than the side that initiates a transaction. | | 2 | B | A invents semantic objects, C adds security behavior not present in classic Modbus, and D is documentation rather than protocol payload. | | 3 | A | B is unrelated to data meaning, C addresses transport security rather than interpretation, and D invents a universal temperature meaning. | | 4 | C | A invents built-in authorization, B invents discovery/semantics, and D ignores Modbus TCP and other transports. | | 5 | C | A makes legacy terms the default, B prevents learners from reading older sources, and D treats vocabulary as a protocol fork. | | 6 | A | B denies write functions, C reverses safety judgment, and D ignores that commands still use function-code-defined Modbus operations. | ## Instructor Notes - If learners miss question 3, revisit the difference between protocol transport and semantic meaning. - If learners miss question 6, mark Module 15 write-safety content as a later reinforcement point. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for application-layer client/server request/reply, four primary logical data tables, serial client/server legacy terminology, normal response vs exception response, public function-code categories, write function echo boundaries where write-safety questions appear, and Modbus Security TLS wrapping where security contrasts appear. - Security and write-safety items remain introductory course framing until Module 15 source/safety review. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 1/16 · v1.0.0 · Exported for offline / agent use._ # 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 ``` | 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._ # Module 3: Data Tables > Coils, discrete inputs, input registers, and holding registers — the four primitives. **Phase:** Foundations **Estimated time:** 7 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/data-tables ## What you'll be able to do - Pick the right Modbus data table for a given device signal. - Explain why a vendor map of 'inputs' rarely means 'discrete inputs'. - Use the table to predict which function codes are legal. ## Three things people get wrong 1. **Assuming 'input' means discrete input.** Vendors use 'input' for analog input registers (table 3) far more often than for discrete inputs (table 2). 2. **Writing to a register because FC 06 is 'allowed'.** Allowed at the protocol layer is not the same as safe at the device layer. Check the map's R/W column. 3. **Mixing tables across one transaction.** Each read function code targets exactly one table. Plan separate reads for coils, registers, and inputs. ## From the field **When a holding register killed a setpoint** An operator's HMI cycled FC 16 to 'refresh' a value it had just read. The PLC accepted the writes, overwriting a recipe parameter someone had nudged manually that morning. Reads and writes use the same table — that's the whole point, and it bites if you forget it. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — Data model — section 4.3 ## Lesson # Module 3 Lesson: Data Tables ## Learner Outcome By the end of this module, learners can distinguish the four primary Modbus logical data tables, choose the likely table and access pattern for common field values, and explain why documentation prefixes are not wire-level fields. ## Key Concepts - Coils are 1-bit read/write items. - Discrete inputs are 1-bit read-only items. - Input registers are 16-bit read-only words. - Holding registers are 16-bit words commonly used for read/write values, though many devices also expose read-only measurements there. - The function code selects the logical table; the PDU address selects an offset inside that table. - Prefixes such as `0xxxx`, `1xxxx`, `3xxxx`, and `4xxxx` are documentation conventions, not bytes sent on the wire. - Real device maps can bend the clean teaching model; vendor-specific mapping must be labeled as product behavior. ## Key Terms - Coil: a single-bit read/write logical point often used for discrete commands or states. - Discrete input: a single-bit read-only logical point. - Input register: a 16-bit read-only register. - Holding register: a 16-bit register that is commonly read and may be writable depending on the device map. - Logical table: the Modbus data area selected by function code and source-map context. - Access: whether the point is read-only, write-capable, reserved, or otherwise constrained by the device. ## Source-Grounded Explanation ### The Four Logical Tables Modbus defines a logical data model with four primary table types: | Table | Object Type | Typical Access | Legacy Prefix | Common Read Function | Common Write Function | |---|---|---|---|---:|---:| | Coils | 1-bit | Read/write | `0xxxx` | `01` | `05`, `15` | | Discrete inputs | 1-bit | Read-only | `1xxxx` | `02` | Not writable | | Input registers | 16-bit word | Read-only | `3xxxx` | `04` | Not writable | | Holding registers | 16-bit word | Read/write table | `4xxxx` | `03` | `06`, `16` | Advanced holding-register write-capable functions such as `22` and `23` are covered later with write-safety controls. This table is the protocol mental model. It does not prove how a device stores data internally, whether a device implements every table, or whether a vendor exposes a measurement through input registers or holding registers. ### Function Code Selects The Table The function code is what tells the server which logical table the request targets. The documentation prefix helps humans read the map, but it is not sent as a leading digit in the PDU. For example, coil offset `0`, discrete input offset `0`, input register offset `0`, and holding register offset `0` can all exist without conflict because they live in different logical tables. The function code separates them: | Request | Meaning | |---|---| | Function `01`, address `0` | Read coil offset `0` | | Function `02`, address `0` | Read discrete input offset `0` | | Function `04`, address `0` | Read input register offset `0` | | Function `03`, address `0` | Read holding register offset `0` | Address conversion details are taught in Module 5. In Module 3, the learner's job is to stop treating the prefix as a wire byte and start asking, "Which table does this row belong to, and which function reads or writes that table?" ### Field Practice Caveat Real device maps often blur the neat categories: - A measurement may appear in holding registers instead of input registers. - A status may be exposed as a packed bitfield inside a holding register instead of as separate discrete inputs. - A command may be a coil, a holding-register bit, an enum value, or a multi-step write workflow. - A table may be documented as read/write even though specific rows are read-only or protected by local/remote mode. Those are map and device behaviors, not changes to the core logical model. Label them as vendor-specific notes or synthetic fixture behavior until verified. ## Practical Example: Synthetic Four-Table Map | Signal | Likely Table | Documented Reference | PDU Address Preview | Access | Type | Scale/Unit | Function To Read | Function To Write | |---|---|---:|---:|---|---|---|---:|---:| | Pump run command | Coil | `00001` | `0` | Read/write | Boolean | On/off | `01` | `05` or `15` | | Door interlock closed | Discrete input | `10002` | `1` | Read-only | Boolean | Closed/open | `02` | Not writable | | Supply temperature | Input register | `30010` | Module 5 preview | Read-only | U16 | `/10 deg C` | `04` | Not writable | | Speed setpoint | Holding register | `40020` | Module 5 preview | Read/write in simulator | U16 | RPM | `03` | `06` or `16` | | Alarm word | Holding register | `40030` | Module 5 preview | Read-only in this fixture | U16 bitfield | none | `03` | Not writable unless source proves it | Source label: synthetic teaching fixture. Worked distinction: ```text Read coil offset 0: function 01, address 0 Read discrete input offset 0: function 02, address 0 ``` The numeric offset can match. The function code selects a different logical table. ## Common Pitfalls - Treating `40001` as a literal numeric address sent on the wire. - Choosing function `04` only because the value is an "input" to a software dashboard. - Assuming every measurement must be in input registers. - Trying to write to discrete inputs or input registers. - Assuming every holding-register row is safe or allowed to write. - Forgetting that status and alarms are often packed into 16-bit registers. - Treating a vendor-specific map decision as a universal Modbus rule. ## Check-Your-Understanding 1. Which table is 1-bit and read/write? 2. Which table is 1-bit and read-only? 3. Which common function reads input registers? 4. What selects the table in the request: the legacy prefix or the function code? 5. Why can two values both use address offset `0` without conflicting? 6. What evidence is needed before writing to a holding-register row? ## Source Notes - Official basis: Modbus Application Protocol Specification for logical data tables, PDU address fields, and common table/function-code mapping. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, and read function rows for coils, discrete inputs, input registers, and holding registers. - Local course spine: `modbus-wiki.md` sections "Data Model", "Addressing", "Function Codes", and "Reading OEM Modbus Maps". - Field note: real device maps can expose measurements, statuses, and commands in product-specific ways; vendor manuals govern named-device behavior. - Synthetic basis: example map rows are course-authored teaching fixtures. ## Completion Checkpoint Before moving on, learners should classify a point as coil, discrete input, input register, holding register, or needs verification, then explain what evidence they used. They should not infer a safe write just because a row appears near write-capable function codes. ## Reusable Assets - [Four-table data model reference](https://learnmodbus.studioseventeen.io/resource/four-table-data-model-reference) - [Data table classification worksheet](https://learnmodbus.studioseventeen.io/resource/data-table-classification-worksheet) - [Module 3 lab](https://learnmodbus.studioseventeen.io/lesson/data-tables?page=lab-1) - [Module 3 quiz](https://learnmodbus.studioseventeen.io/lesson/data-tables?page=quiz) ## Diagram source ```mermaid flowchart TB M["Modbus Data Model"] M --> C["Coils
1-bit · R/W"] M --> DI["Discrete Inputs
1-bit · Read only"] M --> HR["Holding Registers
16-bit · R/W"] M --> IR["Input Registers
16-bit · Read only"] ``` ## Labs ### Lab 1 # Lab 4: Data Table Classification ## Learner Outcome Learners classify common field signals into likely Modbus logical tables, identify read/write access expectations, choose likely read/write functions, and record source questions before integration. ## Prerequisites - Module 1 client/server mental model. - Module 2 PDU/ADU and response-shape basics. - Module 3 lesson or equivalent introduction to coils, discrete inputs, input registers, and holding registers. - [Four-table data model reference](https://learnmodbus.studioseventeen.io/resource/four-table-data-model-reference) - [Data table classification worksheet](https://learnmodbus.studioseventeen.io/resource/data-table-classification-worksheet) ## Safety And Scope This is a no-hardware classification lab. Do not connect to devices or write to equipment. Write-capable examples are source-review prompts only. ## Scenario A synthetic training controller exposes a small map for a pump skid. Learners must classify the signals before any polling or writing occurs. Source label: synthetic teaching fixture. | Signal | Source Wording | Learner Task | |---|---|---| | Pump run command | `00001`, R/W, Boolean | Identify likely coil table and read/write functions. | | Door interlock closed | `10002`, R, Boolean | Identify likely discrete-input table and read-only access. | | Supply temperature | `30010`, R, U16, `/10 deg C` | Identify likely input-register table and read function. | | Speed setpoint | `40020`, R/W, U16, RPM | Identify likely holding-register table and write-safety questions. | | Alarm word | `40030`, R, U16 bits | Identify holding-register bitfield and do not assume write access. | | Line voltage | Source says only `Offset 9`, U16, `/10 V` | Mark table/function/address convention as unresolved. | ## Procedure 1. For each signal, choose the likely logical table. 2. Record the common read function. 3. Record the write function only when the table and source access allow it. 4. Mark any source questions: table, access, address convention, data type, scale/unit, state/validity, or safety requirement. 5. Explain why the same offset number can appear in more than one table. 6. Identify which rows are unsafe or unsupported to write. ## Answer Key | Signal | Expected Classification | |---|---| | Pump run command | Coil; read with `01`; write with `05` or `15` only in approved simulator or reviewed device context. | | Door interlock closed | Discrete input; read with `02`; not writable. | | Supply temperature | Input register; read with `04`; not writable. | | Speed setpoint | Holding register; read with `03`; possible write with `06` or `16` only after write-safety review. | | Alarm word | Holding register bitfield; read with `03`; do not write unless source proves access and safety. | | Line voltage | Needs verification; source row lacks table/function/address convention. | ## Expected Observations - Discrete inputs and input registers are read-only from the Modbus data-model view used in this course. - Coils and holding registers may be write-capable, but access and safety still depend on the source map and reviewed device context. - The same numeric offset can appear in more than one logical table; the table/function context is part of the address evidence. - Weak source rows should produce "needs verification" instead of a guessed function code. ## Troubleshooting Notes - If learners classify every number as a holding register, redirect them to the signal type, access direction, and read function. - If a row lacks table/function/address convention, mark it unresolved instead of forcing a request. - If a write-capable table appears, require a write-safety stop before any real command is considered. - If the value looks wrong but the table is uncertain, test table/function selection before scale, byte order, or word order. ## Check Questions 1. Which examples are read-only by logical table? 2. Which examples are write-capable by table but still require safety review? 3. Why is `Offset 9` incomplete documentation? 4. Why does a holding register not automatically mean "safe to write"? 5. What selects the logical table in the actual request? ## Instructor Notes - Keep address-base math light. Module 5 handles conversion and off-by-one troubleshooting. - Accept "likely table" only when the source row has enough evidence; otherwise require "needs verification." - Use the alarm word to preview Module 8 bitfields. - Use the speed setpoint to preview Module 15 write safety. ## Source Notes - Official protocol basis: Modbus Application Protocol Specification for logical table model and function-code mapping. - Synthetic basis: all scenario rows are course-authored fixtures. - Field note: real vendor maps may expose measurements and status through product-specific table choices; do not generalize those choices without a named source. ## Knowledge check # Module 3 Quiz: Data Tables ## Questions 1. Which Modbus table is 1-bit and commonly read/write? A. Coils B. Discrete inputs C. Input registers D. Holding registers 2. Which table is 1-bit and read-only? A. Coils B. Discrete inputs C. Input registers D. Holding registers 3. Which common function reads input registers? A. `01` B. `02` C. `03` D. `04` 4. A manual shows `40020`. What selects the holding-register table in the actual request? A. The ASCII character `4` sent before the address. B. The function code. C. The TCP port. D. The scale factor. 5. A device map lists an alarm word as `40030`, R, U16 bits. What is the safest interpretation? A. It is a holding-register bitfield that should be read and decoded; do not write unless the source proves write access and safety. B. It is a discrete input because alarms are binary. C. It must be writable because it starts with `4`. D. It is not Modbus. 6. A row says only `Offset 9`, U16, `/10 V`. What should the learner do? A. Assume holding register function `03`. B. Mark table/function/address convention as unresolved. C. Write to it with function `06`. D. Treat it as a coil. 7. Why can coil offset `0` and discrete input offset `0` both exist? A. They are selected by different function codes and logical tables. B. One is always TCP and one is always serial. C. Modbus forbids this. D. The PDU sends the `0xxxx` and `1xxxx` prefixes as bytes. ## Answer Key 1. A. Coils are 1-bit logical items with read/write functions. 2. B. Discrete inputs are 1-bit read-only items. 3. D. Function `04` reads input registers. 4. B. The function code selects the table; prefixes are documentation conventions. 5. A. A holding register can contain packed bits and may still be read-only by source permission. 6. B. Bare offsets need source evidence before choosing table/function/address convention. 7. A. The same offset can exist in different logical tables because the function code selects the table. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | A | B is one-bit but read-only, and C/D are 16-bit register tables rather than the coil table. | | 2 | B | A is commonly read/write, while C/D are register tables, not one-bit discrete input items. | | 3 | D | A reads coils, B reads discrete inputs, and C reads holding registers rather than input registers. | | 4 | B | A treats documentation notation as wire data, C is only a transport service number, and D is an engineering interpretation field. | | 5 | A | B moves the point to a different table without source evidence, C assumes write permission from the prefix, and D rejects a normal Modbus modeling pattern. | | 6 | B | A invents the table, C jumps to a write, and D changes the data type and table without evidence. | | 7 | A | B invents a transport split, C denies valid separate table offsets, and D treats documentation prefixes as PDU bytes. | ## Instructor Notes - Questions 4 and 7 reinforce prefixes-not-on-wire without turning Module 3 into the full addressing module. - Questions 5 and 6 test source discipline and write-safety instincts. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, and read function rows for coils, discrete inputs, input registers, and holding registers. - Vendor-map meaning, access, and bit labels remain source-specific rather than official protocol behavior. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 3/16 · v1.0.0 · Exported for offline / agent use._ # Module 4: Function Codes > Reads, writes, diagnostics, and the codes you'll actually meet in the field. **Phase:** Foundations **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/function-codes ## What you'll be able to do - Recite the four read codes and the four write codes from memory. - Pick FC 03 vs FC 04 vs FC 06 vs FC 16 for a given task. - Parse an exception PDU into function code + exception code. ## Three things people get wrong 1. **Using FC 06 for two registers.** FC 06 writes one register only. FC 16 writes a contiguous block in one request, but device-level atomic behavior still requires vendor documentation or verified lab evidence. 2. **Sending FC 02 to a holding-register map.** Wrong table. Use FC 03 (holding) or FC 04 (input). 3. **Ignoring the 0x80 bit on the response FC.** Any returned FC ≥ 0x80 is an exception — read the next byte for the cause. ## From the field **The device that lied about its function codes** A cheap meter advertised support for FC 03 and FC 04 but actually mirrored the same registers behind both. Integrators kept asking why the 'input' values matched the 'holding' values. The capture showed identical byte sequences on either FC. Trust the bus, not the brochure. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — Function code definitions — section 6 ## Lesson # Module 4 Lesson: Function Codes ## Learner Outcome By the end of this module, learners can select and interpret the most common public Modbus function codes for reading and writing coils and registers, recognize function-code exception behavior, and explain why write echoes are not physical proof. ## Key Concepts - Function codes are one-byte operation selectors. - Common read functions target a table and a quantity. - Common write functions target writable coils or holding registers. - Devices do not have to support every public function code. - Exception responses use the requested function code plus `0x80`. - A successful write response proves protocol acceptance, not the intended physical process state. Related foundations: - [Module 2: The Modbus Message Model](https://learnmodbus.studioseventeen.io/lesson/message-model) - [Module 3: Data Tables](https://learnmodbus.studioseventeen.io/lesson/data-tables) ## Key Terms - Public function code: a standardized operation code defined for common Modbus actions. - Read function: a function that requests coils, discrete inputs, input registers, or holding registers. - Write function: a function that requests a server to change coil or register state. - Write echo: the normal response pattern for many writes; useful protocol evidence but not physical process proof. - Quantity limit: the maximum number of coils or registers a specific function can request. - Safety boundary: the course rule that write-capable examples stay simulator-only or formally reviewed before real-device use. ## Source-Grounded Explanation ### Common Read Functions | Decimal | Hex | Name | Logical Table | Request Shape | Normal Response Shape | |---:|---:|---|---|---|---| | 1 | `0x01` | Read Coils | Coils | starting address + quantity | function + byte count + packed bits | | 2 | `0x02` | Read Discrete Inputs | Discrete inputs | starting address + quantity | function + byte count + packed bits | | 3 | `0x03` | Read Holding Registers | Holding registers | starting address + quantity | function + byte count + register bytes | | 4 | `0x04` | Read Input Registers | Input registers | starting address + quantity | function + byte count + register bytes | The function code selects the logical table. The PDU address selects the offset inside that table. A value being an "input" to a dashboard does not mean function `04` is correct; the source map must identify the table. ### Common Write Functions | Decimal | Hex | Name | Logical Table | Request Shape | Normal Response Shape | |---:|---:|---|---|---|---| | 5 | `0x05` | Write Single Coil | Coils | address + output value | echo function + address + value | | 6 | `0x06` | Write Single Register | Holding registers | address + register value | echo function + address + value | | 15 | `0x0F` | Write Multiple Coils | Coils | start + quantity + byte count + packed values | echo function + start + quantity | | 16 | `0x10` | Write Multiple Registers | Holding registers | start + quantity + byte count + register values | echo function + start + quantity | Advanced holding-register write-capable functions such as mask write register `22` and read/write multiple registers `23` exist, but they are not the core Module 4 write set. Treat them as advanced and safety-relevant until covered with specific source evidence. ### Exception Behavior If a server returns an exception response, the response function byte is the requested function code plus `0x80`. | Requested Function | Exception Function Byte | |---:|---:| | `01` | `81` | | `03` | `83` | | `06` | `86` | | `10` | `90` | Useful early exceptions: - `01` Illegal Function: the server does not support the requested function in that context. - `02` Illegal Data Address: the requested address or range is not available for that function/context. - `03` Illegal Data Value: a value, quantity, byte count, or request structure is not acceptable. - `04` Server Device Failure: the server failed while attempting the requested action. Timeout/no usable response is not an exception response. It means the client did not receive a valid Modbus response. ### Common Quantity Limits Common quantity limits come from the official application protocol and the 253-byte PDU size: | Function | Maximum Quantity | |---|---:| | Read Coils `01` | 2000 bits | | Read Discrete Inputs `02` | 2000 bits | | Read Holding Registers `03` | 125 registers | | Read Input Registers `04` | 125 registers | | Write Multiple Coils `15` | 1968 bits | | Write Multiple Registers `16` | 123 registers | Learners should use the quick reference rather than diagnosing oversized requests as network problems. Advanced/deferred note: Read/Write Multiple Registers `23` has official limits of 125 registers read and 121 registers written, but it is not part of the core Module 4 function-code set. ### Write Safety Boundary A write response echo means the server accepted the Modbus write transaction. It does not prove that a pump started, a drive changed speed, a relay moved, or an interlock allowed the command to affect the process. Real-device write behavior can depend on local/remote mode, interlocks, operating state, reserved bits, write-enable registers, command confirmation patterns, or separate status feedback. Module 4 introduces that boundary; Module 15 handles write safety in depth. ## Practical Example: Simulator-Only Setpoint Write Synthetic teaching fixture: | Example Field | Value | |---|---| | Source label | Synthetic teaching fixture | | Transport | PDU-only worksheet or simulator after toolchain verification | | Function code | `06` Write Single Register | | Documented address | `40020` | | PDU address | `0x0013` | | Quantity | One 16-bit register | | Data type | Unsigned 16-bit | | Scale/unit | RPM in this fixture | | Desired value | `215` RPM | | PDU request | `06 00 13 00 D7` | | Expected normal response | Echo of `06 00 13 00 D7` | | Likely exception | `86 02` for illegal data address; `86 03` for unacceptable value | | Required confirmation | Separate read or status feedback in simulator; no real-device write in this module | Read/write comparison: ```text Read holding register: 03 00 13 00 01 Write one holding register: 06 00 13 00 D7 ``` The address is the same because both operations target the holding-register table. The function code changes the operation. Simulator confirmation step: ```text Read back the same simulator holding register after the write. Record the returned raw value and compare it to the requested value. ``` This confirms simulator state for the exercise. It still does not authorize real-device writes. ## Common Pitfalls - Choosing function `04` because a value is an input to software instead of checking the source map. - Treating `83 02` as a normal response from function `83`. - Assuming exception `02` means the device is dead. It means a responder returned illegal data address. - Treating timeout/no response as an exception. - Assuming support for `16` because `06` works. - Writing to a holding-register row just because holding registers are write-capable as a table. - Trusting write echo as physical process proof. ## Check-Your-Understanding 1. Which function reads holding registers? 2. Which function writes one coil? 3. Which function writes one holding register? 4. If function `03` receives an exception response, what function byte appears? 5. What is the difference between exception `83 02` and a timeout? 6. Why does a write lab use a simulator before real equipment? ## Source Notes - Official basis: Modbus Application Protocol Specification for function-code ranges, common public function behavior, normal response shape, exception response shape, and common quantity limits. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for public function-code categories, maximum Modbus PDU size, read quantity limits, write single coil/register shape and echo boundary, write multiple coils/registers quantity limits, mask write register, read/write multiple registers, normal response vs exception response, and exception response PDU shape. - Local course spine: `modbus-wiki.md` sections "Function Codes", "Common Quantity Limits", "Exception Responses", and "Write Semantics and Control Registers". - Safety boundary: `release/write-function-risk-reference.md` and Module 15 expand real-device write controls. - Synthetic basis: request/response examples are course-authored fixtures unless later verified against a simulator. ## Completion Checkpoint Before moving on, learners should choose the likely function code for a read or write scenario, label the expected normal response shape, and explain why a write response is not evidence that the physical process reached the intended state. ## Reusable Assets - [Function-code quick reference](https://learnmodbus.studioseventeen.io/resource/function-code-quick-reference) - [Exception-code quick reference](https://learnmodbus.studioseventeen.io/resource/exception-code-quick-reference) - [Write-function risk reference](https://learnmodbus.studioseventeen.io/resource/write-function-risk-reference) - [Module 4 function-code lab](https://learnmodbus.studioseventeen.io/lesson/function-codes?page=lab-1) - [Module 4 quiz](https://learnmodbus.studioseventeen.io/lesson/function-codes?page=quiz) ## Diagram source ```mermaid flowchart LR R["Reads"] --> R1["01 Read Coils"] R --> R2["02 Read Discrete Inputs"] R --> R3["03 Read Holding Regs"] R --> R4["04 Read Input Regs"] W["Writes"] --> W1["05 Write Single Coil"] W --> W2["06 Write Single Reg"] W --> W3["15 Write Multi Coils"] W --> W4["16 Write Multi Regs"] ``` ## Labs ### Lab 1 # Lab 16: Function-Code Decode Drill Supporting modules: 2, 3, 14, 15 Estimated time: 40-60 minutes Release state: draft; course-owned localhost simulator smoke test passed for write echo/readback; third-party tool, final source, and safety review pending ## Learner Outcome Learners identify common read/write function codes, classify normal and exception responses, and separate write echo from independent state confirmation. ## Prerequisites - Module 2 response/exception labeling. - Module 3 data-table classification. - [Function-code quick reference](https://learnmodbus.studioseventeen.io/resource/function-code-quick-reference) - [Exception-code quick reference](https://learnmodbus.studioseventeen.io/resource/exception-code-quick-reference) - [Write-function risk reference](https://learnmodbus.studioseventeen.io/resource/write-function-risk-reference) ## Safety And Scope This is a no-hardware/simulator-first lab. Do not write to real devices. Write examples are synthetic fixtures and safety prompts. The course-owned smoke simulator verifies the local write echo/readback path, but that does not authorize any real-device write. ## Decode Cards ### Card A: Read Holding Register ```text 03 00 13 00 01 ``` | Field | Expected answer | |---|---| | Source label | Synthetic teaching fixture | | Operation | Read Holding Registers | | Function | `03` | | Table | Holding registers | | PDU address | `0x0013` | | Quantity | `1` register | | Expected normal response | `03` + byte count + two data bytes | ### Card B: Write Single Register ```text 06 00 13 00 D7 ``` | Field | Expected answer | |---|---| | Source label | Synthetic write fixture | | Operation | Write Single Register | | Function | `06` | | Table | Holding registers | | PDU address | `0x0013` | | Value | `0x00D7`, decimal `215` | | Expected normal response | Echo of `06 00 13 00 D7` | | Safety boundary | Write echo is not physical state proof | ### Card C: Exception To Read Holding Register ```text 83 02 ``` | Field | Expected answer | |---|---| | Source label | Synthetic teaching fixture | | Original function | `03` | | Response type | Exception response | | Exception code | `02`, illegal data address | | Meaning | A responder parsed enough to reject the requested address/range | ### Card D: Write Single Coil ```text 05 00 00 FF 00 ``` | Field | Expected answer | |---|---| | Source label | Synthetic write fixture | | Operation | Write Single Coil | | Function | `05` | | Table | Coils | | PDU address | `0x0000` | | Value | `FF 00` means ON for this standard write-coil request shape | | Safety boundary | Simulator only; real commands require Module 15 review | ### Card E: Timeout Observation The client sends function `03` and receives no usable response. | Field | Expected answer | |---|---| | Response type | Timeout/no usable response | | Is it exception `83 02`? | No | | First checks | Path, wrapper, serial settings, server address, Unit Identifier/gateway route, malformed frame, silent discard | ### Card F: Simulator Readback Confirmation After Card B, the learner performs a separate simulator readback: ```text 03 00 13 00 01 ``` The simulator response returns raw value `00 D7`. | Field | Expected answer | |---|---| | Source label | Synthetic simulator-planned fixture | | Purpose | Confirm simulator state after a write | | Function | `03` Read Holding Registers | | Readback value | `0x00D7`, decimal `215` | | Boundary | Simulator readback confirms this exercise only; it does not authorize or prove real-device physical state | Course-owned smoke transcript: ```text write_request_pdu: 06 00 13 00 D7 write_response_pdu: 06 00 13 00 D7 readback_request_pdu: 03 00 13 00 01 readback_response_pdu: 03 02 00 D7 ``` Learner-style command evidence is available through: ```bash python3 tools/modbus_tcp_smoke.py cli-transcript ``` ## Procedure 1. Identify each function code. 2. Name the target table. 3. Label request fields: address, quantity, value, byte count, or exception code. 4. Classify response cases as normal, exception, or timeout/no usable response. 5. Mark any write case as simulator-only until safety review. 6. Answer the check questions. ## Expected Observations - Read requests identify table and quantity through the function code plus address/count fields. - Write single-register and write single-coil normal responses echo the request fields, but that echo is not physical process proof. - Exception cards prove that a responder parsed enough of the request to reject it with a Modbus exception. - Timeout/no usable response remains separate from exception handling and should move learners into transport/path troubleshooting. - The simulator readback fixture confirms only the synthetic simulator state for this exercise. ## Troubleshooting Notes - If learners treat a write echo as final state evidence, require a separate readback and an explicit simulator-only boundary. - If learners choose function `04` for all measurements, redirect them to the source map and table evidence. - If a timeout occurs, verify path, wrapper, server address, Unit Identifier, framing, and checksum before changing the function code. - If an exception appears, check requested table, address range, quantity, and function support before diagnosing byte order or scale. ## Check Questions 1. Which cards are write-capable operations? 2. Which card proves a responder returned a Modbus exception? 3. Which card proves no usable response arrived but does not prove exception `02`? 4. What separate evidence would confirm a simulator write changed state? 5. Why is function `04` not automatically correct for every measurement? ## Instructor Notes - Keep this lab at PDU/function-code level; transport checks belong to Modules 11 and 12. - Use Card B and Card D to preview Module 15 write-safety stops. - Require learners to say "write echo" rather than "the machine changed." - Use Card F to distinguish simulator readback evidence from real-device physical proof. - If learners diagnose timeout as wrong address first, redirect them to Module 14's no-response branch. ## Source Notes - Official protocol basis: Modbus Application Protocol Specification for function-code behavior, response shape, and exception response shape. - Synthetic basis: all byte strings and the localhost smoke simulator path are course-authored fixtures. - Safety basis: real-device writes are out of scope until Module 15 safety review. ## Knowledge check # Module 4 Quiz: Function Codes ## Questions 1. Which function reads holding registers? A. `01` B. `02` C. `03` D. `05` 2. Which function writes one coil? A. `04` B. `05` C. `06` D. `16` 3. Which function writes one holding register? A. `02` B. `03` C. `05` D. `06` 4. A function `03` request receives `83 02`. What does `83` mean? A. A normal function `83` response. B. Exception response to function `03`. C. TCP port 83. D. A write confirmation. 5. What does exception code `02` usually indicate? A. Illegal function. B. Illegal data address. C. Server device busy. D. A successful write. 6. The client receives no usable response before timeout. Which statement is correct? A. The server returned exception `02`. B. Timeout is a client observation, not a Modbus exception response. C. The value should be scaled differently. D. Function `04` should always be used next. 7. A write single register response echoes the requested value. What does that prove? A. The physical machine definitely changed state. B. The server accepted the Modbus write transaction at the protocol level. C. The value is safe on any real device. D. The register map is no longer needed. 8. Why should real-device writes not be part of Module 4? A. Modbus has no write functions. B. Write behavior can affect physical processes and needs Module 15 safety review, source evidence, and independent feedback. C. Function codes do not apply to writes. D. Holding registers are always read-only. ## Answer Key 1. C. Function `03` reads holding registers. `01` and `02` read one-bit tables, and `05` is a write function for a single coil. 2. B. Function `05` writes one coil. `04` reads input registers, `06` writes one holding register, and `16` writes multiple holding registers. 3. D. Function `06` writes one holding register. `03` reads holding registers, while `02` and `05` target different tables or operations. 4. B. Exception responses add `0x80` to the requested function, so `03` becomes `83`. It is not a normal function `83`, a TCP port, or a write confirmation. 5. B. Exception `02` is illegal data address. Illegal function is `01`, and a successful write would use a normal write response rather than an exception. 6. B. Timeout/no usable response is a client observation, not a Modbus exception response. Exception `02` would require a parseable exception response such as `83 02`. 7. B. A write echo proves the server accepted the Modbus write transaction at the protocol level. It does not prove physical state, safety, or that the register map can be ignored. 8. B. Real writes can affect physical processes and require Module 15 safety review, source evidence, and independent feedback. Modbus does have write functions, but Module 4 keeps them simulator-only. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | C | A/B read one-bit tables, and D is a single-coil write function rather than a holding-register read. | | 2 | B | A reads input registers, C writes one holding register, and D writes multiple holding registers. | | 3 | D | A reads discrete inputs, B reads holding registers, and C writes one coil. | | 4 | B | A invents a normal function `83`, C confuses the byte with a port number, and D treats an exception as a write confirmation. | | 5 | B | A is exception `01`, C is a different exception code, and D would use a normal write response rather than exception `02`. | | 6 | B | A requires a valid exception response, C jumps to value interpretation, and D applies a read function without evidence. | | 7 | B | A/C/D overstate what the protocol echo proves and skip physical-state, safety, and source-map checks. | | 8 | B | A/C deny Modbus write functions, and D invents a universal read-only rule for holding registers. | ## Instructor Notes - Use questions 6 and 7 to separate troubleshooting branches and write-safety boundaries. - Questions 1-3 should be fast recall; questions 4-8 test application. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for public function-code categories, read quantity limits, write single coil/register shape and echo boundary, write multiple coils/registers quantity limits, and exception codes and exception response PDU shape. - Real-device write questions remain safety-gated; normal write echoes are protocol evidence, not proof of physical state. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 4/16 · v1.0.0 · Exported for offline / agent use._ # Module 5: Modbus Addressing > 0-based wire addresses vs 1-based documentation, and how off-by-one bugs are born. **Phase:** Addressing & Data Meaning **Estimated time:** 6 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/modbus-addressing ## What you'll be able to do - Convert documented (40001-style) addresses to PDU wire addresses correctly. - Explain why the same register is called 40001 in one tool and 0 in another. - Spot off-by-one bugs from a capture in under a minute. ## Three things people get wrong 1. **Subtracting 1 instead of 40001.** Documented holding 40001 → PDU 0, not 40000. The 4xxxx digit prefix marks the data table, not an offset. 2. **Confusing 'register number' with 'address'.** Always restate as 'documented address X → PDU address Y' before sending anything. 3. **Assuming all tools use the same convention.** Some tools are 1-based, some 0-based. Verify with a known-good register before any write. ## From the field **The off-by-one that swapped a setpoint** A SCADA integrator copied the documented address straight into a 0-based tool. The PLC happily wrote the requested value to the register one below the intended setpoint — which happened to be a calibration constant. Production drifted for two days before someone diffed the trends. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — Addressing model — section 4.4 ## Lesson # Module 5 Lesson: Modbus Addressing ## Learner Outcome By the end of this module, learners can translate common Modbus documentation references such as `40001`, `40010`, and `400001` into the function code and zero-based PDU address used in a real request. They can also diagnose a likely off-by-one addressing problem without changing unrelated serial, TCP, Unit Identifier, byte-order, or scaling settings. ## Key Concepts - The Modbus request carries a function code, starting PDU address, and quantity. - PDU addresses are zero-based offsets from `0` to `65535`. - Legacy prefixes such as `0xxxx`, `1xxxx`, `3xxxx`, and `4xxxx` are documentation conventions, not bytes sent on the wire. - The function code selects the logical table. - Human documentation is often one-based; protocol addressing is zero-based. - Client tools differ in what they ask learners to enter. ## Key Terms - Documented address: the register or point reference shown in a manual, map, tool, or worksheet. - PDU address: the zero-based address field sent inside the Modbus request. - Zero-based: counting starts at `0`, as the protocol address field does. - One-based: counting starts at `1`, as many human-facing register maps do. - Table prefix: a documentation convention such as `4xxxx`; it is not sent as a protocol byte. - Address-entry mode: the convention a specific tool expects when the learner enters an address. ## Source-Grounded Explanation Official Modbus behavior is simpler than most vendor tables make it look. A read request does not send the text `40010`. It sends a function code, such as `03` for Read Holding Registers, and a two-byte starting address, such as `00 09` for PDU address `9`. The confusing layer is documentation. A traditional holding-register reference starts at `40001`, but the first PDU address in the holding-register table is `0`. That means a documentation row named `40010` usually points to PDU address `9`. The prefix is not the table on the wire. The function code is the table selection. For example: | Documentation Reference | Logical Table | Likely Function Code | First PDU Address To Try | |---|---|---:|---:| | `00017` | Coils | `01` read, `05` or `15` write | `16` | | `10008` | Discrete inputs | `02` read | `7` | | `30025` | Input registers | `04` read | `24` | | `40010` | Holding registers | `03` read, `06` or `16` write | `9` | | `400001` | Holding registers, 6-digit notation | `03` read, `06` or `16` write | usually `0` | Field note: some devices, drivers, gateways, or dialects use different conventions. Treat those as documented implementation behavior, not as the default protocol rule. When the manual is ambiguous, record the assumption and test both likely offsets before changing unrelated settings. ## Practical Example Device documentation: | Name | Register | Access | Type | Scale | Unit | |---|---:|---|---|---:|---| | Line voltage L1-L2 | `40010` | Read | unsigned 16-bit | `0.1` | V | Expected request: | Item | Value | |---|---| | Transport | Modbus TCP or Modbus RTU; PDU fields are the same | | Function code | `03` Read Holding Registers | | Documented address | `40010` | | Actual PDU address | `9` | | Quantity | `1` register | | Data type | unsigned 16-bit | | Scale/unit | raw value times `0.1 V` | | Expected normal response | function `03`, byte count `02`, two data bytes | | Likely exception | `02` Illegal Data Address if the offset/range is not implemented | Request PDU: ```text 03 00 09 00 01 03 function code: Read Holding Registers 00 09 starting PDU address: 9 00 01 quantity: 1 register ``` Normal response PDU: ```text 03 02 09 C4 03 function code echoed 02 byte count: 2 09 C4 raw register value: 2500 decimal ``` Engineering value: ```text 2500 * 0.1 V = 250.0 V ``` ## Common Pitfalls - Entering `40010` into a tool that already asks for `Read Holding Registers` and expects a zero-based address. - Entering `10` when the tool expects PDU address `9`. - Removing the `4` prefix but forgetting to subtract one. - Treating `400001` as a literal PDU address. It is documentation notation, not a value that fits in the 16-bit protocol address field. - Treating a wrong-but-plausible value as a byte-order problem before checking the exact requested address. - Changing Unit Identifier, baud rate, parity, TCP port, or scale factor before testing the adjacent address. ## Instructor Flow 1. Start with the simple rule: function code selects the table; address selects the offset. 2. Show why `40010` usually becomes function `03`, address `9`. 3. Contrast three tool modes: - full documentation reference: learner enters `40010`; - one-based table number: learner enters `10`; - zero-based PDU address: learner enters `9`. 4. Make learners record the mode before judging the result. 5. Use the off-by-one lab before introducing byte order, word order, or scaling problems. ## Check-Your-Understanding 1. A vendor table lists input register `30025`, signed 16-bit, scale `0.1 degrees C`. What function code and PDU address should you try first? 2. A client tool has separate fields for function code and address. You select `03 Read Holding Registers`. The manual says `40001`. Should the address field usually be `40001`, `1`, or `0`? 3. You read `40010` and get a plausible but wrong value. What two address-base tests should you run before changing byte order or scaling? 4. Why is `400001` not a literal protocol address? ## Source Notes - Official rule: Modbus Application Protocol Specification V1.1b3 defines function-code-based requests with address fields inside the PDU. - Official rule: Modbus logical data tables and common public function codes are protocol concepts. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for addressing model and zero-based PDU addresses, four primary logical data tables, public function-code categories, read holding registers quantity limit, read input registers quantity limit, normal response vs exception response, and exception codes and exception response PDU shape. - Documentation convention: legacy reference prefixes such as `0xxxx`, `1xxxx`, `3xxxx`, and `4xxxx` are not sent on the wire. - Local traceability: see `sources/source-traceability-matrix.md`, Modules 5 Addressing. - Tool behavior: address-entry modes differ by client, driver, and library. Any named tool example needs tool documentation or verified lab evidence before release. - Field note: JBus-style or vendor-specific addressing conventions may appear in the field. Label them as exceptions or implementation notes. ## Completion Checkpoint Before moving on, learners should convert a documented reference into function code, logical table, first PDU address to try, and quantity. They should also record the client/tool address-entry mode before changing Unit Identifier, serial settings, byte order, or scale. ## Reusable Assets - [Addressing cheat sheet](https://learnmodbus.studioseventeen.io/resource/addressing-cheat-sheet) - [Off-by-one addressing lab](https://learnmodbus.studioseventeen.io/lesson/modbus-addressing?page=lab-1) - [Module 5 quiz](https://learnmodbus.studioseventeen.io/lesson/modbus-addressing?page=quiz) ## Diagram source ```mermaid flowchart LR Doc["Vendor doc:
40001 → 40010"] Doc -- "subtract 40001" --> Wire["PDU wire address:
0 → 9"] Wire -- "FC 03, qty 10" --> Server ``` ## Labs ### Lab 1 # Lab 06: Off-By-One Addressing ## Learner Outcome Learners can prove whether a client tool is using documentation notation, one-based table numbering, or zero-based PDU addressing before changing unrelated settings. ## Prerequisites - Module 2: request/response and PDU basics. - Module 3: data tables. - Module 4: function codes. - Module 5 lesson through the worked `40010` example. ## Safety And Scope This lab uses synthetic data only. Do not point these steps at production equipment. If a real client tool is used later, connect only to an isolated simulator or training device. ## Scenario A manual says the value `Line voltage L1-L2` is at holding register `40010`, unsigned 16-bit, scale `0.1 V`. Your simulator or provided table has: | PDU Address | Raw Value | Intended Meaning | |---:|---:|---| | `9` | `2500` | Correct line voltage: `250.0 V` | | `10` | `0` | Adjacent register used to expose off-by-one mistakes | The learner must determine which tool input returns the correct value and why. ## Protocol Target | Field | Value | |---|---| | Transport | Modbus TCP or paper/saved-byte exercise | | Function code | `03` Read Holding Registers | | Documented register | `40010` | | Correct PDU address | `9` | | Quantity | `1` | | Data type | unsigned 16-bit | | Scale/unit | raw value times `0.1 V` | | Expected normal response | function `03`, byte count `02`, raw value `2500` | | Expected failure mode | wrong-but-valid value from address `10`, or exception `02` if only address `9` is implemented | ## No-Hardware Procedure 1. Write the expected request PDU for the documented value `40010`. 2. Decode the expected response PDU `03 02 09 C4`. 3. Complete the worksheet table below for three possible client inputs. 4. Decide which client mode each input represents. 5. State the next troubleshooting step if all three attempts fail. Worksheet: | Attempt | Client Input | Assumed Tool Mode | PDU Address Sent | Expected Raw Value | Expected Engineering Value | Interpretation | |---:|---|---|---:|---:|---:|---| | 1 | `40010` | Full documentation reference | tool-dependent | tool-dependent | tool-dependent | Needs tool-mode evidence | | 2 | `10` | One-based table item number | usually `9` if tool subtracts one | `2500` | `250.0 V` | Correct only in this tool mode | | 3 | `9` | Zero-based PDU address | `9` | `2500` | `250.0 V` | Correct when tool expects protocol offset | ## Optional Simulator Track The course-owned localhost smoke simulator now verifies the core PDU address `9` fixture: ```text read_request_pdu: 03 00 09 00 01 read_response_pdu: 03 02 09 C4 ``` After `lab-toolchain-bom.md` pins third-party learner tools, convert this paper lab into a tool-specific runnable lab: 1. Configure holding register PDU address `9` to raw `2500`. 2. Configure holding register PDU address `10` to raw `0`. 3. Read the value using each tool input mode the selected client supports. 4. Capture request bytes or tool logs showing the actual PDU address. 5. Save expected output screenshots or logs in the lab folder. ## Expected Observations - If the client sends PDU address `9`, the raw value should be `2500`, which scales to `250.0 V`. - If the client sends PDU address `10`, the learner may see `0.0 V` or another wrong-but-valid value. - If the device does not implement the requested address, the server may return exception `02` Illegal Data Address. - If there is no response at all, do not start with byte order or scaling. First verify transport reachability, server/unit, and function code. ## Troubleshooting Notes - Wrong-but-valid value usually means the request reached a real register. Check address base and table selection first. - Exception `02` means the server rejected the requested address or range. Check PDU address, quantity, and supported range. - Timeout means no valid response came back before the client deadline. Check IP/port, serial settings, Unit Identifier/server address, and gateway path. ## Check Questions 1. Why is `40010` usually PDU address `9`? 2. Which field selects holding registers: the `4` prefix or function code `03`? 3. If address `10` returns a plausible but wrong value, what should you test next? 4. What evidence proves the actual PDU address sent by a client tool? ## Answer Key 1. Traditional documentation is usually one-based, so item 10 maps to zero-based offset 9. 2. Function code `03` selects holding registers. The `4` prefix is documentation notation. 3. Test the adjacent zero-based and one-based interpretations, record tool mode, then confirm quantity and table selection. 4. Request bytes, packet capture, raw client log, simulator log, or a tool display that shows the actual request address. ## Instructor Notes - Require learners to show both documented reference and PDU address before accepting an answer. - Treat `40010`, `10`, and `9` as tool-input hypotheses until request bytes or simulator logs prove the actual PDU address. - If learners change scale or data type first, redirect them to address-base evidence and table/function selection. - Keep third-party client behavior marked pending until the selected tool/version is verified in `lab-toolchain-bom.md`. ## Source Notes - Official source: Modbus Application Protocol Specification V1.1b3 for PDU structure, function codes, address fields, and exception responses. - Local source: `modbus-wiki.md` Addressing and Exception Responses. - Local traceability: `sources/source-traceability-matrix.md`, Modules 5 Addressing. - Tool behavior: course-owned localhost smoke simulator verifies the fixture response; third-party client UI behavior remains pending in `lab-toolchain-bom.md`. ## Knowledge check # Module 5 Quiz: Modbus Addressing ## Questions ### Multiple Choice 1. A manual lists holding register `40001`. A client tool separately asks for function code and zero-based address. What address should you usually enter? - A. `40001` - B. `1` - C. `0` - D. `4` 2. Which part of a Modbus request selects the holding-register table? - A. The leading `4` in `40010` - B. Function code `03` - C. The TCP port - D. The Unit Identifier 3. A vendor table lists input register `30025`. What function code and first PDU address should you try first? - A. Function `03`, address `25` - B. Function `04`, address `24` - C. Function `04`, address `30025` - D. Function `02`, address `24` 4. A read of `40010` returns a plausible but wrong value. Which check should usually come before changing byte order? - A. Try the adjacent address-base interpretation. - B. Change TCP port from `502` to `802`. - C. Reverse every byte in the response. - D. Increase the quantity to the maximum supported value. 5. Why is `400001` not sent as a literal PDU address? - A. Modbus TCP forbids holding registers. - B. The PDU address field is a 16-bit offset and the prefix is documentation notation. - C. Function code `03` can only read one register. - D. It is a Modbus Security-only address. 6. A vendor table lists coil `00017`. What logical table, likely read function code, and first PDU address should you try? - A. Coils, function `01`, PDU address `16`. - B. Coils, function `01`, PDU address `17`. - C. Discrete inputs, function `02`, PDU address `16`. - D. Holding registers, function `03`, PDU address `17`. 7. A vendor table lists discrete input `10008`. What logical table, likely read function code, and first PDU address should you try? - A. Coils, function `01`, PDU address `8`. - B. Discrete inputs, function `02`, PDU address `8`. - C. Discrete inputs, function `02`, PDU address `7`. - D. Input registers, function `04`, PDU address `7`. ### Short Answer 1. Convert `00017` into logical table, likely read function code, and first PDU address to try. 2. Convert `10008` into logical table, likely read function code, and first PDU address to try. 3. Name two pieces of evidence that can prove what address a client actually sent. 4. Explain the difference between a wrong-but-valid value and exception `02` during address troubleshooting. ### Applied Scenario A device manual says: | Name | Register | Access | Type | Scale | Unit | |---|---:|---|---|---:|---| | Line voltage L1-L2 | `40010` | Read | unsigned 16-bit | `0.1` | V | Your client reads a raw value of `0` when you expect about `2500`. Tasks: 1. Write the request PDU you expected the client to send. 2. List two likely address-entry mistakes. 3. List one thing not to change until address mode is verified. ## Answer Key 1. Multiple choice: C. `40001` is usually the first holding-register item, so zero-based PDU address is `0`. 2. Multiple choice: B. Function code `03` selects holding registers; the prefix is documentation notation. 3. Multiple choice: B. `30025` is usually input register item 25, so function `04`, PDU address `24`. 4. Multiple choice: A. Off-by-one mistakes are common and should be tested before byte/word-order changes. 5. Multiple choice: B. `400001` is documentation notation; the protocol address is a 16-bit offset. 6. Multiple choice: A. `00017` is coil item 17; subtract one for the zero-based PDU, so function `01`, PDU address `16`. 7. Multiple choice: C. `10008` is discrete input item 8; subtract one for the zero-based PDU, so function `02`, PDU address `7`. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | C | A sends the documentation reference, B is the one-based item number, and D confuses the prefix with the zero-based PDU address. | | 2 | B | A is documentation notation, C is only the TCP service port, and D is transport or gateway routing context rather than table selection. | | 3 | B | A uses the holding-register function, C sends the documented reference as a PDU address, and D uses the discrete-input function. | | 4 | A | B changes an unrelated port, C changes byte order before proving the address, and D increases range risk instead of testing the address-base hypothesis. | | 5 | B | A falsely excludes holding registers from TCP, C invents a one-register limit, and D treats extended documentation notation as Modbus Security behavior. | | 6 | A | B forgets to subtract one for the zero-based PDU, C reads the coil as a discrete input, and D treats the `0` prefix as a holding register. | | 7 | C | A puts a discrete input in the coil table, B forgets to subtract one for the zero-based PDU, and D reads the discrete input as an input register. | Short answer: 1. `00017`: coil table, function `01` for read, first PDU address `16`. Writes would use function `05` or `15` if the coil is writable. 2. `10008`: discrete input table, function `02`, first PDU address `7`. 3. Valid evidence includes packet capture, raw client log, simulator log, request bytes, or a tool screen that displays the actual PDU address. 4. A wrong-but-valid value means the request may have reached an implemented but unintended register. Exception `02` means the server rejected the requested address or range. Applied scenario: 1. Expected request PDU: `03 00 09 00 01`. 2. Likely mistakes: entering `10` into a zero-based address field, entering `40010` into a field that already selected holding registers, or forgetting to subtract one after removing the `4` prefix. 3. Do not change byte order, scaling, Unit Identifier, serial settings, or TCP port until address mode and requested PDU address are verified. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for addressing model and zero-based PDU addresses, four primary logical data tables, public function-code categories, read coils quantity limit, read discrete inputs quantity limit, read holding registers quantity limit, read input registers quantity limit, normal response vs exception response, exception codes and exception response PDU shape, and IANA service name `mbap` on port `502` where port distractors appear. - Tool address-entry modes are implementation-specific and still need selected tool/version evidence before learner release. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 5/16 · v1.0.0 · Exported for offline / agent use._ # Module 6: Register Maps > Reading a vendor map and turning it into a reliable, reviewed integration plan. **Phase:** Addressing & Data Meaning **Estimated time:** 7 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/register-maps ## What you'll be able to do - Normalize a vendor register map into a reviewable integration plan. - Identify the seven columns every map needs (address, type, scale, unit, R/W, range, notes). - Flag missing evidence before you put a single value on a screen. ## Three things people get wrong 1. **Skipping the 'evidence' column.** For every row, record where the meaning came from: spec page, lab read, vendor email, or assumption. 2. **Treating the map as fully tested.** Until you've round-tripped each row, assume nothing — especially scale and word order. 3. **Putting raw values on a dashboard.** Dashboards lie when the map lies. Get the map reviewed first. ## From the field **The map that needed a footnote on every row** A bright integrator built a clean spreadsheet from a vendor PDF — and shipped it. Half the rows had 'scale: 1' by default because the column was blank in the source. Three weeks later, a 'voltage' reading of 12,460 turned out to be tenths of a volt. The fix was a footnote column, not new code. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — No standard register map — entirely vendor-specific. ## Lesson # Module 6 Lesson: Register Maps ## Learner Outcome By the end of this module, learners can read an OEM register map as evidence rather than a magic list of numbers. They can infer table, function code, documented address, actual PDU address, quantity, permission, data type, scale, unit, validity notes, and unresolved assumptions needed for a reliable integration. ## Key Concepts - A register map is vendor documentation, not the Modbus protocol itself. - Column names such as `Address`, `Register`, `Offset`, `Location`, `Word`, `Parameter`, and `Index` are not standardized. - The word `register` is ambiguous until the table and function code are known. - A professional map preserves both the vendor reference and the actual request fields used by the client. - Reserved ranges, gaps, model-dependent registers, firmware changes, and hidden installer-only items are normal hazards. - Evidence matters: record source row, address-base assumption, request bytes, response bytes, decoded value, and unresolved assumptions. ## Key Terms - Register map: the source document or table that gives Modbus points meaning. - Normalized row: a course/internal row that turns source-map wording into poll-ready fields and assumptions. - Source label: the evidence category for a row, such as official rule, vendor-specific note, synthetic fixture, or needs verification. - Access: whether the point is read-only, writable, reserved, or constrained. - Validity condition: the state, mode, or context required for a value to be meaningful. - Unresolved assumption: a map interpretation that must be tested or reviewed before release. ## Source-Grounded Explanation Modbus defines logical tables, function codes, address fields, quantities, and response shapes. It does not define the meaning of a vendor's row named `Frequency`, `Status`, `Offset`, or `Register`. That split is the heart of register-map work: | Layer | Governs | Example | |---|---|---| | Official protocol | Function code, PDU address, quantity, response structure, exception behavior. | Function `04`, PDU address `20`, quantity `1`, normal response `04 02 17 70`. | | Vendor-specific documentation | Meaning, type, scale, unit, permissions, validity, word order, and safety context. | `30021`, `U16`, `/100`, `Hz`, valid when grid present. | | Tool behavior | Address-entry mode, byte/word-order labels, logs, export format. | Tool expects `20`, `21`, or `30021` depending on configuration. | | Field evidence | What actually worked in a controlled test. | Captured request, response, decoded value, and comparison to known display. | Learners should normalize every useful row into a poll-ready shape before configuring a client. The clean row should answer: | Question | Why It Matters | |---|---| | Which logical table? | Determines likely read/write function code. | | Which function code? | Prevents mixing holding registers and input registers. | | Which documented address? | Preserves the vendor evidence. | | Which actual PDU address? | Prevents off-by-one errors. | | What quantity? | Multi-register values must read the correct number of registers. | | What type, scale, and unit? | Converts raw words into useful values. | | What permission and safety context? | Avoids unsafe writes and rejected requests. | | What validity context? | Prevents displaying stale, sentinel, or state-dependent data as real telemetry. | ## Practical Example Synthetic source row: | Parameter | Register | Access | Format | Multiplier | Unit | Notes | |---|---:|---|---|---:|---|---| | AC frequency | `30021` | R | `U16` | `/100` | Hz | Input register table | Normalized row: | Field | Value | |---|---| | Transport | Modbus TCP for the no-hardware example; PDU fields also apply to RTU | | Logical table | Input registers | | Function code | `04` Read Input Registers | | Documented address | `30021` | | Actual PDU address | `20` | | Quantity | `1` register | | Data type | unsigned 16-bit | | Scale/unit | raw `/100 Hz` | | Expected normal response | function `04`, byte count `02`, data bytes `17 70` | | Decoded value | `0x1770 = 6000`; `6000 / 100 = 60.00 Hz` | | Likely failure or exception | exception `02` if address/range unavailable; wrong table if function `03` is used | | Source label | Synthetic vendor note plus official protocol request fields | Request PDU: ```text 04 00 14 00 01 04 function code: Read Input Registers 00 14 starting PDU address: 20 00 01 quantity: 1 register ``` Normal response PDU: ```text 04 02 17 70 04 function code echoed 02 byte count: 2 17 70 raw register value: 6000 decimal ``` ## Common Pitfalls - Treating every row called `Register` as a holding register. - Assuming read-only measurements must use function code `04`; many devices expose read-only values through holding registers and function `03`. - Reading across reserved gaps because one large poll is convenient. - Losing the documented address after converting to PDU address. - Recording type and scale but omitting unit and validity context. - Copying write-capable rows into a tool without reviewing safety state, permissions, interlocks, and rollback. - Treating a synthetic or vendor-specific map convention as a universal Modbus rule. ## Instructor Flow 1. Start with the split between official protocol and vendor meaning. 2. Give learners the messy synthetic course map first. 3. Have them normalize one easy row, one input-register row, one 32-bit row, one bitfield, and one ambiguous offset row. 4. Force source labels: official rule, synthetic vendor note, tool behavior, field note, or needs verification. 5. End by comparing normalized rows to the register-map review checklist. ## Check-Your-Understanding 1. A map heading says `Holding Registers`, but the row access is read-only. Which function code is the first one to try, and why? 2. A map lists `Offset 60` with no base convention. What should you record before testing it? 3. Why should a normalized map preserve both documented address and actual PDU address? 4. A contiguous read fails across a reserved range, but smaller reads succeed. What should the polling plan do next? ## Source Notes - Official rule: Modbus Application Protocol Specification V1.1b3 defines logical data tables, function codes, address fields, quantity fields, response shapes, and exception behavior. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, normal response vs exception response, and exception codes and exception response PDU shape. - Vendor-specific note: register meanings, data type conventions, word order, scale, unit, permission, and validity context come from vendor documentation or verified behavior. - Synthetic source: `release/synthetic-course-device-map.md` provides course-authored examples for no-hardware lessons. - Local traceability: see `sources/source-traceability-matrix.md`, Modules 6 Register Maps. ## Completion Checkpoint Before moving on, learners should normalize at least one weak register-map row and mark missing table, address base, data type, scale, access, or source evidence as `needs verification` instead of guessing. ## Reusable Assets - [Synthetic course device map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) - [Register-map review checklist](https://learnmodbus.studioseventeen.io/resource/register-map-review-checklist) - [Device survey template](https://learnmodbus.studioseventeen.io/resource/device-survey-template) - [Register-map normalization lab](https://learnmodbus.studioseventeen.io/lesson/register-maps?page=lab-1) - [Module 6 quiz](https://learnmodbus.studioseventeen.io/lesson/register-maps?page=quiz) ## Labs ### Lab 1 # Lab 22: Register Map Normalization ## Learner Outcome Learners can convert a messy OEM-style register map excerpt into a clean integration table that records function code, documented address, PDU address, quantity, type, scale, unit, access, validity context, evidence, and unresolved assumptions. ## Prerequisites - Module 3: data tables. - Module 4: function codes. - Module 5: addressing. - Module 6 lesson through the AC frequency worked example. ## Safety And Scope This lab uses [Synthetic Course Device Map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map). It is not a real vendor map and should not be used to configure production equipment. Write rows are discussion-only unless a simulator later implements them. Do not perform writes against real devices during this lab. ## Scenario You receive an OEM-style table for a course energy meter simulator. The table mixes `40001` notation, `30021` notation, a reserved gap, one 32-bit value, one status word, and one ambiguous `Offset 60` row. Your job is to create a normalized map that another integrator could use without guessing. ## Protocol Target The required worked row is `AC frequency`: | Field | Value | |---|---| | Transport | Modbus TCP paper exercise; PDU fields also apply to RTU | | Function code | `04` Read Input Registers | | Documented address | `30021` | | Actual PDU address | `20` | | Quantity | `1` register | | Data type | unsigned 16-bit | | Scale/unit | raw `/100 Hz` | | Expected normal response | `04 02 17 70`, raw `6000`, decoded `60.00 Hz` | | Likely failure mode | exception `02` if address/range is unavailable; wrong table if function `03` is used | ## Procedure 1. Open `release/synthetic-course-device-map.md`. 2. Copy the OEM-style source excerpt into your notes. 3. For each row, infer the logical table, likely function code, documented address, PDU address, quantity, data type, scale/unit, access, and validity context. 4. Mark each row's source label as `Official rule`, `Synthetic vendor note`, `Tool behavior`, `Field note`, or `Needs verification`. 5. Do not normalize reserved ranges into active polling rows. 6. Mark the ambiguous `Offset 60` row as needing verification rather than pretending the base is known. 7. Compare your normalized rows with the answer key. ## Worksheet | Tag | Function | Documented Address | PDU Address | Qty | Type | Scale/Unit | Access | Validity | Evidence | Source Label | Unresolved Assumptions | |---|---:|---|---:|---:|---|---|---|---|---|---|---| | `device_status_word` | | | | | | | | | | | | | `line_voltage_l1_l2` | | | | | | | | | | | | | `ac_frequency` | | | | | | | | | | | | | `total_energy_import` | | | | | | | | | | | | | `command_word` | | | | | | | | | | | | | `temperature` | | | | | | | | | | | | ## Expected Normalization Highlights - `40001` usually maps to holding-register PDU address `0`, function `03`, quantity `1`. - `40010` usually maps to holding-register PDU address `9`, function `03`, quantity `1`, unsigned 16-bit, `/10 V`. - `30021` usually maps to input-register PDU address `20`, function `04`, quantity `1`, unsigned 16-bit, `/100 Hz`. - `40031` is a two-register value starting at PDU address `30`, function `03`, quantity `2`, unsigned 32-bit, high word first. - `40101` is writable only in the simulator context and should carry write-safety notes. - `Offset 60` is unresolved until the manual or test evidence proves whether it is zero-based or one-based and which table/function applies. ## Expected Observations - Learners who preserve both documented address and PDU address can explain their request. - Learners who mark `Offset 60` as unresolved have done the safer professional thing. - Learners who poll across `40050-40059` should identify the reserved gap before blaming the device. - Learners should separate official protocol fields from synthetic map meanings. ## Troubleshooting Notes - Wrong table: function `03` and function `04` can both read 16-bit registers, but they address different logical tables. - Wrong address base: a one-off request can return a wrong-but-valid adjacent value. - Reserved gap: a large contiguous read may fail even if smaller reads around the gap succeed. - Unsafe write: the `command_word` row is simulator-only until a write-safety workflow is reviewed. ## Answer Key | Tag | Function | Documented Address | PDU Address | Qty | Type | Scale/Unit | Access | Validity | Evidence | Source Label | Unresolved Assumptions | |---|---:|---|---:|---:|---|---|---|---|---|---|---| | `device_status_word` | `03` | `40001` | `0` | `1` | unsigned 16-bit bitfield | none | R | bit definitions are synthetic | synthetic map row | Synthetic vendor note plus official protocol fields | none for paper lab | | `line_voltage_l1_l2` | `03` | `40010` | `9` | `1` | unsigned 16-bit | `/10 V` | R | valid when grid present | synthetic map row and response `03 02 09 C4` | Synthetic vendor note plus official protocol fields | simulator output pending | | `ac_frequency` | `04` | `30021` | `20` | `1` | unsigned 16-bit | `/100 Hz` | R | input register table | synthetic map row and response `04 02 17 70` | Synthetic vendor note plus official protocol fields | simulator output pending | | `total_energy_import` | `03` | `40031` | `30` | `2` | unsigned 32-bit high word first | `Wh` | R | high-word-first stated in synthetic map | synthetic map row and response example | Synthetic vendor note plus official protocol fields | simulator output pending | | `command_word` | `06` or `16` in simulator only | `40101` | `100` | `1` | unsigned 16-bit bitfield | none | RW | simulated only; preserve reserved bits | synthetic map row | Synthetic write-safety note | write workflow not runnable yet | | `temperature` | Needs verification | `Offset 60` | Needs verification | `1` | signed 16-bit | `/10 deg C` | R | unclear offset base | synthetic map row only | Needs verification | table/function and address base unresolved | ## Check Questions 1. Why is `ac_frequency` read with function `04` rather than `03`? 2. Why should `Offset 60` remain marked `Needs verification`? 3. Why is reading `40050-40059` as part of one large contiguous poll a bad first plan? 4. What evidence would move this lab from paper exercise to runnable no-hardware lab? ## Instructor Notes - Do not reward learners for filling every cell with certainty. Correctly marking ambiguity is part of the skill. - Ask learners to explain whether each claim is protocol behavior, synthetic map behavior, or tool behavior. - Use this lab as the bridge into Module 7 data types and Module 14 troubleshooting. ## Source Notes - Official source: Modbus Application Protocol Specification V1.1b3 for function codes, PDU address fields, quantities, and response shapes. - Synthetic source: `release/synthetic-course-device-map.md` for map meanings and example values. - Local source: `release/register-map-review-checklist.md` for row fields and review prompts. ## Knowledge check # Module 6 Quiz: Register Maps ## Questions ### Multiple Choice 1. A vendor row is labeled `Register 40010`. Which statement is safest? - A. The client sends `40010` as the PDU address. - B. The row is probably a holding-register reference, but the actual PDU address and tool mode must be confirmed. - C. The row must be read with function `04`. - D. The row is writable because it starts with `4`. 2. A map heading says `Input Registers` and a row lists `30021`, `U16`, `/100 Hz`. What is the first request to try? - A. Function `04`, PDU address `20`, quantity `1`. - B. Function `03`, PDU address `30021`, quantity `1`. - C. Function `04`, PDU address `30021`, quantity `100`. - D. Function `06`, PDU address `20`, quantity `1`. 3. Which field is vendor-specific rather than a Modbus wire-protocol field? - A. Function code. - B. PDU address. - C. Unit scale `/10 V`. - D. Quantity. 4. A row says `Offset 60` but does not identify table or address base. What should the normalized map say? - A. Holding register, PDU address `59`. - B. Input register, PDU address `60`. - C. Needs verification. - D. Broadcast address. 5. Why should reserved gaps be handled carefully? - A. The Modbus protocol requires all reserved gaps to be writable. - B. A contiguous read across unsupported addresses may fail even if smaller reads succeed. - C. Reserved gaps always contain zero. - D. Reserved gaps are always coils. 6. A map row reads `Total energy import`, `40031`, `U32`, high word first. What normalized function code, first PDU address, and quantity should you record? - A. Function `04`, PDU address `31`, quantity `1`. - B. Function `03`, PDU address `30`, quantity `2`. - C. Function `03`, PDU address `40031`, quantity `2`. - D. Function `03`, PDU address `31`, quantity `1`. 7. A map heading says `Holding Registers`, but a row's access is read-only. Which read function code should you try first, and why? - A. Function `04`, because read-only values always live in input registers. - B. Function `03`, because a vendor can expose read-only measurements in holding-register space. - C. Function `02`, because read-only implies a discrete input. - D. Function `06`, because read-only rows still need a write to refresh. ### Short Answer 1. List four fields that a normalized register-map row should preserve. 2. Explain why a read-only value may still appear in holding registers and use function `03`. 3. What evidence would you record to prove the actual PDU address used by a client? 4. Why is a vendor manual authoritative only for its named product/version/configuration? ### Applied Scenario Synthetic source row: | Parameter | Register | Access | Format | Multiplier | Unit | Notes | |---|---:|---|---|---:|---|---| | Total energy import | `40031` | R | `U32` | `1` | Wh | High word first | Tasks: 1. Fill the normalized fields: function code, documented address, PDU address, quantity, type, scale/unit, access, and word order. 2. Name one likely failure or wrong-value mode. 3. State whether the word-order claim is official protocol behavior or synthetic vendor-note behavior. ## Answer Key 1. Multiple choice: B. `40010` is documentation notation; the function code and PDU address must be inferred and tested. 2. Multiple choice: A. `30021` usually means input-register item 21, so function `04`, PDU address `20`, quantity `1`. 3. Multiple choice: C. Scale and unit come from vendor documentation or synthetic teaching data, not the Modbus frame. 4. Multiple choice: C. Without table and address-base evidence, the row should remain unresolved. 5. Multiple choice: B. Unsupported gaps can produce exception `02` or force smaller polling groups. 6. Multiple choice: B. `40031` is holding-register item 31, so function `03`, PDU address `30`; a `U32` value spans two registers, so quantity `2`. 7. Multiple choice: B. Modbus allows holding registers to be read with function `03`; a vendor can expose read-only measurements in holding-register space even when writes are not permitted. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A sends documentation notation as an offset, C picks the input-register function without evidence, and D assumes write access from a prefix. | | 2 | A | B uses the holding-register function and sends the documented number, C sends the documented number and invents quantity `100`, and D is a write function. | | 3 | C | A/B/D are Modbus request or response fields, while scale and unit come from a source map or teaching fixture. | | 4 | C | A/B invent table and address-base assumptions, and D confuses an unresolved register-map offset with the serial broadcast address. | | 5 | B | A invents a write rule, C invents data content, and D changes reserved register gaps into coil items without evidence. | | 6 | B | A picks the input-register function and forgets to subtract one, C sends the documented number as a PDU address, and D forgets that a `U32` value needs two registers. | | 7 | B | A assumes read-only values must be input registers, C confuses read-only with the discrete-input table, and D uses a write function code to read a value. | Short answer: 1. Good answers include documented address, PDU address, function code, quantity, data type, scale/unit, access, validity notes, source evidence, and unresolved assumptions. 2. Modbus allows holding registers to be read with function `03`; a vendor can expose read-only measurements in holding-register space even if writes are not permitted. 3. Request bytes, packet capture, raw client log, simulator log, or a tool display showing function code and PDU address. 4. The manual describes that product's implementation choices; data meanings, scale, word order, permissions, and quirks are not universal Modbus rules. Applied scenario: 1. Function `03`; documented address `40031`; PDU address `30`; quantity `2`; unsigned 32-bit; scale/unit `1 Wh`; access read-only; high word first. 2. Wrong word order can produce an implausible energy value; a contiguous read across a reserved gap can produce exception `02`; address-base error can return an adjacent value. 3. Word order is synthetic vendor-note behavior in this course map, not an official Modbus protocol rule. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, read holding/input register quantity limits, exception codes and exception response PDU shape, and multi-byte numeric encoding in protocol fields. - Register meanings, word order, scale, access, and vendor row labels remain vendor-specific or synthetic-map behavior. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 6/16 · v1.0.0 · Exported for offline / agent use._ # Module 7: Data Types > INT16, UINT16, INT32, FLOAT, word/byte order, and the encoding traps you'll hit. **Phase:** Addressing & Data Meaning **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/data-types ## What you'll be able to do - Decode INT16, UINT16, INT32, UINT32, and IEEE-754 floats from raw registers. - Identify ABCD / CDAB / BADC / DCBA word-order patterns from a capture. - Explain why a 'valid Modbus response' can still produce the wrong number. ## Three things people get wrong 1. **Reading a 32-bit value as one register.** 32-bit values span two consecutive registers — request quantity 2, then assemble. 2. **Assuming little-endian like a CPU.** Modbus registers are big-endian (high byte first). Word order across the two registers is vendor-specific. 3. **Trusting tool labels like 'swap'.** Different tools use 'swap' to mean different things. Verify with a register whose expected value is known. ## From the field **The float that crashed an alarm system** A new gateway changed default word order from ABCD to CDAB during a firmware update. Suddenly tank levels read as denormal numbers near zero — and the low-level alarm fired continuously. Rolling back the firmware was faster than rewriting the alarm logic, but the post-mortem demanded an explicit word-order column on every row. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — Endianness — section 4.2 - [IEEE 754 single precision](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) ## Lesson # Module 7 Lesson: Data Types And Word Order ## Learner Outcome By the end of this module, learners can explain what Modbus actually transports for data, then decode common vendor-defined representations: unsigned and signed integers, fixed-point values, IEEE-754 floats, packed bits, enums, BCD-style values, strings, and multi-register values. They can state signedness, width, byte order, word order, scale, and source evidence instead of hiding those assumptions. ## Key Concepts - Modbus register data is transported as 16-bit register values. The frame does not say whether a register is signed, unsigned, scaled, a bitfield, an enum, a string fragment, or part of a larger value. - Multi-register values are vendor or profile conventions layered on top of Modbus. A 32-bit value usually uses two consecutive registers; a 64-bit value usually uses four. - Signedness is an interpretation choice unless the map says otherwise. The same raw word can decode differently as unsigned 16-bit and signed two's-complement. - Byte order inside each transmitted 16-bit register value is protocol-defined in the response data. Word order across multiple registers is not universally defined by Modbus. - A correct Modbus transaction can still produce a wrong engineering value if the client applies the wrong data type, signedness, scale, word order, or unit. ## Key Terms - Signedness: whether a numeric value can represent negative numbers. - Width: how many bits or registers the value uses. - 32-bit value: a value spread across two 16-bit Modbus registers. - Float: a floating-point value whose register order still depends on the source map or tool convention. - Byte order: the order of bytes inside a field or register grouping. - Word order: the order of 16-bit registers that make up a larger value. - Known-value test: a comparison against a value whose real meaning is already known. ## Source-Grounded Explanation At the protocol layer, a read response gives a function code, a byte count, and data bytes. The protocol can tell the client how many bytes arrived. It does not tell the client that `FF CE` means `-50`, that `00 01 86 A0` means `100000 Wh`, or that `41 48 00 00` means an IEEE-754 float value of `12.5`. The interpretation comes from a register map, a device profile, a tool configuration, or verified field evidence. ### 16-Bit Signedness | Raw hex | Unsigned 16-bit | Signed 16-bit two's-complement | |---:|---:|---:| | `0000` | `0` | `0` | | `0001` | `1` | `1` | | `7FFF` | `32767` | `32767` | | `8000` | `32768` | `-32768` | | `FFCE` | `65486` | `-50` | | `FFFF` | `65535` | `-1` | Field rule: decode the correct width first. A signed 32-bit value split across two registers is not the same thing as two independent signed 16-bit values. ### Multi-Register Order Use a neutral byte label when teaching multi-register values. If the intended 32-bit byte sequence is `A B C D`, common layouts are: | Label | Register 1 | Register 2 | Description | |---|---|---|---| | `ABCD` | `A B` | `C D` | high word first, high byte first inside each word | | `CDAB` | `C D` | `A B` | low word first, high byte first inside each word | | `BADC` | `B A` | `D C` | high word first, bytes swapped inside each word | | `DCBA` | `D C` | `B A` | low word first, bytes swapped inside each word | Source boundary: the official Modbus protocol defines the register data bytes in a response, but it does not assign a universal meaning to `ABCD`, `CDAB`, `BADC`, or `DCBA` for every 32-bit vendor value. Tool labels such as big-endian, little-endian, byte swap, and word swap must be checked against the specific tool and version. ## Practical Example ### Example 1: Unsigned 32-Bit Counter Synthetic source row: | Field | Value | |---|---| | Parameter | Total energy import | | Documented address | `40031` | | Actual PDU address | `30` | | Function code | `03` Read Holding Registers | | Quantity | `2` registers | | Type | unsigned 32-bit integer | | Word order | high word first (`ABCD`) | | Scale/unit | raw `Wh` | | Expected normal response | `03 04 00 01 86 A0` | Decode: ```text Data bytes: 00 01 86 A0 ABCD unsigned 32-bit: 0x000186A0 = 100000 Wh CDAB unsigned 32-bit: 0x86A00001 = 2258632705 Wh ``` The first value fits a small teaching meter. The second is a possible number mathematically, but it is not plausible for this scenario unless other evidence supports it. Do not choose the order by plausibility alone; record the source row and any known-value comparison. ### Example 2: IEEE-754 Float Fixture The Module 7 decoder fixture uses a known float value: | Field | Value | |---|---| | Parameter | Lab float reference | | Function code | `03` Read Holding Registers | | Documented address | `40071` | | Actual PDU address | `70` | | Quantity | `2` registers | | Intended type | IEEE-754 32-bit float | | Intended order | high word first (`ABCD`) | | Data bytes | `41 48 00 00` | | Expected decoded value | `12.5` | Normal response PDU: ```text 03 04 41 48 00 00 03 function code echoed 04 byte count: 4 41 48 00 00 two registers interpreted as IEEE-754 float, ABCD order ``` Common wrong-order tests: | Assumption | Byte sequence used for decode | Result to record | |---|---|---| | Float, `ABCD` | `41 48 00 00` | `12.5` | | Float, `CDAB` | `00 00 41 48` | tiny nonphysical value | | Float, `BADC` | `48 41 00 00` | very large value | | Float, `DCBA` | `00 00 48 41` | tiny nonphysical value | Those wrong values do not prove the device is broken. They prove the Modbus transaction and the data interpretation are separate problems. ## Common Pitfalls - Assuming a tool's positive decimal display means the underlying value is unsigned. - Applying scale before deciding signedness and width. - Treating a 32-bit or 64-bit value as independent 16-bit registers. - Trying byte and word orders until a number looks reasonable, then failing to document the evidence. - Reading the right address with the wrong function code and diagnosing the result as a data-type issue. - Ignoring BCD, string padding, enum tables, local-time assumptions, and sentinel values because the first few values were plain integers. - Treating tool UI wording as an official Modbus term. ## Instructor Flow 1. Start with one raw 16-bit word and ask learners to decode it unsigned, signed, bitfield, and enum. 2. Move to two-register values and label the bytes `A B C D`. 3. Decode one known unsigned 32-bit counter and one known IEEE-754 float using multiple order assumptions. 4. Ask learners to separate protocol fields from synthetic map meanings and tool behavior. 5. End with the rule: correct communication is necessary, but it is not sufficient for correct data. ## Check-Your-Understanding 1. A register returns `FF CE`. What are the unsigned and signed 16-bit interpretations? 2. A float value looks impossible, but the function code, PDU address, quantity, and byte count are correct. What assumptions should you test before changing the address? 3. Why does a Modbus response not tell you whether `0003` means number `3`, enum state `Running`, active bit flags, or part of a string? 4. A device map says `U32, high word first`. Is the word-order claim official protocol behavior or vendor-specific behavior? ## Source Notes - Official rule: Modbus Application Protocol Specification V1.1b3 defines logical tables, function codes, address fields, quantity fields, response shapes, byte counts, and register data in protocol messages. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for multi-byte numeric encoding in protocol fields, four primary logical data tables, addressing model and zero-based PDU addresses, read holding/input register quantity limits, and normal response vs exception response. - Vendor-specific note: signedness, width beyond 16 bits, IEEE-754 use, strings, BCD, enums, scale, units, validity, and word order come from vendor documentation, device profiles, synthetic course data, or verified behavior. - Synthetic source: `release/synthetic-course-device-map.md` provides the current no-hardware fixtures. - Tool source: tool-specific byte/word-order labels still need versioned verification before release. ## Completion Checkpoint Before moving on, learners should decode the same two-register value more than one way, identify which interpretations are plausible, and explain what map, known-value, or tool evidence is still needed before calling one interpretation correct. ## Reusable Assets - [Synthetic course device map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) - [Data type and byte-order worksheet](https://learnmodbus.studioseventeen.io/resource/data-type-byte-order-worksheet) - [Word-order decoding lab](https://learnmodbus.studioseventeen.io/lesson/data-types?page=lab-1) - [Module 7 quiz](https://learnmodbus.studioseventeen.io/lesson/data-types?page=quiz) - [Normalized register map template](https://learnmodbus.studioseventeen.io/resource/normalized-register-map-template) ## Diagram source ```mermaid flowchart LR R1["Reg N: 0x4248"] R2["Reg N+1: 0x0000"] R1 --> AB["ABCD
(big-endian)"] R2 --> AB R1 --> CD["CDAB
(word-swapped)"] R2 --> CD AB --> V1["50.0 °C"] CD --> V2["1.847e-41"] ``` ## Labs ### Lab 1 # Lab 7: Word Order And Data Type Decoding ## Learner Outcome Learners can decode the same Modbus register bytes under several type and order assumptions, identify the interpretation supported by the source evidence, and explain why a valid Modbus response can still produce a wrong value. ## Prerequisites - Module 3: data tables and 16-bit registers. - Module 4: read function response shape. - Module 5: documented address versus PDU address. - Module 6: normalized register-map rows. - Module 7 lesson through multi-register order. ## Safety And Scope This lab uses [Synthetic Course Device Map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) and [Data Type And Byte-Order Worksheet](https://learnmodbus.studioseventeen.io/resource/data-type-byte-order-worksheet). It is a paper or spreadsheet exercise until the simulator fixture is implemented. Do not use the worksheet results to configure production equipment. Real devices require their own manual, known-value test, and tool-version verification. ## Scenario Your client successfully reads two holding registers, but the displayed value is obviously wrong. The request fields match the source row: function code, PDU address, and quantity. The response also has the expected function code and byte count. The likely problem is data interpretation. Your job is to decode the bytes several ways, record the assumptions, and decide which interpretation is supported by the synthetic source evidence. ## Protocol Target Fixture A: unsigned 32-bit counter from the synthetic course map. | Field | Value | |---|---| | Function code | `03` Read Holding Registers | | Documented address | `40031` | | Actual PDU address | `30` | | Quantity | `2` registers | | Type from source | unsigned 32-bit | | Word order from source | high word first (`ABCD`) | | Normal response | `03 04 00 01 86 A0` | | Expected decoded value | `100000 Wh` | Fixture B: IEEE-754 float reference for Module 7. | Field | Value | |---|---| | Function code | `03` Read Holding Registers | | Documented address | `40071` | | Actual PDU address | `70` | | Quantity | `2` registers | | Type from source | IEEE-754 32-bit float | | Word order from source | high word first (`ABCD`) | | Normal response | `03 04 41 48 00 00` | | Expected decoded value | `12.5` | ## Procedure 1. Copy the two normal response PDUs into the worksheet. 2. Confirm that the request used function `03`, the correct PDU address, and quantity `2`, then confirm that the response echoed function `03` with byte count `04`. 3. Strip the function code and byte count so only data bytes remain. 4. Decode Fixture A as unsigned 32-bit `ABCD`, unsigned 32-bit `CDAB`, signed 32-bit `ABCD`, and IEEE-754 float `ABCD`. 5. Decode Fixture B as IEEE-754 float `ABCD`, `CDAB`, `BADC`, and `DCBA`. 6. For each decode, record whether the assumption came from an official protocol field, synthetic vendor note, tool behavior, or a test hypothesis. 7. Choose the interpretation supported by the source row and explain why the other results are wrong for the scenario. 8. Fill the Data Meaning Ledger in the worksheet for the supported interpretation. 9. List the evidence still needed before calling this runnable in a real Modbus client. ## Auto-Graded Checks ```lab type: decode prompt: Decode Fixture A's data bytes as U32 with high word first (ABCD). bytes: 00 01 86 A0 as: u32 order: ABCD unit: Wh hint: Concatenate the bytes in ABCD order, then read as unsigned 32-bit big-endian. explain: 0x000186A0 = 100000. toolLink: /tools?tab=decoder&hex=000186A0 ``` ```lab type: decode prompt: Decode Fixture B's data bytes as IEEE-754 float with high word first (ABCD). bytes: 41 48 00 00 as: f32 order: ABCD hint: 0x41480000 in IEEE-754 single precision. explain: 0x41480000 = 12.5. toolLink: /tools?tab=decoder&hex=41480000 ``` ```lab type: decode prompt: Now decode the same Fixture B bytes with the wrong word order (CDAB). What value would a misconfigured client display? bytes: 41 48 00 00 as: f32 order: CDAB hint: Swap the two 16-bit words before reading as float. explain: Bytes become 00 00 41 48 → an extremely small denormal float — a classic sign of inverted word order. ``` ## Worksheet | Fixture | Data Bytes | Decode Assumption | Decoded Value | Source Label | Plausible For Scenario? | Evidence Or Note | |---|---|---|---:|---|---|---| | A | `00 01 86 A0` | U32 `ABCD` | | | | | | A | `00 01 86 A0` | U32 `CDAB` | | | | | | A | `00 01 86 A0` | S32 `ABCD` | | | | | | A | `00 01 86 A0` | float `ABCD` | | | | | | B | `41 48 00 00` | float `ABCD` | | | | | | B | `41 48 00 00` | float `CDAB` | | | | | | B | `41 48 00 00` | float `BADC` | | | | | | B | `41 48 00 00` | float `DCBA` | | | | | ## Expected Results | Fixture | Decode Assumption | Expected Result | Interpretation | |---|---|---:|---| | A | U32 `ABCD` | `100000 Wh` | Correct for the synthetic source row. | | A | U32 `CDAB` | `2258632705 Wh` | Wrong word order for the source row. | | A | S32 `ABCD` | `100000 Wh` | Same numeric result here because the high bit is not set; still the wrong type label for the row. | | A | float `ABCD` | tiny nonphysical value | Wrong data type for the row. | | B | float `ABCD` | `12.5` | Correct for the Module 7 fixture. | | B | float `CDAB` | tiny nonphysical value | Wrong word order for the fixture. | | B | float `BADC` | very large value | Byte-swapped interpretation, not supported by the fixture. | | B | float `DCBA` | tiny nonphysical value | Wrong byte and word order for the fixture. | ## Expected Observations - A successful Modbus response proves the server returned bytes. It does not prove the client decoded the bytes correctly. - `ABCD` and `CDAB` are teaching labels for byte sequence assumptions, not universal protocol settings. - Fixture A shows why signedness can be invisible when the high bit is not set. - Fixture B shows why float-order mistakes often look like impossible process values rather than communication failures. - The Data Meaning Ledger should preserve the source row, raw bytes, decode settings, and unresolved uncertainty for later troubleshooting. ## Troubleshooting Notes - If a value is wrong but the byte count and response shape are correct, check address, table, type, signedness, word order, scale, and unit as separate hypotheses. - Do not change several assumptions at once. Record one decode attempt per row. - Do not trust a tool's "little-endian" or "swapped" label until you know exactly how that tool applies it to Modbus registers. ## Check Questions 1. Which fixture proves communication success but data interpretation failure? 2. Why is U32 `ABCD` and S32 `ABCD` the same numeric result for Fixture A? 3. What evidence supports float `ABCD` for Fixture B? 4. What tool or simulator evidence is still needed before this lab becomes runnable rather than paper-based? ## Instructor Notes - Keep the first pass calculator-free if possible: learners should label bytes and words before entering values in any tool. - Reward evidence labels. The correct answer is not only the number; it is the source-backed assumption behind the number. - If a learner changes the address to fix a float-order symptom, pause and return to the normalized row. ## Source Notes - Official source: Modbus Application Protocol Specification V1.1b3 for read response structure, byte count, and register data fields. - Synthetic source: `release/synthetic-course-device-map.md` for fixture meanings and expected values. - Course-owned helper evidence: `python3 tools/modbus_fixture_helper.py decode-fixtures` verifies the Lab 7 decode values without opening serial, TCP, or device connections. - Tool source: selected client and decoder tools still need versioned verification before release. ## Knowledge check # Module 7 Quiz: Data Types And Word Order ## Questions ### Multiple Choice 1. A Modbus response contains data bytes `FF CE` for one register. Which statement is safest? - A. The value is always `65486`. - B. The value is always `-50`. - C. The bytes can be interpreted different ways depending on the source map. - D. The device sent an exception response. 2. A two-register value is documented as `U32, high word first` and returns `00 01 86 A0`. What is the expected unsigned value? - A. `100000`. - B. `2258632705`. - C. `-100000`. - D. `12.5`. 3. Which item is not carried as a universal meaning in the Modbus frame? - A. Function code. - B. Byte count in a read response. - C. Starting PDU address in a read request. - D. IEEE-754 float interpretation. 4. A known IEEE-754 float fixture returns `41 48 00 00`. The map says high word first. What should the client decode first? - A. Float `ABCD`. - B. Float `CDAB`. - C. Coil status. - D. Function code `06`. 5. A value looks wildly wrong, but the request function code, PDU address, and quantity match the source row, and the response function code and byte count are consistent. What is the best next move? - A. Change the address and the scale at the same time. - B. Assume the server is offline. - C. Test data type, signedness, word order, scale, and unit as separate hypotheses. - D. Treat the vendor word-order note as an official Modbus rule. 6. A single register returns data bytes `FF CE`. The source map says the value is signed 16-bit. What is the decoded value? - A. `-50`. - B. `65486`. - C. `-178`. - D. `50`. 7. The same register value `FF CE` is instead documented as unsigned 16-bit. What is the decoded value? - A. `-50`. - B. `65486`. - C. `65535`. - D. `206`. ### Short Answer 1. Decode `FF CE` as unsigned 16-bit and signed 16-bit. 2. Why is word order a vendor or profile convention rather than a universal Modbus rule? 3. List three source-map fields needed before a raw two-register value can be treated as engineering data. 4. Explain why a correct byte count does not prove a correct float value. ### Applied Scenario A synthetic course device row says: | Field | Value | |---|---| | Function code | `03` | | Documented address | `40071` | | PDU address | `70` | | Quantity | `2` | | Type | IEEE-754 32-bit float | | Word order | high word first (`ABCD`) | | Response PDU | `03 04 41 48 00 00` | Tasks: 1. Identify the data bytes. 2. State the first decode assumption to try. 3. State the expected value. 4. Name two wrong assumptions that could still occur after a successful read. ## Answer Key 1. Multiple choice: C. The raw bytes need a source-map interpretation. A and B are both possible interpretations, but neither is universal without the map. D is wrong because `FF CE` is data bytes, not an exception-response shape. 2. Multiple choice: A. `0x000186A0` is `100000` decimal. B is the low-word-first interpretation, C invents a negative sign, and D is the separate float fixture value. 3. Multiple choice: D. IEEE-754 interpretation is layered on top of Modbus by a map, profile, tool, or verified behavior. Function code, response byte count, and request PDU address are protocol fields. 4. Multiple choice: A. The fixture states high word first, so decode bytes as `41 48 00 00`. The other order choices are test hypotheses only if the source row or known-value comparison contradicts the first decode. 5. Multiple choice: C. Keep the communication and interpretation hypotheses separate. Changing several assumptions at once destroys evidence, and vendor word order is not an official Modbus rule. 6. Multiple choice: A. `0xFFCE` as signed 16-bit two's-complement is `65486 - 65536 = -50`. 7. Multiple choice: B. `0xFFCE` as unsigned 16-bit is `65486`. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | C | A and B each choose one interpretation as universal, and D mistakes data bytes for an exception response. | | 2 | A | B uses the wrong word order, C adds signed interpretation not specified by the source row, and D belongs to a different float example. | | 3 | D | A/B/C are Modbus message fields, while IEEE-754 meaning is defined by a source map, profile, tool setting, or verified behavior. | | 4 | A | B is a possible test only if evidence contradicts the stated map, C changes the table and data model, and D is a write function code. | | 5 | C | A changes multiple variables, B ignores the valid response evidence, and D turns a vendor convention into an official protocol rule. | | 6 | A | B is the unsigned interpretation, C miscomputes the two's-complement value, and D drops the negative sign. | | 7 | B | A is the signed interpretation, C is the all-ones value `0xFFFF`, and D keeps only the low byte `0xCE`. | Short answer: 1. Unsigned 16-bit `FF CE` is `65486`; signed 16-bit two's-complement is `-50`. 2. Modbus defines how register data is transported, but device documentation or a profile defines how multiple registers combine into a larger value. 3. Good answers include type, width, signedness, byte/word order, scale, unit, validity context, documented address, PDU address, quantity, and source evidence. 4. A byte count only proves the number of data bytes returned. The client can still apply the wrong type, signedness, word order, scale, or unit. Applied scenario: 1. The data bytes are `41 48 00 00`. 2. First try IEEE-754 float `ABCD`. 3. The expected value is `12.5`. 4. Wrong assumptions include low-word-first decode, byte-swapped decode, treating the bytes as a U32 integer, applying an unsupported scale, or changing the address before testing the decode. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for multi-byte numeric encoding in protocol fields, four primary logical data tables, addressing model and zero-based PDU addresses, read holding/input register quantity limits, and normal response vs exception response. - Signedness, IEEE-754 use, word order, strings, BCD, and wider numeric meanings remain map/profile/tool behavior unless tied to a reviewed source. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 7/16 · v1.0.0 · Exported for offline / agent use._ # Module 8: Scaling & Engineering Meaning > Raw register → engineering value with units, scale, and a sanity check at every step. **Phase:** Addressing & Data Meaning **Estimated time:** 9 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/scaling-engineering-meaning ## What you'll be able to do - Convert a raw register to engineering units with the correct sign, scale, and unit. - Decode bitfields and enums from a status word. - Use sentinel values to mark a reading invalid instead of displaying nonsense. ## Three things people get wrong 1. **Scaling before checking signedness.** Apply the type rule (S16/S32) first, then divide by 10. Otherwise -1 becomes 6553.5. 2. **Showing sentinels as values.** 0x7FFF / 0x8000 / 0xFFFF are often 'invalid' markers — gate them before they reach a dashboard. 3. **Forgetting the unit.** A number without a unit is a guess. Carry the unit through every transformation. ## From the field **The dashboard that scaled twice** A team multiplied by 0.1 in the gateway and another 0.1 in the historian. Voltages displayed as 2.4 V instead of 240 V. The bug only showed up when an operator tried to plot trends against the utility bill. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) — Modbus does not standardize scaling — entirely vendor convention. ## Lesson # Module 8 Lesson: Scaling And Engineering Meaning ## Learner Outcome By the end of this module, learners can convert raw Modbus values into engineering telemetry with explicit type, scale, offset, unit, sign convention, sentinel handling, quality, and state context. They can also decode simple status words and enum values without treating map-specific meanings as official Modbus behavior. ## Key Concepts - Modbus transports raw bits and register data. The register map supplies engineering meaning. - Scaling can be written as `/10`, `/100`, `*0.1`, a decimal-position register, an offset formula, or a profile-specific convention. - Units and sign conventions are part of the integration contract. `W`, `kW`, `Hz`, `centi-Hz`, `deg C`, import/export direction, and charge/discharge direction can vary by device. - Sentinel values are raw values that mean invalid, unavailable, overflow, not installed, stale, or sensor fault. - Status words, alarm words, command words, and enums must be decoded from the source map and verified against known safe states. - A professional integration preserves raw value, decoded value, unit, quality, source evidence, and unresolved assumptions during commissioning. ## Key Terms - Scale: the source-map rule that converts raw value into engineering value. - Engineering unit: the unit that gives a decoded value meaning, such as volts, hertz, or degrees C. - Sentinel: a special raw value that means invalid, unavailable, overrange, or another non-measurement state. - Enum: a numeric code mapped to named states. - Bitfield: a register where individual bits carry separate meanings. - Quality: evidence that a value is valid, stale, invalid, estimated, or context-dependent. - Freshness: whether the value is current enough to use. ## Source-Grounded Explanation A Modbus response can return valid bytes while the displayed telemetry is still wrong. The response does not carry a unit label, scale factor, sign convention, sentinel table, or quality flag. Those meanings come from vendor documentation, a device profile, a synthetic course map, or verified behavior. The basic teaching model is: ```text engineering value = decoded raw value * scale + offset ``` That formula is useful, but maps may express it in different ways. A row may say `/10`, `0.1`, `scale = -1`, `decimal position = 2`, or `value = raw / 100`. If the map does not say whether an offset is applied before or after scaling, mark the row `Needs verification` and test against a known display or simulator. ### Scaling Examples | Source Row | Raw Bytes | Raw Value | Meaning | |---|---:|---:|---| | `line_voltage_l1_l2`, `U16`, `/10 V` | `09 C4` | `2500` | `250.0 V` | | `ac_frequency`, `U16`, `/100 Hz` | `17 70` | `6000` | `60.00 Hz` | | `battery_power`, `S32`, `/10 kW` | `FF FF F6 3C` | `-2500` | `-250.0 kW` in the synthetic sign convention | Synthetic sign convention for this lesson: negative `battery_power` means charging/import into the battery; positive means discharging/export from the battery. This is scoped to the synthetic course map. It is not a universal Modbus rule or a universal battery-vendor convention. ### Sentinels And Quality A sentinel is a raw value that should not be displayed as a real measurement. Example: | Field | Value | |---|---| | Parameter | Lab temperature reading | | Type | signed 16-bit | | Scale/unit | `/10 deg C` | | Sentinel | `0x7FFF` means invalid/unavailable | | Response | `03 02 7F FF` | Wrong display: ```text 32767 / 10 = 3276.7 deg C ``` Correct telemetry: ```text temperature.raw = 0x7FFF temperature.value = null temperature.unit = deg C temperature.quality = invalid temperature.reason = synthetic sentinel: unavailable ``` ### Status Words And Enums Bit-level meaning also comes from the map. A 16-bit status word might define: | Bit | Meaning | |---:|---| | 0 | Enabled | | 1 | Fault active | | 2 | Remote mode | | 3 | Power value valid | If the raw value is `0x000D`, the binary value is: ```text 0000 0000 0000 1101 ``` Bits `0`, `2`, and `3` are set. The device is enabled, remote mode is true, and the power value is valid. Fault active is false. Field note: many maps use bit `0` as the least-significant bit, but bit numbering is still a map convention. Some manuals number bits `1-16` or display bit diagrams left-to-right. Verify the convention before building alarms or command logic. Enum values are similar. A register value of `2` means nothing by itself. In the synthetic fixture, operating mode enum `2` means `Remote`. In another device, the same value could mean a different state. ## Practical Example: Normalized Telemetry Synthetic read set: | Tag | Function | Documented Address | PDU Address | Quantity | Type | Raw Response | |---|---:|---|---:|---:|---|---| | `battery_power` | `03` | `40091` | `90` | `2` | signed 32-bit high word first, `/10 kW` | `03 04 FF FF F6 3C` | | `telemetry_status_word` | `03` | `40081` | `80` | `1` | U16 bitfield | `03 02 00 0D` | | `operating_mode` | `03` | `40093` | `92` | `1` | U16 enum | `03 02 00 02` | | `lab_temperature_reading` | `03` | `40094` | `93` | `1` | S16 `/10 deg C`, sentinel `0x7FFF` | `03 02 7F FF` | Decoded telemetry: | Tag | Raw | Decoded Value | Unit | Quality | State Context | |---|---:|---:|---|---|---| | `battery_power` | `-2500` | `-250.0` | `kW` | valid | valid because status bit `3` is true; negative means charging in this synthetic map | | `telemetry_status_word.enabled` | bit `0` | `true` | flag | valid | source label: synthetic vendor note | | `telemetry_status_word.fault_active` | bit `1` | `false` | flag | valid | no active fault in this response | | `telemetry_status_word.remote_mode` | bit `2` | `true` | flag | valid | operating mode should agree with enum | | `operating_mode` | `2` | `Remote` | enum | valid | synthetic enum table | | `lab_temperature_reading` | `0x7FFF` | null | `deg C` | invalid | sentinel means unavailable | The important point is not just arithmetic. Learners should preserve the evidence chain: ```text response bytes -> raw value -> typed value -> scale/unit -> quality/state-aware telemetry ``` ## Common Pitfalls - Displaying a scaled value without its unit. - Applying scale before signedness and width are correct. - Treating a sentinel as a real maximum, minimum, or alarming process value. - Showing stale or invalid values as live telemetry because the valid bit was ignored. - Assuming negative power always means import, export, charge, or discharge. - Treating bit numbering as obvious from the tool display rather than from the source map. - Treating latching, historical, or read-to-clear alarm behavior as generic Modbus behavior instead of future vendor-specific coverage that needs a named source. - Treating a write echo as proof that the physical process changed state. ## Instructor Flow 1. Start with one known raw register and apply scale/unit. 2. Add signedness and sign convention. 3. Add one status word and decode bit truth values. 4. Add one sentinel and force learners to output null/invalid rather than a fake engineering value. 5. Add one enum and cross-check it against a related status bit. 6. End with a normalized telemetry table that keeps raw, decoded, quality, and source evidence together. ## Check-Your-Understanding 1. A register returns raw `1234`, type signed 16-bit, scale `/10`, unit `deg C`. What should be displayed? 2. A status register returns `0x0006`. If bit `1` means fault active and bit `2` means remote mode, what is true? 3. A temperature register returns `0x7FFF`, and the map says that value means unavailable. What should the telemetry show? 4. Why should a dashboard keep both raw value and decoded engineering value during commissioning? ## Source Notes - Official rule: Modbus Application Protocol Specification V1.1b3 defines normal and exception response shapes, register read/write functions, byte counts for normal read responses, and exception behavior. It does not define universal engineering units, scale factors, alarm meanings, quality bits, sentinels, enum values, or battery sign conventions. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for normal response vs exception response, exception codes and exception response PDU shape, read holding/input register quantity limits, write single register shape and echo boundary, and multi-byte numeric encoding in protocol fields. - Future vendor-specific coverage: latching alarms, historical alarms, and read-to-clear registers need a named device manual or profile before becoming runnable course examples. - Synthetic source: `release/synthetic-course-device-map.md` provides the current no-hardware Module 8 fixtures. - Vendor/profile source: real scale, sentinel, bitfield, enum, and sign-convention rules must come from the named device manual, profile, or verified behavior. - Tool source: display names, bit labels, and alarm handling must be tied to a selected tool/version before release. ## Completion Checkpoint Before moving on, learners should turn one raw register value into an engineering value and also decide whether sentinel, quality, state, or freshness rules prevent that value from being used as trustworthy telemetry. ## Reusable Assets - [Synthetic course device map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) - [Raw-to-telemetry worksheet](https://learnmodbus.studioseventeen.io/resource/raw-to-telemetry-worksheet) - [Raw-to-telemetry lab](https://learnmodbus.studioseventeen.io/lesson/scaling-engineering-meaning?page=lab-1) - [Module 8 quiz](https://learnmodbus.studioseventeen.io/lesson/scaling-engineering-meaning?page=quiz) - [Data type and byte-order worksheet](https://learnmodbus.studioseventeen.io/resource/data-type-byte-order-worksheet) ## Diagram source ```mermaid flowchart LR Raw["Raw register: 224"] Map["Map: INT16, /10, °C"] Raw --> Apply["Apply scale"] Map --> Apply Apply --> Eng["22.4 °C"] Eng --> Check["Plausible range check"] ``` ## Labs ### Lab 1 # Lab 8: Raw Registers To Normalized Telemetry ## Learner Outcome Learners can convert raw Modbus response bytes into normalized telemetry that includes raw value, decoded value, unit, quality, state context, source label, and unresolved assumptions. ## Prerequisites - Module 5: documented address versus PDU address. - Module 6: normalized register-map rows. - Module 7: signedness, width, and word order. - Module 8 lesson through sentinels and bitfields. ## Safety And Scope This lab uses [Synthetic Course Device Map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) and [Raw-To-Telemetry Worksheet](https://learnmodbus.studioseventeen.io/resource/raw-to-telemetry-worksheet). It is a paper or spreadsheet exercise until the simulator fixture is implemented. Do not use these synthetic sign conventions, sentinel values, enum values, or bit meanings on production devices. Real equipment requires its own manual, read-only verification, and commissioning evidence. ## Scenario You have a valid set of Modbus read responses from a course energy system simulator. The raw values are not ready for a dashboard. Your job is to turn them into normalized telemetry that another integrator can review without guessing. ## Protocol Targets | Tag | Function | Documented Address | PDU Address | Quantity | Type | Source Meaning | Response PDU | |---|---:|---|---:|---:|---|---|---| | `line_voltage_l1_l2` | `03` | `40010` | `9` | `1` | U16 | `/10 V`; validity depends on grid-present evidence not included in this fixture | `03 02 09 C4` | | `ac_frequency` | `04` | `30021` | `20` | `1` | U16 | `/100 Hz`, input-register table | `04 02 17 70` | | `battery_power` | `03` | `40091` | `90` | `2` | S32 high word first | `/10 kW`; negative means charging in this synthetic map | `03 04 FF FF F6 3C` | | `telemetry_status_word` | `03` | `40081` | `80` | `1` | U16 bitfield | bit 0 enabled, bit 1 fault, bit 2 remote, bit 3 power valid | `03 02 00 0D` | | `operating_mode` | `03` | `40093` | `92` | `1` | U16 enum | `0` Off, `1` Local, `2` Remote, `3` Faulted | `03 02 00 02` | | `lab_temperature_reading` | `03` | `40094` | `93` | `1` | S16 | `/10 deg C`; `0x7FFF` means unavailable | `03 02 7F FF` | ## Procedure 1. For each row, confirm the request fields: function code, documented address, PDU address, and quantity. 2. Confirm the response shape: function code, byte count, and data bytes. 3. Decode the raw value using the stated type, signedness, and word order. 4. Apply scale and unit only after the raw type is correct. 5. Decode `telemetry_status_word` into individual boolean fields. 6. Decode `operating_mode` using the synthetic enum table. 7. Apply the temperature sentinel rule before scaling it as a real temperature. 8. Fill the normalized telemetry table and source labels. 9. Write one sentence explaining which claims came from official protocol behavior and which came from synthetic map meaning. ## Auto-Graded Checks ```lab type: scale prompt: line_voltage_l1_l2 reads raw 0x09C4 (= 2500). Apply the synthetic map scale (÷10 V). raw: 2500 op: div factor: 10 unit: V explain: 2500 ÷ 10 = 250.0 V (quality conditional on grid-present evidence). ``` ```lab type: scale prompt: ac_frequency reads raw 0x1770 (= 6000). Apply the input-register scale (÷100 Hz). raw: 6000 op: div factor: 100 unit: Hz explain: 6000 ÷ 100 = 60.00 Hz. ``` ```lab type: decode prompt: Decode battery_power as S32 high word first. Raw bytes shown below. bytes: FF FF F6 3C as: s32 order: ABCD hint: A leading 0xFFFF strongly suggests a negative two's-complement value. explain: 0xFFFFF63C → -2500. After ÷10 kW that's -250.0 kW (charging in this synthetic map). toolLink: /tools?tab=decoder&hex=FFFFF63C ``` ```lab type: text prompt: lab_temperature_reading returns raw 0x7FFF. According to the synthetic source map, what value should you display? (one word) answer: invalid hint: 0x7FFF is the sentinel for unavailable on this map — quality should win over plausibility. explain: Display invalid / unavailable, NOT 3276.7 °C. ``` ## Worksheet | Tag | Raw Bytes | Raw Value | Decode Rule | Engineering Value | Unit | Quality | State Context | Source Label | Unresolved Assumptions | |---|---|---:|---|---:|---|---|---|---|---| | `line_voltage_l1_l2` | | | | | | | | | | | `ac_frequency` | | | | | | | | | | | `battery_power` | | | | | | | | | | | `telemetry_status_word.enabled` | | | | | flag | | | | | | `telemetry_status_word.fault_active` | | | | | flag | | | | | | `telemetry_status_word.remote_mode` | | | | | flag | | | | | | `telemetry_status_word.power_valid` | | | | | flag | | | | | | `operating_mode` | | | | | enum | | | | | | `lab_temperature_reading` | | | | | deg C | | | | | ## Expected Results | Tag | Expected Result | Why | |---|---|---| | `line_voltage_l1_l2` | `250.0 V`, quality conditional | `0x09C4 = 2500`; `/10 V` is synthetic map meaning; grid-present evidence is not included in this fixture. | | `ac_frequency` | `60.00 Hz` | `0x1770 = 6000`; `/100 Hz`; function `04` confirms input-register response. | | `battery_power` | `-250.0 kW`, valid | `0xFFFFF63C` as S32 is `-2500`; `/10 kW`; status bit `3` is true. | | `telemetry_status_word.enabled` | `true` | `0x000D` has bit `0` set. | | `telemetry_status_word.fault_active` | `false` | `0x000D` does not have bit `1` set. | | `telemetry_status_word.remote_mode` | `true` | `0x000D` has bit `2` set. | | `telemetry_status_word.power_valid` | `true` | `0x000D` has bit `3` set. | | `operating_mode` | `Remote` | Synthetic enum table maps raw `2` to `Remote`. | | `lab_temperature_reading` | null/invalid, not `3276.7 deg C` | `0x7FFF` is a synthetic sentinel for unavailable. | ## Expected Observations - Scaling without unit and quality is not enough for paid-course-grade telemetry. - A raw sentinel should become invalid/unavailable, not a large process value. - Bitfield and enum meanings are source-map claims, not official Modbus claims. - Status bit `remote_mode` and enum `Remote` agree in this fixture; a mismatch would be a troubleshooting clue. ## Troubleshooting Notes - If a value looks wrong, separate communication evidence from interpretation evidence. - If a scaled value is plausible but the valid bit is false, quality should win over plausibility. - If a tool numbers bits differently than the source map, record both labels and prove the convention with a known safe state. - Treat read-to-clear alarm behavior as vendor-specific future coverage until a named manual or profile is reviewed. ## Check Questions 1. Which values in this lab are official protocol evidence? 2. Which values are synthetic map meaning? 3. Why is `0x7FFF` not displayed as `3276.7 deg C`? 4. What would you record if `operating_mode` said `Remote` but the status word's remote bit was false? ## Instructor Notes - Insist that learners fill source labels, not just numbers. - Ask learners to show the raw response bytes next to every decoded value. - Use the temperature sentinel row to reinforce that quality gates come before dashboards. - Keep write behavior out of this lab; Module 15 owns write safety. ## Source Notes - Official source: Modbus Application Protocol Specification V1.1b3 for normal read response structure, exception response structure, and register data fields. - Synthetic source: `release/synthetic-course-device-map.md` for scale, unit, bit, enum, sentinel, and sign-convention meanings. - Course-owned helper evidence: `python3 tools/modbus_fixture_helper.py decode-fixtures` verifies the Lab 8 raw decode values before synthetic scale, unit, enum, bitfield, sentinel, and quality rules are applied. - Local source: Module 7 data-type assets for signedness and word-order prerequisites. - Tool source: selected learner tools still need version-specific terminology and display verification before release. ## Knowledge check # Module 8 Quiz: Scaling And Engineering Meaning ## Questions ### Multiple Choice 1. A register returns raw `09 C4`, and the map says `U16`, `/10 V`. What should be displayed? - A. `2500 V`. - B. `250.0 V`. - C. `25.00 V`. - D. `09 C4 V`. 2. A temperature row says `S16`, `/10 deg C`, sentinel `0x7FFF = unavailable`, and the response data is `7F FF`. What should a dashboard show? - A. `3276.7 deg C`. - B. `32767 deg C`. - C. Invalid or unavailable, with raw value preserved. - D. Exception response. 3. A status word returns `0x000D`. If bits `0`, `2`, and `3` are set, which statement is true? - A. Bits `1`, `2`, and `4` are set because bit numbering starts at one. - B. The map's bit numbering must be applied; in the synthetic fixture, enabled, remote, and power-valid are true. - C. Modbus defines bit `3` as power valid. - D. The register must be a coil table. 4. A synthetic battery-power row says signed 32-bit, high word first, `/10 kW`, and negative means charging. Raw `FF FF F6 3C` decodes to `-2500`. What is the engineering value? - A. `-250.0 kW`, charging in this synthetic map. - B. `-2500 kW`, discharging by universal Modbus convention. - C. `250.0 W`, charging. - D. Invalid because negative values are not allowed in holding registers. 5. Which claim is official Modbus behavior for a normal FC03/FC04 read response? - A. `0x7FFF` means unavailable. - B. Enum value `2` means `Remote`. - C. The normal response includes a function code, byte count, and data bytes. - D. Negative battery power means charging. 6. A temperature row is `S16`, `/10 deg C`, with sentinel `0x7FFF = unavailable`. The response returns data bytes `7F FF`. What raw value and telemetry should be published? - A. Raw `32767`, value `3276.7 deg C`, quality valid. - B. Raw `0x7FFF`, value null/invalid, quality unavailable, raw preserved. - C. Raw `-1`, value `-0.1 deg C`, quality valid. - D. Raw `0x7FFF`, value `327.67 deg C`, quality valid. 7. In a decode pipeline, when should sentinel and quality handling happen relative to scaling and alarming? - A. After scaling, so the sentinel is scaled into engineering units first. - B. Before scaling and alarming, so an unavailable value is never displayed or alarmed as a real measurement. - C. Only after an alarm has already been raised on the scaled value. - D. Never, because Modbus flags sentinels in the response frame. ### Short Answer 1. Why should normalized telemetry preserve both raw value and engineering value? 2. What evidence would you need before using a vendor sign convention in a real dashboard? 3. Why should quality or sentinel handling happen before alarming on a scaled value? 4. Name three fields that belong in a telemetry row after decoding. ### Applied Scenario A synthetic course fixture returns: | Tag | Response | Source Meaning | |---|---|---| | `telemetry_status_word` | `03 02 00 0D` | bit 0 enabled, bit 1 fault, bit 2 remote, bit 3 power valid | | `operating_mode` | `03 02 00 02` | enum `0` Off, `1` Local, `2` Remote, `3` Faulted | | `lab_temperature_reading` | `03 02 7F FF` | S16 `/10 deg C`; `0x7FFF` means unavailable | Tasks: 1. Decode the status bits. 2. Decode the operating mode. 3. State the temperature telemetry value and quality. 4. Label which facts are official protocol behavior and which are synthetic map meaning. ## Answer Key 1. Multiple choice: B. `0x09C4` is `2500`, and the synthetic map's `/10 V` scale gives `250.0 V`. A misses the scale, C applies the wrong scale, and D displays the raw hex as if it were engineering data. 2. Multiple choice: C. The sentinel rule wins before scaling. A and B incorrectly display an unavailable value as real temperature, and D is wrong because the bytes shown are a normal data response. 3. Multiple choice: B. The bit meanings come from the source map. A assumes a different numbering convention without evidence, C invents an official Modbus meaning, and D confuses packed register bits with the coil table. 4. Multiple choice: A. The signed raw value `-2500` scaled by `/10 kW` is `-250.0 kW`, and the charging direction is scoped to the synthetic map. B invents a universal sign convention, C changes the unit, and D is false because holding registers can carry signed interpretations. 5. Multiple choice: C. Function code, byte count, and data bytes are part of a normal FC03/FC04 read response shape. Exception responses use a different exception-response shape, and the other claims are synthetic or vendor/profile meanings. 6. Multiple choice: B. `0x7FFF` matches the sentinel, so publish null/invalid with quality unavailable and preserve the raw value; do not scale it into `3276.7 deg C`. 7. Multiple choice: B. Sentinel and quality handling must run before scaling and alarming so an unavailable value is never displayed or alarmed as a real measurement. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A misses the `/10` scale, C applies the wrong scale, and D displays raw hex as if it were the engineering value. | | 2 | C | A/B scale or display a sentinel as real data, and D confuses normal data bytes with an exception response. | | 3 | B | A assumes a numbering convention without evidence, C invents an official bit meaning, and D confuses packed register bits with the coil table. | | 4 | A | B invents a universal sign convention, C changes the unit and magnitude, and D invents a ban on signed interpretations in holding registers. | | 5 | C | A/B/D are synthetic map or vendor/profile meanings, not fields defined by the normal FC03/FC04 response shape. | | 6 | B | A scales the sentinel as if valid, C invents a wrong sign and value, and D applies the wrong scale to a value that should not be scaled at all. | | 7 | B | A scales the sentinel before checking it, C alarms on a value before validating quality, and D falsely claims Modbus flags sentinels in the frame. | Short answer: 1. Raw values make commissioning and troubleshooting repeatable; engineering values make the data usable. Keeping both preserves evidence when scale, signedness, quality, or source assumptions are challenged. 2. A named manual/profile row plus known operating state, device display comparison, or captured real-device evidence showing the convention. Simulator evidence only counts for real equipment if it is versioned and explicitly implements the named device/profile. 3. A sentinel may look like a large valid number after scaling. Quality handling prevents false alarms, fake dashboards, and bad control decisions. 4. Good answers include raw bytes, raw value, type, scale, unit, decoded value, quality, validity context, source label, timestamp/freshness, and unresolved assumptions. Applied scenario: 1. `0x000D` has bits `0`, `2`, and `3` set: enabled true, fault false, remote true, power valid true. 2. Raw enum `2` means `Remote` in the synthetic enum table. 3. Temperature is null/invalid or unavailable; preserve raw `0x7FFF` and do not display `3276.7 deg C`. 4. Official protocol behavior: response function code, byte count, and data bytes. Synthetic map meaning: bit labels, enum labels, sentinel rule, and temperature unit/scale. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, normal response vs exception response, exception codes and exception response PDU shape, read holding/input register quantity limits, write single register shape and echo boundary, and multi-byte numeric encoding in protocol fields. - Scale, unit, sentinel, enum, status-bit, freshness, and quality rules remain synthetic-map or vendor/profile behavior. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 8/16 · v1.0.0 · Exported for offline / agent use._ # Module 9: Serial Communication Basics > Baud, parity, stop bits, timing — the fundamentals every RTU integrator must own. **Phase:** Physical Network & Transport **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/serial-communication-basics ## What you'll be able to do - Configure baud, parity, and stop bits to match a Modbus RTU server. - Calculate the 3.5-character silent interval at a given baud rate. - Recognize timing-related failures from a capture. ## Three things people get wrong 1. **Mixing parity and stop-bit defaults.** Default is 8-E-1 (even parity, 1 stop). If no parity, use 8-N-2. 2. **Ignoring the 3.5-char silent interval.** At 19200 baud and below, calculate the 1.5- and 3.5-character intervals. Above 19200 baud, the official guide recommends fixed 750 µs and 1.750 ms intervals. 3. **Treating timeout as 'wrong address'.** A timeout only proves that no valid response arrived before the client deadline. Check reachability, settings, address or Unit Identifier, framing, timing, gateway routing, and physical evidence. ## From the field **Two stop bits, one bad cable** An integrator could read at 9600 but timed out at 38400. The cable had marginal capacitance — fine at low baud, sloppy at high. Adding a second stop bit hid the symptom for a week until traffic doubled. The fix was the cable, not the settings. ## References - [Modbus over Serial Line V1.02](https://www.modbus.org/file/secure/modbusoverserial.pdf) — Section 2.4 — character framing and timing ## Lesson # Module 9 Lesson: Serial Communication Basics ## Learner Outcome By the end of this module, learners can identify the serial settings that must match on a Modbus serial link, separate Modbus PDU, serial ADU, and electrical-layer concerns, and classify common timeout symptoms before changing register addresses or data types. ## Key Concepts - Serial communication sends data as character frames over an electrical interface. - Baud rate, parity, data bits, and stop bits must match across the serial link. - The client must address the intended serial server ID, and server IDs should be unique on a multidrop segment. - Modbus RTU and Modbus ASCII are serial transmission modes. RS-232, RS-422, and RS-485 are electrical layers that can carry serial bytes. - A malformed serial frame, parity error, framing error, CRC/LRC error, wrong serial address, or timing problem usually appears as a timeout, not as a Modbus exception response. - Half-duplex links share transmit direction; full-duplex links have separate transmit and receive paths. - Many field symptoms are transport problems first, not register-map problems. ## Key Terms - Baud rate: the serial bit rate used by both ends of the link. - Parity: an error-detection setting that must match between client and server. - Stop bit: the bit or bits that mark the end of a serial character. - Timeout: the client-side deadline for receiving a valid response. - Serial server address: the serial address of the responding Modbus server. - One-change test: a troubleshooting step that changes only one likely cause before observing the result. ## Source-Grounded Explanation Teach serial Modbus in layers: ```text Modbus PDU: Function Code | Data Serial Modbus ADU: Address | Function Code | Data | CRC or LRC Electrical layer: RS-232, RS-422, RS-485, or another serial interface carrying bytes ``` The PDU is the Modbus operation. The serial ADU wraps that operation with a serial server address and an error-check field. Modbus RTU uses binary bytes and a CRC. Modbus ASCII uses ASCII hex characters and an LRC. The physical layer carries the serial characters but does not change the Modbus PDU. This layer diagram is shorthand. Modbus RTU uses silent intervals plus CRC framing; Modbus ASCII uses a colon start, ASCII hex characters, LRC, and CRLF ending. The project wiki summarizes official serial-line guidance this way: - Devices should support 9600 bps and 19.2 kbps, with 19.2 kbps as the required default. - Even parity is the default parity mode. - If no parity is used, two stop bits are used to keep character length consistent. - RTU frames are separated by silent intervals; an excessive silent gap inside a frame means the receiver should treat the frame as incomplete. Course reference: | Serial mode | Data representation | Default course setting | If parity is disabled | Source boundary | |---|---|---|---|---| | Modbus RTU | 8-bit binary bytes | `8-E-1` | `8-N-2` | Official serial-line guide basis; verify device manuals for deviations. | | Modbus ASCII | ASCII hex characters | `7-E-1` | `7-N-2` | Official serial-line guide basis; verify client-tool wording before release labs. | Field note: `8-N-1` is common in real devices and tools. Teach it as a device/tool setting to verify, not as the official default. ### Timeout Does Not Mean Exception A Modbus exception response is a valid Modbus response that reports a protocol-level problem, such as illegal function or illegal data address. A serial timeout is different. It means the client did not receive a valid response in time. Common serial timeout causes include: | Symptom Source | What Happens | |---|---| | Wrong baud rate | Receiver cannot decode the character stream correctly. | | Wrong parity or stop bits | UART framing/parity checks fail before Modbus can parse the frame. | | Wrong serial server address | The requested server does not answer. | | CRC or LRC failure | Receiver discards the frame silently. | | Timing gap inside RTU frame | Receiver treats the frame as incomplete. | | Half-duplex direction-control problem | Client or adapter transmits/receives at the wrong time. | | Noise or weak wiring | Bytes are corrupted before Modbus parsing. | The troubleshooting habit is to classify the failure first: ```text No valid response -> check transport/settings/address/timing/error check Exception response -> check function, PDU address, quantity, access, or device state Wrong value -> check map, type, word order, scale, unit, quality ``` ## Practical Example: Before Changing The Register Map Scenario: A technician is trying to read a temperature value from a serial controller. | Field | Example | |---|---| | Variant | Modbus RTU | | Electrical layer | Serial physical layer, type to be confirmed from device manual | | Serial settings | `19200`, even parity, 8 data bits, 1 stop bit | | Serial server address | `7` | | Function code | `03` Read Holding Registers | | Documented address | `40010` | | Actual PDU address | `9` if the map uses one-based `40001` notation | | Quantity | `1` register | | Data type/scale | signed 16-bit, `/10 deg C` | | Expected normal response | server address `7`, function `03`, byte count `02`, one register, valid CRC | | Likely no-response causes | wrong serial settings, wrong server address, CRC/framing failure, direction-control issue, wiring/noise | If the client times out, do not start by changing `40010` to `40009` or changing word order. First prove the link can exchange valid serial frames with the expected server address and serial settings. ## Common Pitfalls - Treating "serial" and "RS-485" as synonyms. - Treating Modbus RTU, Modbus ASCII, and Modbus TCP as interchangeable because they can carry similar PDUs. - Expecting a Modbus exception response for bad parity, wrong baud, or bad CRC. - Changing register addresses before confirming serial settings and server address. - Assuming `8-N-1` is official default because it is common in field tools. - Ignoring half-duplex direction control when using USB-to-RS-485 adapters. - Calling a silent serial discard a device bug without checking timing, framing, address, and error check evidence. ## Instructor Flow 1. Draw the three layers: PDU, serial ADU, electrical layer. 2. Compare timeout, exception response, and wrong value as separate diagnostic buckets — the three failure categories (no response, exception response, wrong value) that Module 14 develops into a full troubleshooting method. 3. Walk through the serial settings table. 4. Use simulated log cards to classify wrong baud, wrong parity, wrong server address, and illegal data address. 5. End with a checklist that requires serial evidence before register-map edits. ## Check-Your-Understanding 1. Name three transport-layer causes that can produce a timeout without a Modbus exception response. 2. What fields does a serial Modbus ADU add around the Modbus PDU? 3. Why should a troubleshooting worksheet ask for baud rate, parity, data bits, stop bits, and serial server address before changing function code? 4. Why is `8-N-1` a field/device setting to verify rather than the official default taught in this course? ## Source Notes - Official serial basis: Modbus over Serial Line Specification and Implementation Guide V1.02 for serial settings, RTU/ASCII framing, silent interval behavior, serial addressing, and default parity guidance. - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for PDU and exception-response concepts. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for serial client/server legacy terminology, serial server address range and broadcast address, serial implementation defaults and character formats, RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, PDU vs ADU and general frame structure, and normal response vs exception response. - Field-note basis: timeout triage and adapter direction-control symptoms come from project troubleshooting notes and must be tied to tool/hardware evidence before release labs. - Needs verification: final screenshots, client-tool wording, and adapter-specific behavior require selected tools and versions. ## Completion Checkpoint Before moving on, learners should classify a serial failure as likely baud, parity, stop-bit, server-address, timeout-window, or map-related evidence, then choose one safe next test. ## Reusable Assets - [Serial settings triage checklist](https://learnmodbus.studioseventeen.io/resource/serial-settings-triage-checklist) - [Serial settings triage lab](https://learnmodbus.studioseventeen.io/lesson/serial-communication-basics?page=lab-1) - [Module 9 quiz](https://learnmodbus.studioseventeen.io/lesson/serial-communication-basics?page=quiz) ## Labs ### Lab 1 # Lab 37: Serial Settings Triage Without Hardware ## Learner Outcome Learners can classify serial Modbus failures as no response, exception response, or wrong value, then choose the next evidence to gather without changing register-map assumptions prematurely. ## Prerequisites - Module 2: PDU and ADU. - Module 4: normal and exception responses. - Module 5: documented address versus PDU address. - Module 9 lesson through timeout triage. ## Safety And Scope This is a no-hardware paper lab. It uses simulated log cards, not a real serial port. Do not connect to production equipment or change device serial settings during this lab. Optional hardware tracks should be added only after a specific adapter, client tool, simulator/device, operating system, and expected output are verified. ## Scenario A technician is trying to read holding register `40010` from a serial controller at server address `7`. The map says `40010`, signed 16-bit, `/10 deg C`. The first request to try is function `03`, PDU address `9`, quantity `1`. The expected working setup is: | Field | Expected | |---|---| | Variant | Modbus RTU | | Serial server address | `7` | | Baud rate | `19200` | | Parity | even | | Data bits | `8` | | Stop bits | `1` | | Function | `03` | | PDU address | `9` | | Quantity | `1` | ## Log Cards | Card | Observed Evidence | |---|---| | F | Client sends to server `7`, function `03`, PDU address `9`, quantity `1`. Response is normal: server `7`, function `03`, byte count `02`, data `00 FA`, valid error check. | | A | Client sends to server `7`, function `03`, PDU address `9`, quantity `1`. No bytes are received before timeout. Local notes show client set to `9600 8-E-1`; device label says `19200 8-E-1`. | | B | Client sends to server `7`, function `03`, PDU address `9`, quantity `1`. Serial analyzer shows bytes returned, but client marks framing/parity error. Client is `19200 8-N-1`; device label says `19200 8-E-1`. | | C | Client sends to server `1`, function `03`, PDU address `9`, quantity `1`. No response. Device label says serial address `7`. | | D | Client sends to server `7`, function `03`, PDU address `9`, quantity `1`. Response from server `7`: function `83`, exception code `02`, valid error check. | | E | Client sends to server `7`, function `03`, PDU address `10`, quantity `1`. Response is normal with raw value `0000`, but nearby register `9` is known to contain `00FA`. | ## Procedure 1. For each card, classify the symptom as `No valid response`, `Exception response`, or `Wrong value`. 2. Identify the first evidence to check next. 3. Decide whether the learner should change serial settings, serial server address, function/PDU address, or data decoding. 4. Record which layer is implicated: PDU, serial ADU, serial settings, physical/electrical layer, or source map. 5. Fill the answer table. ## Worksheet | Card | Bucket | Most Likely Cause | Layer | Next Check | What Not To Change Yet | |---|---|---|---|---|---| | F | | | | | | | A | | | | | | | B | | | | | | | C | | | | | | | D | | | | | | | E | | | | | | ## Answer Key | Card | Bucket | Most Likely Cause | Layer | Next Check | What Not To Change Yet | |---|---|---|---|---|---| | F | Normal response | Baseline working case | Serial ADU and PDU both plausible | Decode raw `00 FA` using the source map and record evidence | Do not change any settings without a symptom | | A | No valid response | Baud mismatch | Serial settings | Match client to `19200 8-E-1` or confirm device setting | Register address, word order, scale | | B | No valid response | Parity/stop-bit mismatch or tool setting mismatch | Serial settings | Confirm `8-E-1` versus `8-N-1`; inspect tool parity error | Register address, data type | | C | No valid response | Wrong serial server address | Serial ADU | Send to server address `7`; confirm no duplicate IDs | Baud and register map if other evidence is absent | | D | Exception response | Function `03` returned exception code `02` Illegal Data Address | PDU/source map | Recheck documented address, PDU address, table, quantity, access | Serial settings, because a valid response arrived | | E | Wrong value | Off-by-one PDU address | Source map/addressing | Try PDU address `9` with documented-address evidence | Baud, parity, CRC, word order | ## Expected Observations - Bad serial settings usually create no valid Modbus response, not a Modbus exception. - A valid exception response proves that at least some serial transport path is working. - Wrong value is a different diagnostic path from timeout. - Changing several assumptions at once destroys evidence. ## Troubleshooting Notes - A client timeout is not enough evidence to change register addresses. - If a serial analyzer reports framing or parity errors, stay in the serial-settings layer. - If the device is silent only for one server address, check serial server address before wiring. - If the response function code has the exception bit set, move to function/address/quantity/access evidence. ## Check Questions 1. Which card proves the serial path returned a valid Modbus response? 2. Which cards should not lead to register-map changes yet? 3. Why does card E belong to the wrong-value bucket rather than the no-response bucket? 4. What real tool evidence would you need before turning this into a runnable hardware lab? ## Instructor Notes - Ask learners to explain why each wrong answer is tempting. - Keep the three buckets visible: no valid response, exception response, wrong value. - Do not let learners change address, baud, parity, and scale in one step. - Optional extension: add a real serial client log after tool versions are selected. ## Source Notes - Official serial source: Modbus over Serial Line Specification and Implementation Guide V1.02 for serial settings, RTU framing, server address, and silent discard behavior. - Official protocol source: Modbus Application Protocol Specification V1.1b3 for exception-response shape and exception code `02`. - Synthetic source: all log cards are course-authored teaching fixtures. ## Knowledge check # Module 9 Quiz: Serial Communication Basics ## Questions ### Multiple Choice 1. A Modbus RTU client receives no valid bytes before timeout. Which cause is most likely to produce this symptom without a Modbus exception response? - A. Wrong parity setting. - B. Illegal data address returned by the server. - C. Unsupported function code returned as exception `01`. - D. Valid read response with byte count `02`. 2. Which layer adds the serial server address and CRC/LRC around the Modbus PDU? - A. Modbus TCP MBAP header. - B. Serial Modbus ADU. - C. Vendor register map. - D. Engineering-unit scale. 3. Which statement is safest about `8-N-1`? - A. It is the official default for all Modbus RTU devices. - B. It is common in field devices and tools, but must be verified against the device and client settings. - C. It is a Modbus TCP setting. - D. It changes the PDU address. 4. A client sends to serial server `1`, but the device label says address `7`. No response is received. What should be checked before changing `40010` to another register? - A. Serial server address. - B. Floating-point word order. - C. Scale factor. - D. Unit label. 5. A response contains exception function `83` and exception code `02`. What does this prove? - A. The serial path returned a valid Modbus exception response. - B. The baud rate must be wrong. - C. The server never heard the request. - D. The value should be byte-swapped. 6. According to the official serial-line guidance, which parity mode is the default for Modbus serial devices, and what stop-bit rule applies if parity is disabled? - A. No parity is the default, with one stop bit. - B. Even parity is the default, and if parity is disabled two stop bits are used. - C. Odd parity is the default, with one stop bit. - D. Parity is not defined by the serial-line guidance and is vendor-specific. 7. A client reads holding register `40010` from serial server `7`. The device label says `19200 8-E-1` but the client is set to `9600 8-E-1`, and the client times out. What is the first setting to fix? - A. The floating-point word order. - B. The scale factor. - C. The baud rate mismatch between client and device. - D. The engineering unit label. ### Short Answer 1. List four serial settings or identifiers that should be recorded before changing register-map assumptions. 2. Why do bad CRC, parity, framing, or timing problems usually look like timeouts? 3. Explain the difference between a Modbus exception response and a serial timeout. 4. Name one reason half-duplex direction control matters on many RS-485 Modbus RTU links. ### Applied Scenario A technician is reading documented holding register `40010` from serial server `7`. | Field | Current Setting | |---|---| | Device label | `19200 8-E-1`, server address `7` | | Client setting | `9600 8-E-1`, server address `7` | | Function | `03` | | PDU address | `9` | | Quantity | `1` | | Client result | Timeout | Tasks: 1. Classify the symptom bucket. 2. Identify the first setting to fix or verify. 3. State why changing data type, word order, or scale is premature. 4. State what evidence would move the problem from serial settings to function/address troubleshooting. ## Answer Key 1. Multiple choice: A. Wrong parity can prevent the receiver from accepting a valid serial frame. B and C are valid exception responses, not silent serial timeouts. D is a normal response. 2. Multiple choice: B. The serial Modbus ADU wraps the PDU with serial address and error check. MBAP is for Modbus TCP, and scale/register-map meanings are not transport fields. 3. Multiple choice: B. `8-N-1` appears often in real tools and devices, but the course should teach it as a setting to verify, not as the official default. 4. Multiple choice: A. A request sent to the wrong serial server address can be ignored by the intended server. 5. Multiple choice: A. Exception function `83` and code `02` mean a valid Modbus exception response was received, so the next check is function/address/quantity/access evidence, not baud rate. 6. Multiple choice: B. The official serial-line guidance sets even parity as the default; when parity is disabled, two stop bits are used to keep character length consistent (`8-N-2`). `8-N-1` is common in field tools but is not the official default. 7. Multiple choice: C. The client `9600` does not match the device `19200`, so the baud rate is the first thing to fix. Word order, scale, and unit are data-interpretation fields that only matter after valid response bytes are received. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | A | B/C are valid exception-response cases, and D is a valid normal read response rather than a silent timeout cause. | | 2 | B | A is TCP framing, C is source meaning, and D is an engineering interpretation rule. | | 3 | B | A invents a universal default, C moves the setting to TCP, and D confuses serial format with register addressing. | | 4 | A | B/C/D are data-interpretation fields that come after a valid response from the intended serial server. | | 5 | A | B/C contradict the received valid frame, and D jumps to data decoding instead of acting on exception evidence. | | 6 | B | A/C name the wrong default parity mode, and D denies that the serial-line guidance defines a default at all. | | 7 | C | A/B/D are data-interpretation fields that only apply after a valid response; the mismatched baud rate blocks any valid frame first. | Short answer: 1. Good answers include baud rate, parity, data bits, stop bits, serial server address, Modbus variant, client timeout, and adapter/tool setting. 2. Those errors prevent a valid Modbus frame from being accepted. Receivers normally discard malformed frames rather than returning a Modbus exception. 3. A Modbus exception response is a valid Modbus response with an exception function and code. A serial timeout means the client did not receive a valid response in time. 4. On a half-duplex link, only one side should transmit at a time. Poor adapter direction control or two devices transmitting together can corrupt bytes before Modbus parsing. Applied scenario: 1. No valid response. 2. Baud rate mismatch: the client is `9600`, while the device label says `19200`. 3. Data type, word order, and scale apply after valid response bytes are received. The current evidence says the client has not received a valid response. 4. A valid normal response or exception response from server `7` would prove the serial path is at least partly working and move the next check to function, PDU address, quantity, table, access, or map evidence. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for serial client/server legacy terminology, serial server address range and broadcast address, serial implementation defaults and character formats (SER-2.5-DEFAULTS: default parity is even, 8-N-2 when parity is disabled), RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, PDU vs ADU and general frame structure, and normal response vs exception response. - Adapter direction control, tool timeout wording, and field symptom patterns remain tool/hardware evidence gates. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 9/16 · v1.0.0 · Exported for offline / agent use._ # Module 10: RS-232, RS-422, RS-485 > Topologies, biasing, termination, and why your bus quietly stops working at node 17. **Phase:** Physical Network & Transport **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/rs-physical-layers ## What you'll be able to do - Wire a multi-drop RS-485 bus with correct termination and biasing. - Pick RS-232 / RS-422 / RS-485 for a given topology. - Diagnose 'works at node 5, dies at node 17' bus problems. ## Three things people get wrong 1. **Terminating one end only.** Terminate near both trunk ends, never on a derivation, and choose the termination network from the official design case plus the cable and device documentation. 2. **Skipping fail-safe biasing.** Use one bus-wide polarization network only when the connected devices require it; verify the values against the device and network design. 3. **Mixing A/B polarity across vendors.** Different vendors label A/B opposite ways. Trust the signal name (D+/D-) over the letter. ## From the field **The 17th drop** Adding one more meter to an existing RS-485 trunk caused every device to start dropping frames. The added stub was 80 cm — long enough to reflect at 38400 baud. Rerouting the cable as a true daisy-chain fixed the problem without changing any device settings. ## References - [TIA-485-A standard](https://global.ihs.com/doc_detail.cfm?document_name=TIA-485-A) - [Modbus over Serial Line V1.02](https://www.modbus.org/file/secure/modbusoverserial.pdf) — Section 3 — physical layer ## Lesson # Module 10 Lesson: RS-232, RS-422, And RS-485 ## Learner Outcome By the end of this module, learners can distinguish Modbus serial transmission modes from physical/electrical layers, compare RS-232, RS-422, and RS-485 at a troubleshooting level, and identify common RS-485 topology, termination, common-conductor, polarity-label, and server-ID faults before blaming the Modbus register map. ## Key Concepts - Modbus RTU and Modbus ASCII describe serial Modbus framing. RS-232, RS-422, and RS-485 describe electrical interfaces that can carry serial bytes. - RS-232 is commonly used for short point-to-point links, bench work, and older equipment. - RS-422 uses differential signaling and is commonly treated in this course as point-to-point or one-driver/multiple-receiver unless a device manual says otherwise. - RS-485 is the common physical layer for multidrop industrial Modbus RTU networks. - On a 2-wire RS-485 bus, topology, common conductor, terminations, polarity labels, bias/polarization, stubs, and duplicate server IDs can all create timeouts or intermittent communication. ## Key Terms - RS-232: a point-to-point serial physical-layer option. - RS-422: a differential serial physical-layer option often used for longer distances or one-driver/multiple-receiver variants. - RS-485: a common differential multidrop serial physical layer used with Modbus RTU. - Topology: the physical arrangement of devices and cable runs. - Termination: resistance used to reduce signal reflections on a bus. - Bias: a method for keeping an idle RS-485 line in a known state. - Common conductor: a reference conductor that may be required by device manuals or site standards. - Polarity label: vendor terminal naming for differential pairs; labels can vary. ## Source-Grounded Explanation The Modbus PDU can be the same while the wiring problem changes completely. ```text Modbus PDU: Function Code | Data Serial Modbus ADU: Server Address | Function Code | Data | CRC or LRC Physical layer: RS-232, RS-422, RS-485, or another serial interface ``` Module 9 taught serial settings. Module 10 teaches the electrical layer carrying those serial characters. | Physical Layer | Common Course Use | Topology | Troubleshooting Emphasis | |---|---|---|---| | RS-232 | Bench setup, legacy devices, short point-to-point links | Point-to-point | Cable/adapter, port settings, local loopback-style checks | | RS-422 | Differential signaling, longer links, limited receive-only multidrop patterns | Usually point-to-point or one-driver/multiple-receiver in this course | Direction, pairs, device-manual-specific wiring | | RS-485 | Industrial Modbus RTU field buses | Multidrop bus, commonly 2-wire half-duplex | Trunk/stubs, terminations, common conductor, unique server IDs, polarity labels, biasing | ### RS-485 Course Rules The project wiki summarizes official serial-line guidance with these RS-485 points: | Topic | Course Rule | Source Boundary | |---|---|---| | Bus shape | Use one trunk with daisy-chain devices or short derivations. | Official serial-line guide basis; final wording needs direct review. | | Termination | Terminate near both ends of the trunk, not at every device. | Do not teach a universal resistor value without a selected cable/device source. | | Derivations/stubs | Keep derivations short and do not terminate stubs. | Official guide gives a maximum derivation value in the wiki; final release should verify directly. | | Common conductor | Standard 2-wire Modbus uses a balanced pair plus common conductor. | Grounding and shielding details are installation-specific. | | Driver control | Only one driver should transmit at a time on a 2-wire bus. | Adapter direction-control behavior is hardware/tool-specific. | | Node count | The wiki uses the official guide's 32-device statement as a conservative course anchor. | Higher counts require documented low-unit-load devices or repeaters. | | Bias/polarization | If needed, implement for the segment rather than independently at many devices. | Resistor values are hardware-design or vendor-manual details. | | Polarity labels | A/B, D+/D-, and vendor terminal names are not universal. | Verify against the device manual or controlled test evidence. | Field note: many serial Modbus problems are RS-485 problems: A/B label reversal, missing common conductor, too many terminations, no termination, star topology, long stubs, duplicate server IDs, mismatched serial settings, weak biasing, ground loops, bad shielding, or adapter direction-control timing. Treat this as triage guidance, not a universal diagnosis. ## Practical Example: Three Meters On One RS-485 Trunk Scenario: One Modbus RTU client polls three energy meters on a 2-wire RS-485 trunk. | Field | Example | |---|---| | Variant | Modbus RTU | | Physical layer | RS-485 2-wire half-duplex | | Serial server addresses | `1`, `2`, and `3` | | Function code | `04` Read Input Registers | | Documented address | `30001` | | Actual PDU address | `0` if the map uses one-based `30001` notation | | Quantity | `2` registers | | Data type/scale | vendor-defined 32-bit value, scale/unit from meter map | | Expected normal behavior | Only the addressed server responds to each request | | Likely physical-layer failure modes | timeout or intermittent failures from bad topology, missing common conductor, too many terminations, polarity mismatch, duplicate IDs, or direction-control problem | Triage sequence: 1. Draw the trunk, stubs, devices, and client before changing software. 2. Confirm the physical layer really is RS-485 and not RS-232 or Ethernet-to-serial gateway behavior. 3. Confirm only one driver transmits at a time on the 2-wire segment, and that normal Modbus transactions are initiated by the client with unique server IDs. 4. Confirm there are terminations near the two trunk ends only. 5. Confirm common conductor, polarity labels, and shield/grounding approach from the device manuals. 6. Only after the physical layer and serial settings are credible should learners change function code, PDU address, data type, scale, or word order. ## Common Pitfalls - Calling RS-485 "the Modbus protocol." - Assuming a Modbus RTU problem must be an RS-485 problem; RTU can also appear over other serial interfaces. - Building a star topology because Ethernet wiring habits leak into serial work. - Adding termination at every device instead of at the trunk ends. - Leaving out the common conductor and then chasing intermittent timeouts. - Assuming A/B labels mean the same thing across all vendors. - Treating a hardware app note or vendor high-node-count claim as a universal Modbus rule. - Changing register addresses when the problem is a physical bus fault or duplicate serial server ID. ## Instructor Flow 1. Reuse the Module 9 layer diagram and move the focus to the physical layer. 2. Compare RS-232, RS-422, and RS-485 in one table. 3. Walk through the RS-485 course rules with source-boundary labels. 4. Use topology fault cards: correct trunk, star topology, three terminations, long stub, missing common, duplicate server ID, and uncertain A/B labels. 5. End by tying physical-layer evidence back to the three troubleshooting buckets: no valid response, exception response, wrong value. ## Check-Your-Understanding 1. Why can the same Modbus RTU request behave differently over RS-232 and RS-485 even if the PDU is unchanged? 2. On a passive RS-485 trunk, where should termination normally be placed? 3. Why should A/B or D+/D- labels be treated as vendor-specific evidence? 4. A bus has four servers and only one replies reliably. Name two wiring/topology checks and two configuration checks. ## Source Notes - Official serial basis: Modbus over Serial Line Specification and Implementation Guide V1.02 for RS-485 topology, common conductor, termination, derivation, node-count, and polarization guidance as summarized in the project wiki. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for RS-485 implementation guidance, serial server address range and broadcast address, serial client/server legacy terminology, RTU/ASCII frame fields, CRC/LRC checking, and RTU timing and ASCII framing where symptoms depend on framing/timing. - Secondary hardware sources: hardware vendor application notes listed in `notebooklm-source-list.md` should be used before publishing exact cable, shielding, termination resistor, surge, isolation, high-node-count, RS-232, or RS-422 comparison guidance. - Field-note basis: project troubleshooting notes for common RS-485 fault patterns. - Needs verification: final release needs direct serial-guide review and selected hardware-source review before turning draft wording into release-ready field guidance. ## Completion Checkpoint Before moving on, learners should identify whether a symptom belongs to the physical layer, serial settings, Modbus frame evidence, or register-map interpretation. They should not perform field wiring changes from this lesson alone. ## Reusable Assets - [RS-485 wiring review checklist](https://learnmodbus.studioseventeen.io/resource/rs485-wiring-review-checklist) - [Physical-layer comparison lab](https://learnmodbus.studioseventeen.io/lesson/rs-physical-layers?page=lab-1) - [Module 10 quiz](https://learnmodbus.studioseventeen.io/lesson/rs-physical-layers?page=quiz) - [Serial settings triage checklist](https://learnmodbus.studioseventeen.io/resource/serial-settings-triage-checklist) ## Diagram source ```mermaid flowchart LR T["120Ω term"] --- N1["Node 1"] --- N2["Node 2"] --- N3["Node 3"] --- Nx["Node N"] --- T2["120Ω term"] Bias["Bias resistors
(idle high)"] -.-> N1 ``` ## Labs ### Lab 1 # Lab 11: Physical-Layer Topology Fault Cards ## Learner Outcome Learners can inspect simplified serial-network diagrams, identify likely physical-layer faults, separate physical-layer evidence from Modbus PDU evidence, and choose the next check before changing register-map assumptions. ## Prerequisites - Module 9: serial settings and timeout triage. - Module 10 lesson through RS-485 course rules. ## Safety And Scope This is a no-hardware topology exercise. It does not instruct learners to wire real equipment. Optional real-device or adapter labs require selected hardware, device manuals, safe bench power, and instructor review. The diagrams are simplified teaching fixtures. Exact cable, termination resistor, shielding, grounding, surge protection, and isolation choices must come from the device manuals, site standard, and hardware references. ## Scenario A Modbus RTU client polls three meters on an RS-485 2-wire half-duplex segment. All devices are intended to use the same serial settings. Learners receive eight topology cards and must identify the likely failure mode and next evidence to gather. ## Topology Cards Legend: ```text C = client M1/M2/M3 = meters T = trunk-end termination --- = trunk | = derivation/stub ? = unresolved wiring or label evidence ``` Card A: baseline trunk ```text T C --- M1 --- M2 --- M3 T ``` Card B: star topology ```text M1 | C ------+------ M2 | M3 ``` Card C: too many terminations ```text T C --- M1(T) --- M2(T) --- M3 T ``` Card D: no termination documented ```text C --- M1 --- M2 --- M3 No trunk-end terminations documented ``` Card E: long stub ```text T C --- M1 --- M2 T | long derivation to M3 ``` Card F: missing common conductor ```text D0/D1 pair connected through trunk Common conductor not connected or not documented ``` Card G: duplicate serial server IDs ```text T C --- M1(ID 1) --- M2(ID 1) --- M3(ID 3) T ``` Card H: polarity labels unresolved or mismatched ```text Client terminals: A/B Meter terminals: D+/D- Manual pages missing from commissioning folder ``` ## Procedure 1. Classify each card as baseline, topology fault, termination fault, common-conductor issue, identity/configuration issue, or unresolved evidence. 2. Name the likely symptom: no valid response, intermittent response, response from wrong/duplicate server, or needs verification. 3. Choose the next evidence to gather. 4. State what not to change yet. 5. Fill the answer table. ## Worksheet | Card | Classification | Likely Symptom | Next Evidence | What Not To Change Yet | Source Label | |---|---|---|---|---|---| | A | | | | | | | B | | | | | | | C | | | | | | | D | | | | | | | E | | | | | | | F | | | | | | | G | | | | | | | H | | | | | | ## Answer Key | Card | Classification | Likely Symptom | Next Evidence | What Not To Change Yet | Source Label | |---|---|---|---|---|---| | A | Baseline topology | Expected to work if settings, IDs, and wiring details are correct | Confirm actual terminations, common, polarity, settings, and server IDs | Do not assume it works without evidence | Official guide basis plus field verification | | B | Star topology | Reflections/intermittent or no valid response | Draw actual cable path and redesign as trunk with short derivations where needed | Register map, scale, word order | Official guide basis | | C | Too many terminations | Weak signal/intermittent or no valid response | Locate enabled terminations and leave only trunk-end terminations | Function code and PDU address | Official guide basis | | D | No termination documented | Intermittent or no valid response depending on length, speed, and devices | Confirm whether trunk-end termination exists and whether devices include switchable termination | Register map and data type | Official guide basis plus hardware/manual verification | | E | Long stub/derivation | Intermittent response, especially at higher speeds or with noise | Measure derivation length and compare to source-backed limit | Data type and scale | Official guide basis, final length wording pending direct review | | F | Missing common conductor | Intermittent communication or noise sensitivity | Verify common conductor and grounding approach from device manuals/site standard | Register address | Official guide basis plus installation-specific review | | G | Duplicate server IDs | Colliding responses or wrong device responding | Verify every server address is unique on the segment | Baud/parity if other devices work | Official serial addressing plus field verification | | H | Unresolved or mismatched polarity labels | No valid response or intermittent response | Get manuals or perform controlled bench test to map A/B to D+/D- | Do not swap wires repeatedly without evidence | Vendor-specific note / Needs verification | ## Expected Observations - Physical-layer faults often produce no valid response or intermittent response, not clean Modbus exceptions. - A good-looking topology sketch is not proof; learners still need settings, terminations, common, polarity, and server-ID evidence. - Duplicate server IDs are a configuration/identity problem, but the symptom can look like a bus problem. - Polarity labels are implementation-specific and should be verified rather than assumed. ## Troubleshooting Notes - Do not let learners solve every card by changing PDU address. - Keep exact resistor values, shield bonding, surge protection, and isolation out of the answer key until hardware references are selected. - If learners mention 120-ohm termination, ask for the cable/device source rather than accepting it as a universal Modbus rule. - Optional hardware extension should use a verified training bench, not production wiring. ## Check Questions 1. Which cards are physical topology faults? 2. Which card is primarily a serial server identity problem? 3. Why is Card H marked needs verification rather than simply "swap A and B"? 4. Which cards could create timeouts without any Modbus exception response? ## Instructor Notes - Ask learners to separate official serial-line guidance, vendor/manual evidence, and field notes. - Use this lab before Module 11 frame decoding so learners do not confuse CRC failures with topology mistakes. - If teaching with real hardware later, require a written bench plan and stop point before rewiring anything. ## Source Notes - Official source: Modbus over Serial Line Specification and Implementation Guide V1.02 as summarized in `modbus-wiki.md` for RS-485 trunk, derivation, termination, common conductor, node count, and polarization guidance. - Secondary source: hardware application notes listed in `notebooklm-source-list.md` for exact physical-design details before release. - Synthetic source: all topology cards are course-authored teaching diagrams. ## Knowledge check # Module 10 Quiz: RS-232, RS-422, And RS-485 ## Questions ### Multiple Choice 1. Which statement is safest? - A. RS-485 is the Modbus protocol. - B. Modbus RTU and Modbus ASCII are serial transmission modes; RS-232, RS-422, and RS-485 are electrical layers. - C. Modbus TCP requires RS-485 wiring. - D. RS-232 is always multidrop. 2. A passive RS-485 trunk has termination enabled at the client, M1, M2, and the far end. What is the likely issue? - A. Too many terminations. - B. Wrong word order. - C. Illegal function code. - D. Missing MBAP header. 3. A bus has two meters both configured as serial server ID `1`. What should be checked first? - A. Unique server IDs. - B. Scale factor. - C. IEEE-754 byte order. - D. Port 502. 4. Why should A/B or D+/D- polarity labels be treated carefully? - A. The labels are always identical across vendors. - B. They are implementation-specific and should be verified against manuals or controlled tests. - C. They are PDU addresses. - D. They are Modbus exception codes. 5. Which guidance should not be taught as a universal Modbus rule without a hardware source? - A. RS-485 is an electrical layer, not the Modbus PDU. - B. A passive trunk should not have termination at every device. - C. An exact termination resistor value for every cable and device. - D. Duplicate serial server IDs can cause trouble. 6. On a passive RS-485 trunk, where should termination normally be placed? - A. At every device on the bus. - B. Near the two ends of the trunk only. - C. Only at the client, never at the servers. - D. Termination is never needed on RS-485. 7. Following the official serial-line guide as a conservative course anchor, how many standard unit loads does the guide use as the device count for a single RS-485 segment before repeaters or low-unit-load devices are required? - A. 8. - B. 16. - C. 32. - D. 247. ### Short Answer 1. Explain why the same Modbus RTU PDU can have different failure modes over RS-232 and RS-485. 2. List three RS-485 physical-layer checks to make before changing a register address. 3. Why is a star topology risky in an RS-485 Modbus field bus? 4. What source would you need before teaching exact cable, shielding, or termination resistor values? ### Applied Scenario One Modbus RTU client polls three meters on an RS-485 2-wire segment. M1 responds reliably, M2 and M3 are intermittent. A sketch shows a long branch to M3 and termination enabled at M1, M2, and the trunk end. Tasks: 1. Name two likely physical-layer issues. 2. Name one configuration issue to check. 3. State what not to change yet. 4. Label which claims are official serial-line guidance, field notes, or needs verification. ## Answer Key 1. Multiple choice: B. RTU/ASCII define serial Modbus framing; RS-232/422/485 define electrical interfaces. A and C confuse protocol/transport layers, and D is false. 2. Multiple choice: A. The course rule is termination near the two trunk ends, not at every device. Word order, function code, and MBAP are different layers. 3. Multiple choice: A. Duplicate server IDs can cause colliding or confusing responses on a multidrop segment. 4. Multiple choice: B. Polarity labels are vendor/device-specific evidence and should not be assumed universal. 5. Multiple choice: C. Exact resistor values depend on cable/device/hardware references. The other statements are appropriate course-level guidance with source labels. 6. Multiple choice: B. The course rule is termination near the two trunk ends only. Terminating at every device, only at the client, or omitting termination entirely all diverge from that rule. 7. Multiple choice: C. The wiki uses the official guide's 32-unit-load statement as a conservative course anchor for a single segment; higher counts require documented low-unit-load devices or repeaters. `247` is the top serial server address, not a node-count limit. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A confuses electrical layer with protocol, C assigns TCP to serial wiring, and D invents multidrop behavior for RS-232. | | 2 | A | B/C/D are data, function, or TCP framing issues rather than an RS-485 termination issue. | | 3 | A | B/C/D are interpretation or TCP details that do not resolve duplicate serial server IDs on a multidrop bus. | | 4 | B | A overgeneralizes vendor labels, and C/D confuse terminal markings with PDU addresses or exception codes. | | 5 | C | A/B/D are defensible course-level boundaries; C requires named hardware, cable, or installation evidence before becoming a universal rule. | | 6 | B | A over-terminates the bus, C terminates only one node, and D denies that termination is ever needed; the rule is termination near the two trunk ends. | | 7 | C | A/B understate the guide's 32-unit-load anchor, and D confuses the top serial server address (`247`) with a segment device count. | Short answer: 1. The Modbus PDU can be identical, but RS-232 and RS-485 use different electrical interfaces and topologies. RS-485 multidrop faults such as stubs, terminations, polarity labels, common conductor, duplicate IDs, or bus contention do not apply the same way to a short point-to-point RS-232 link. 2. Good answers include trunk shape, termination count/location, common conductor, polarity labels, server IDs, stubs/derivations, bias/polarization source, serial settings, and adapter direction control. 3. A star creates multiple branches rather than one controlled trunk with short derivations; it can create signal integrity and reflection problems. 4. A named device manual, cable/hardware reference, installation standard, or reviewed hardware application note. Applied scenario: 1. Likely physical-layer issues: long branch/stub and too many enabled terminations. 2. Check unique serial server IDs and matching serial settings. 3. Do not change register address, word order, scale, or units until the bus evidence is corrected or ruled out. 4. Official serial-line guidance: trunk/derivation and termination discipline at course level. Field notes: intermittent symptoms and common field failure patterns. Needs verification: exact cable length, resistor values, shielding/grounding, and product-specific terminal labels. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for RS-485 implementation guidance, serial server address range and broadcast address, serial client/server legacy terminology, RTU/ASCII frame fields, CRC/LRC checking, and RTU timing and ASCII framing. - Exact cable, shielding, termination, resistor, surge, isolation, and terminal-label guidance remains hardware-source or vendor-specific until reviewed. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 10/16 · v1.0.0 · Exported for offline / agent use._ # Module 11: RTU & ASCII Frames > Frame structure, CRC vs LRC, silent intervals, and reading captures by hand. **Phase:** Physical Network & Transport **Estimated time:** 7 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/rtu-ascii-frames ## What you'll be able to do - Read an RTU capture byte by byte: address, FC, data, CRC. - Compute a Modbus CRC by hand or with the workbench tool. - Convert between RTU and ASCII framings for the same PDU. ## Three things people get wrong 1. **Writing the CRC high byte first.** Modbus appends CRC low byte then high. CRC = 0x0BC4 goes on the wire as C4 0B. 2. **Including the colon or CRLF in the LRC.** ASCII LRC covers the binary message bytes only — exclude ':' and the trailing CR/LF. 3. **Treating bad CRC as an exception.** A device that sees a bad CRC discards the frame silently. The client sees a timeout, not 83 xx. ## From the field **The CRC that was off by one byte** A homebrew script computed the CRC on the address plus PDU but forgot to include the byte count for FC 17. Every response looked right except the last two bytes. The fix was three lines of code, but the team spent a day blaming the cable. ## References - [Modbus over Serial Line V1.02](https://www.modbus.org/file/secure/modbusoverserial.pdf) — Section 2.5 — frame description ## Lesson # Module 11 Lesson: Modbus RTU And ASCII Frames ## Learner Outcome By the end of this module, learners can label Modbus RTU and Modbus ASCII frames, separate serial server address from PDU address, explain CRC versus LRC at a troubleshooting level, and predict when a bad serial frame produces a timeout instead of a Modbus exception response. ## Key Concepts - Modbus RTU and Modbus ASCII are serial transmission modes. They carry the same PDU shape inside different serial ADUs. - RTU sends binary bytes, uses CRC-16, and relies on silent intervals for frame boundaries. - ASCII sends each byte as two ASCII hex characters, uses LRC, starts with `:`, and ends with CRLF. - The serial server address is part of the serial ADU. It is not the coil/register PDU address. - Individual serial server addresses are `1` through `247`; address `0` is broadcast. - Valid serial broadcast write requests do not receive normal responses. - A CRC, LRC, parity, framing, timing, or unmatched serial-address failure is normally discarded silently and appears as a timeout. A request sent to the wrong active device is different: it may receive a valid response, exception, or plausible wrong data from the wrong server. ## Key Terms - RTU: a binary serial Modbus transmission mode. - ASCII: a serial Modbus transmission mode that represents bytes as ASCII hex characters. - CRC: Cyclic Redundancy Check; the RTU error check sent at the end of the frame. - LRC: Longitudinal Redundancy Check; the ASCII mode error check. - Silent interval: the quiet time used to separate RTU frames. - Serial ADU: the serial address plus PDU plus serial error check. - Broadcast: a serial request to address `0` where valid write requests do not receive normal responses. ## Source-Grounded Explanation The PDU is the Modbus operation. The serial ADU adds the serial address and error check needed on serial links. ```text PDU: Function Code | Data RTU ADU: Address | Function Code | Data | CRC Low | CRC High ASCII ADU: : | Address | Function Code | Data | LRC | CR | LF ``` | Mode | Encoding | Error Check | Boundary Signal | Practical Reading Habit | |---|---|---|---|---| | Modbus RTU | Binary bytes | CRC-16 | Silent interval before and after frame | Label bytes before calculating CRC. | | Modbus ASCII | ASCII hex characters | LRC | Colon start and CRLF end | Convert ASCII pairs back to bytes before interpreting fields. | RTU frames must be transmitted as a continuous stream. The project wiki summarizes the official serial-line guide this way: a silent gap greater than 1.5 character times inside an RTU frame means the receiver should discard the frame as incomplete, and a silent interval of at least 3.5 character times separates frames. At baud rates above 19,200 bps, the guide recommends fixed timing values; final course release should verify exact wording directly against the guide. ASCII framing makes message boundaries visible, but it is still serial Modbus. It still has a serial address, PDU, and error check. It is not Modbus TCP written as text. ## Practical Example: Same PDU, Two Serial ADUs Scenario: Read one holding register from serial server `0x11`. | Field | Example | |---|---| | Transport | Modbus RTU or Modbus ASCII | | Serial server address | `0x11` | | Function code | `0x03` Read Holding Registers | | Documented address | `40010` | | Actual PDU address | `0x0009` | | Quantity | `0x0001` register | | Data type and scale | signed 16-bit, scale `0.1 deg C` | | Expected normal response | address `0x11`, function `0x03`, byte count `0x02`, two data bytes, valid error check | | Likely exception or failure mode | exception `83 02` if the range is unsupported; timeout if CRC/LRC, serial settings, timing, or serial server address is wrong | RTU request before checksum: ```modbus-rtu 11 03 00 09 00 01 ``` RTU request with locally generated CRC bytes: ```modbus-rtu 11 03 00 09 00 01 56 98 ``` ASCII request with locally generated LRC: ```modbus-ascii :110300090001E2\r\n ``` The function code, PDU address, and quantity mean the same thing in both modes. The serial ADU and error check are different. ## Broadcast Example Serial address `0` is broadcast for supported serial broadcast operations. This lesson uses a synthetic broadcast write request because valid serial broadcast write requests do not receive normal responses. Do not teach broadcast reads as a normal lab pattern unless the exact behavior is verified against the serial-line and application protocol specifications. Course fixture: | Field | Value | |---|---| | Transport | Modbus RTU | | Serial address | `0x00` broadcast | | Function code | `0x05` Write Single Coil | | Documented coil | `00020` if the map uses one-based coil notation | | Actual PDU address | `0x0013` | | Write value | `0xFF00` on | | RTU bytes with locally generated CRC | `00 05 00 13 FF 00 7C 2E` | | Expected normal response | none, because this is broadcast | | Safety note | Keep broadcast write examples synthetic unless an instructor-approved simulator is used. | ## Common Pitfalls - Confusing serial server address with PDU register address. - Reading RTU CRC bytes in high-byte/low-byte order instead of wire order: low byte, then high byte. - Treating a bad CRC as an exception-response problem. A bad CRC usually means silent discard and timeout. - Forgetting that ASCII uses the same underlying bytes represented as ASCII hex characters. - Expecting a normal response to a valid serial broadcast write request. - Looking for a CRC in true Modbus TCP traffic. ## Instructor Flow 1. Start with the PDU, then wrap it in RTU and ASCII ADUs. 2. Label address, function, data, and error-check fields before doing arithmetic. 3. Use a request frame, an exception response, and a broadcast write to show three different response expectations. 4. Tie errors back to the three troubleshooting buckets: no valid response, exception response, wrong value. 5. Send learners to the worksheet after they can label the fields without a checksum calculator. ## Check-Your-Understanding 1. In `11 03 00 09 00 01 56 98`, which byte is the serial server address and which bytes are the PDU address? 2. Why does the RTU CRC appear as two bytes at the end of the frame? 3. Why does ASCII mode still need an LRC? 4. Why is "no response" expected for a valid broadcast write? 5. What evidence would move a timeout into function/address troubleshooting? ## Source Notes - Official serial basis: Modbus over Serial Line Specification and Implementation Guide V1.02 for RTU/ASCII modes, serial addressing, broadcast behavior, timing, CRC/LRC fields, and serial defaults. - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for PDU structure, function codes, exception-response shape, and broadcast support boundaries. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, serial server address range and broadcast address, broadcast behavior on serial line, PDU vs ADU and general frame structure, and exception codes and exception response PDU shape. - Local verification basis: checksum examples in this draft were generated with a local Modbus CRC-16/LRC calculation during course build. - Needs verification: final release should compare checksum fixtures against an independent trusted calculator or library and directly review serial-guide timing/broadcast wording. ## Completion Checkpoint Before moving on, learners should label one RTU request, one ASCII request, and one broadcast write expectation. They should explain why a bad CRC/LRC usually appears as timeout/no usable response, not as a Modbus exception response. ## Reusable Assets - [RTU/ASCII frame worksheet](https://learnmodbus.studioseventeen.io/resource/rtu-ascii-frame-worksheet) - [RTU CRC and ASCII LRC verification lab](https://learnmodbus.studioseventeen.io/lesson/rtu-ascii-frames?page=lab-1) - [RTU/ASCII frame lab](https://learnmodbus.studioseventeen.io/lesson/rtu-ascii-frames?page=lab-2) - [Module 11 quiz](https://learnmodbus.studioseventeen.io/lesson/rtu-ascii-frames?page=quiz) - [Serial settings triage checklist](https://learnmodbus.studioseventeen.io/resource/serial-settings-triage-checklist) ## Diagram source ```mermaid flowchart LR subgraph RTU["RTU frame"] A1["Addr"] --> F1["FC"] --> D1["Data"] --> C1["CRC-16"] end subgraph ASCII["ASCII frame"] S[":"] --> A2["Addr"] --> F2["FC"] --> D2["Data"] --> L["LRC"] --> CR["CR LF"] end ``` ## Labs ### Lab 1 # Lab 2: RTU CRC And ASCII LRC Verification ## Learner Outcome Learners can verify a Modbus RTU CRC and Modbus ASCII LRC for known request bytes, explain why the RTU CRC is sent low byte first, and classify a bad checksum as a no-valid-response problem rather than a Modbus exception response. ## Prerequisites - Module 2: PDU and ADU. - Module 4: exception-response shape. - Module 9: serial settings and timeout triage. - Module 11 lesson through CRC/LRC fields. ## Safety And Scope This is a no-hardware worksheet lab. It does not send traffic to any device. The checksum fixtures are covered by the course-owned helper in `tools/modbus_fixture_helper.py`; final paid release should still compare them against one independent trusted calculator, library, or reviewed tool output. ## Scenario A client wants to read two holding registers from serial server `1`, starting at PDU address `0`. Bytes before the RTU CRC or ASCII LRC: ```text 01 03 00 00 00 02 ``` ## Procedure 1. Label the bytes: serial server address, function code, PDU address, and quantity. 2. Verify the RTU CRC bytes on the wire. 3. Verify the ASCII LRC byte. 4. Build the ASCII frame. 5. Classify what happens if the checksum is wrong. ## Auto-Graded Checks ```lab type: crc prompt: Compute the Modbus RTU CRC for the ADU bytes below. Enter both CRC bytes as they go on the wire (low byte first). bytes: 01 03 00 00 00 02 hint: Modbus appends the CRC low byte before the high byte. toolLink: /tools?tab=crc&hex=010300000002 toolLink: /tools?tab=crc&hex=01030000000A ``` ```lab type: lrc prompt: Compute the Modbus ASCII LRC for the same message bytes (exclude the colon and CRLF). bytes: 01 03 00 00 00 02 hint: LRC is the two's complement of the 8-bit sum. ``` ## Worksheet | Item | Learner Answer | |---|---| | Serial server address | | | Function code | | | PDU address | | | Quantity | | | RTU CRC bytes on wire | | | ASCII LRC byte | | | ASCII frame | | | Expected client symptom if CRC/LRC is wrong | | | What not to change yet | | ## Answer Key | Item | Answer | |---|---| | Serial server address | `0x01` | | Function code | `0x03` Read Holding Registers | | PDU address | `0x0000` | | Quantity | `0x0002` registers | | RTU CRC bytes on wire | `C4 0B` | | ASCII LRC byte | `FA` | | ASCII frame | `:010300000002FA\r\n` | | Expected client symptom if CRC/LRC is wrong | timeout or silent discard, not a Modbus exception response | | What not to change yet | documented address, data type, word order, scale, or unit | ## Verification Method For Draft Fixtures - CRC fixture basis: Modbus CRC-16 initialized to `0xFFFF`, polynomial `0xA001`, transmitted low byte then high byte. - LRC fixture basis: two's complement of the 8-bit sum of the message bytes, excluding ASCII `:` and CRLF delimiters. - Course helper evidence: `python3 tools/modbus_fixture_helper.py checksum "01 03 00 00 00 02"` and `python3 tools/modbus_fixture_helper.py self-test`. - Release gate: compare worksheet values against one independent trusted external calculator or library before publishing. ## Expected Observations - The CRC/LRC protects the serial ADU bytes, not the learner's interpretation of scale, unit, or word order. - A bad checksum usually prevents a valid Modbus frame from being accepted. - The receiver normally does not send an exception response for a frame it discards before protocol handling. ## Troubleshooting Notes - If the calculated RTU CRC does not match, re-check byte order on the wire before changing the documented address or quantity. - If the ASCII LRC does not match, confirm that the colon and CRLF delimiters were excluded from the sum. - If the client reports timeout/no usable response, treat checksum/framing as a transport-layer suspect before diagnosing exception codes. - If a learner sees exception `83 02`, that is a parsed Modbus exception response, not the expected symptom of a bad CRC/LRC discard. ## Check Questions 1. Why are the RTU CRC bytes written as `C4 0B` instead of `0B C4` on the wire? 2. Which bytes are included in the ASCII LRC calculation? 3. Why should a bad checksum not lead directly to changing `40001` to another address? ## Instructor Notes - Keep this lab arithmetic-light unless learners need the algorithm. The key professional skill is knowing what a checksum proves and what it does not prove. - Pair this lab with Lab 12 so learners see checksum verification after frame labeling. - Optional extension: add one version-pinned third-party tool command after the lab toolchain is selected. ## Source Notes - Official serial source: Modbus over Serial Line Specification and Implementation Guide V1.02 for CRC/LRC fields and serial frame handling. - Official protocol source: Modbus Application Protocol Specification V1.1b3 for function `03` request meaning. - Synthetic source: request bytes are course-authored fixtures. - Verification note: checksum values are now covered by the course-owned helper self-test and still need independent external release verification. ### Lab 2 # Lab 12: RTU/ASCII Frame Inspection Without Hardware ## Learner Outcome Learners can label RTU and ASCII serial ADU fields, separate serial server address from PDU address, verify whether a checksum belongs to RTU or ASCII, and decide whether the expected result is a normal response, exception response, broadcast silence, or timeout. ## Prerequisites - Module 2: PDU versus ADU. - Module 4: function codes and exception responses. - Module 5: documented address versus PDU address. - Module 9: serial settings and timeout triage. - Module 11 lesson through broadcast behavior. ## Safety And Scope This is a no-hardware paper lab. It uses synthetic course-authored frames and checksum fixtures covered by `tools/modbus_fixture_helper.py`. Do not send broadcast writes to real equipment. Optional simulator or serial-client tracks require an instructor-approved isolated simulator and version-pinned tools. ## Scenario A technician is learning to inspect serial Modbus frames before troubleshooting a real line. Each card includes enough information to label the serial ADU, PDU, and expected result. ## Frame Cards | Card | Frame Evidence | Context | |---|---|---| | A | `01 03 00 00 00 02 C4 0B` | RTU request. Read two holding registers starting at PDU address `0`. | | B | `:010300000002FA\r\n` | ASCII request for the same logical operation as Card A. | | C | `11 83 02 C1 34` | RTU exception response. | | D | `00 05 00 13 FF 00 7C 2E` | RTU broadcast write single coil. | | E | `11 03 00 09 00 01 56 98` | RTU request. Read documented holding register `40010` if the map uses one-based `40001` notation. | | F | `11 03 00 09 00 01 00 00` | Same request bytes as Card E, but with invalid placeholder CRC bytes. | ## Procedure 1. Identify whether each card is RTU or ASCII. 2. Label serial address, function code, PDU address, quantity or value, and error-check field. 3. For request frames, identify documented address when enough context is provided. 4. Predict the expected result: normal response, exception response, broadcast silence, or timeout/silent discard. 5. Explain what not to troubleshoot yet. ## Worksheet | Card | Mode | Serial Address | Function | PDU Data Meaning | Error Check | Expected Result | What Not To Change Yet | |---|---|---|---|---|---|---|---| | A | | | | | | | | | B | | | | | | | | | C | | | | | | | | | D | | | | | | | | | E | | | | | | | | | F | | | | | | | | ## Answer Key | Card | Mode | Serial Address | Function | PDU Data Meaning | Error Check | Expected Result | What Not To Change Yet | |---|---|---|---|---|---|---|---| | A | RTU | `0x01` | `0x03` Read Holding Registers | PDU address `0x0000`, quantity `2` | CRC `C4 0B` on wire | Normal response if server and range are valid | Data type, scale, word order | | B | ASCII | `0x01` | `0x03` Read Holding Registers | PDU address `0x0000`, quantity `2` | LRC `FA` before CRLF | Normal response if server and range are valid | RTU CRC byte order | | C | RTU | `0x11` | `0x83` exception for function `0x03` | Exception code `0x02` Illegal Data Address | CRC `C1 34` on wire | Valid exception response | Baud, parity, CRC, physical wiring unless other evidence appears | | D | RTU | `0x00` broadcast | `0x05` Write Single Coil | PDU address `0x0013`, value `0xFF00` | CRC `7C 2E` on wire | No normal response expected | Do not treat silence alone as a failed response | | E | RTU | `0x11` | `0x03` Read Holding Registers | PDU address `0x0009`, quantity `1`, documented `40010` under one-based notation | CRC `56 98` on wire | Normal response if server and range are valid | Do not change to `40009` without map evidence | | F | RTU | `0x11` | `0x03` Read Holding Registers | Same PDU as Card E | Invalid placeholder CRC `00 00` | Timeout or silent discard likely | Function, PDU address, data type, scale | ## Expected Observations - RTU and ASCII can carry the same PDU meaning with different serial ADUs. - CRC and LRC errors are not Modbus exception responses. - A valid exception response proves a valid Modbus response was received. - Broadcast write silence is expected behavior, not automatically a fault. ## Troubleshooting Notes - Label fields before calculating or checking checksums. - Keep documented references such as `40010` separate from the PDU address bytes. - Treat checksum fixtures as training data until the course-owned helper output is compared against an independent external tool or the final chosen toolchain. - Do not use real broadcast write examples outside an isolated simulator or reviewed training bench. ## Check Questions 1. Which cards carry the same logical read request in different serial modes? 2. Which card is a valid Modbus exception response? 3. Which card should be silent if the request is accepted by servers? 4. Why is Card F a timeout/silent-discard case rather than an exception-response case? ## Instructor Notes - Ask learners to explain why the first byte in RTU/ASCII is not the register address. - Use Card C to reinforce that an exception response is still a response. - Use Card D to keep broadcast behavior and write safety visible. - Helper command: `python3 tools/modbus_fixture_helper.py self-test` verifies the current frame-card checksum constants. - Optional extension: after tool versions are selected, verify these frames with an external calculator/library and add the command output to the release notes. ## Source Notes - Official serial source: Modbus over Serial Line Specification and Implementation Guide V1.02 for RTU/ASCII frame shapes, serial addressing, error checks, timing, and broadcast response behavior. - Official protocol source: Modbus Application Protocol Specification V1.1b3 for function codes, PDU structure, and exception code `02`. - Synthetic source: all frame cards are course-authored teaching fixtures. - Verification note: checksum bytes are covered by the course-owned helper self-test and still need independent external release verification. ## Knowledge check # Module 11 Quiz: Modbus RTU And ASCII Frames ## Questions ### Multiple Choice 1. In the RTU request `11 03 00 09 00 01 56 98`, what is `0x11`? - A. The serial server address. - B. The PDU register address. - C. The CRC high byte. - D. The byte count. 2. Which statement is safest about RTU CRC bytes? - A. They are sent high byte first. - B. They are part of true Modbus TCP. - C. They appear at the end of the RTU ADU on the wire as low byte, then high byte. - D. They replace the function code. 3. Which frame shape describes Modbus ASCII? - A. MBAP header plus PDU. - B. Colon, ASCII hex byte pairs, LRC, CRLF. - C. Silent interval, binary bytes, CRC, silent interval. - D. Ethernet frame with no Unit Identifier. 4. A client sends a valid serial broadcast write to address `0`. What normal response should it expect? - A. Every server responds at once. - B. Only server `1` responds. - C. No normal response. - D. A Modbus TCP MBAP response. 5. A receiver detects a bad CRC in an RTU request. What should the learner expect at the client? - A. Usually timeout or silent discard. - B. Exception code `02` from the receiver. - C. A normal response with byte count `02`. - D. A text ASCII response. 6. On a serial Modbus line, which range covers the individually addressable serial server addresses, and which address is reserved for broadcast? - A. Addresses `0` through `247`, with `248` as broadcast. - B. Addresses `1` through `247`, with `0` as broadcast. - C. Addresses `1` through `255`, with `255` as broadcast. - D. Addresses `0` through `255`, with no broadcast address. 7. In the RTU frame `01 03 00 00 00 02 C4 0B`, what are the last two bytes `C4 0B`? - A. The PDU register address and quantity. - B. The CRC-16, transmitted low byte (`C4`) then high byte (`0B`). - C. The CRC-16, transmitted high byte (`C4`) then low byte (`0B`). - D. An ASCII LRC followed by CRLF. ### Short Answer 1. Explain the difference between serial server address and PDU address. 2. Why should learners label a frame before calculating CRC or LRC? 3. How can the same logical read request appear in both RTU and ASCII? 4. Why is a valid exception response different from a checksum failure? ### Applied Scenario A learner sees this RTU frame: ```text 01 03 00 00 00 02 C4 0B ``` Tasks: 1. Label the serial server address. 2. Label the function code. 3. Label the PDU address and quantity. 4. State the documented holding-register reference if the map uses one-based `40001` notation. 5. Explain what a bad CRC would likely look like to the client. ## Answer Key 1. Multiple choice: A. `0x11` is the serial server address in the serial ADU. The PDU address is `00 09`. 2. Multiple choice: C. RTU CRC bytes are transmitted low byte, then high byte, at the end of the RTU frame. 3. Multiple choice: B. ASCII starts with `:`, carries ASCII hex byte pairs, includes LRC, and ends with CRLF. 4. Multiple choice: C. Valid serial broadcast write requests do not receive normal responses. 5. Multiple choice: A. Bad CRC prevents the receiver from accepting the frame, so the client usually sees timeout or silent discard, not a Modbus exception. 6. Multiple choice: B. Individual serial server addresses are `1` through `247`, and address `0` is broadcast. The other ranges misplace the broadcast address or invent an out-of-range span. 7. Multiple choice: B. `C4 0B` is the RTU CRC-16, transmitted low byte first (`C4`) then high byte (`0B`), so the CRC value is `0x0BC4`. It is not the PDU address/quantity and it is not an ASCII LRC/CRLF. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | A | B is the later PDU register address, C is part of the final CRC field, and D belongs in normal read responses. | | 2 | C | A reverses RTU CRC byte order, B adds serial CRC to true TCP, and D replaces the function code with the wrong field. | | 3 | B | A is Modbus TCP, C is RTU, and D describes Ethernet/TCP framing rather than Modbus ASCII. | | 4 | C | A/B would create response collisions or invent a single responder, and D applies TCP response framing to serial broadcast behavior. | | 5 | A | B would require a valid exception response, C is a normal read response, and D changes the mode to ASCII text. | | 6 | B | A/C/D misplace the broadcast address or use an out-of-range span; only `1`-`247` with `0` broadcast is correct. | | 7 | B | A misreads the CRC field as PDU data, C reverses the wire byte order, and D applies ASCII framing to an RTU frame. | Short answer: 1. The serial server address selects the serial node that should process the request. The PDU address selects the coil/register offset inside the requested function's data area. 2. Labeling fields first prevents learners from treating checksum arithmetic as the whole task. It also catches layer mistakes such as confusing server address, function code, and PDU address. 3. The server address, function code, PDU address, and quantity can be the same underlying bytes, while RTU carries them as binary bytes with CRC and ASCII carries them as ASCII hex characters with LRC and delimiters. 4. A valid exception response is a valid Modbus frame with an exception function and code. A checksum failure means the receiver normally discards the frame before Modbus exception handling. Applied scenario: 1. Serial server address: `0x01`. 2. Function code: `0x03` Read Holding Registers. 3. PDU address: `0x0000`; quantity: `0x0002`. 4. Documented references: holding registers `40001` and `40002` if the map uses one-based `40001` notation. 5. A bad CRC would usually lead to silent discard and client timeout. It should not be diagnosed first as illegal data address, word order, scale, or unit. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, serial server address range and broadcast address, broadcast behavior on serial line, PDU vs ADU and general frame structure, and exception codes and exception response PDU shape. - Current checksum fixtures remain draft until independently verified against a trusted calculator or library. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 11/16 · v1.0.0 · Exported for offline / agent use._ # Module 12: Modbus TCP > MBAP, unit identifiers, ports, and what changes (and doesn't) moving from RTU. **Phase:** Physical Network & Transport **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/modbus-tcp ## What you'll be able to do - Parse the 7-byte MBAP header from a capture. - Explain when Unit ID matters and when 0xFF is fine. - Predict what a Modbus TCP frame for FC 03 looks like end-to-end. ## Three things people get wrong 1. **Appending a CRC over TCP.** TCP handles integrity. No CRC bytes belong in a Modbus TCP frame. 2. **Hard-coding Unit ID 1.** Through a gateway, Unit ID picks the serial address. Hard-coding 1 breaks multi-drop topologies. 3. **Ignoring MBAP length.** Length covers Unit ID + PDU. Mis-calculating it confuses servers that strictly validate. ## From the field **Port 502 is not magic** An IT team blocked port 502 'because it's unencrypted' without realizing the SCADA box used it for every poll. Production trends went flat for an hour. The eventual compromise was a Modbus Security gateway on 802 and a documented allowlist — same protocol, different posture. ## References - [Modbus Messaging on TCP/IP V1.0b](https://www.modbus.org/file/secure/messagingimplementationguide.pdf) — MBAP header — section 4.1 ## Lesson # Module 12 Lesson: Modbus TCP And MBAP ## Learner Outcome By the end of this module, learners can label the Modbus TCP ADU, explain the MBAP header, distinguish true Modbus TCP from RTU-over-TCP, use Transaction Identifier and Unit Identifier evidence correctly, and identify when a TCP-side problem should be handled before changing register-map assumptions. ## Key Concepts - Modbus TCP carries the Modbus PDU over TCP/IP. - True Modbus TCP uses a 7-byte MBAP header and does not include the serial address, RTU CRC, ASCII LRC, or RTU timing gaps. - The MBAP header contains Transaction Identifier, Protocol Identifier, Length, and Unit Identifier. - MBAP fields are big-endian. - TCP port `502` is registered for `mbap`; Modbus Security uses a different TLS-protected service path covered later. - The Unit Identifier matters most through gateways, where it may select a downstream serial server. - TCP connection success does not prove the Unit Identifier, function code, PDU address, quantity, or downstream path is correct. ## Key Terms - MBAP: Modbus Application Protocol header used by Modbus TCP. - Transaction Identifier: MBAP field used to associate a response with a request. - Protocol Identifier: MBAP field that is `0x0000` for Modbus. - Length: MBAP field that counts following bytes, including Unit Identifier plus PDU. - Unit Identifier: MBAP field commonly relevant through gateways; accepted values are product/path-specific. - True Modbus TCP: Modbus PDU carried with an MBAP header and no RTU CRC. - RTU-over-TCP: product/tool-specific transport of serial-style bytes over a TCP socket. ## Source-Grounded Explanation Modbus TCP is not RTU with an Ethernet cable. The PDU still carries the Modbus operation, but the ADU changes: ```text Modbus PDU: Function Code | Data Serial RTU ADU: Address | Function Code | Data | CRC Low | CRC High Modbus TCP ADU: MBAP Header | Function Code | Data ``` MBAP header: | Field | Size | Course Meaning | Source Boundary | |---|---:|---|---| | Transaction Identifier | 2 bytes | Pairs a response with a request. | Official TCP guide; client/server behavior still needs tool examples. | | Protocol Identifier | 2 bytes | `0x0000` for Modbus. | Official TCP guide. | | Length | 2 bytes | Number of following bytes, including Unit Identifier and PDU. | Official TCP guide; learners should count bytes. | | Unit Identifier | 1 byte | Identifies a remote unit, commonly through gateways, or a server-specific unit. | Gateway/native-device behavior is product-specific. | All MBAP fields are big-endian. True Modbus TCP has no Modbus CRC because it relies on TCP/IP transport checks for delivery and integrity at that layer. This is not security: classic Modbus TCP is still plaintext and normally lacks authentication or authorization. ### Unit Identifier The Unit Identifier is a common source of field confusion: - Native Modbus TCP devices may ignore or require specific request Unit Identifier values. Responses should echo the request Unit Identifier, but accepted request values remain vendor/manual-specific. - TCP-to-serial gateways often use it to choose the downstream serial server address. - A wrong Unit Identifier through a gateway can look like a timeout, wrong target, or gateway exception. - The course should not teach one universal Unit Identifier value. Use the device manual, gateway manual, or a controlled test. ### Message Boundaries TCP is a stream. A Modbus TCP receiver should not assume one TCP segment equals one Modbus message. It should use the MBAP Length field and function-specific structure to reconstruct the ADU. For learners, the practical habit is to count from the Unit Identifier through the end of the PDU and compare that count to the Length field. ## Practical Example: Read Holding Register `40010` Scenario: A Modbus TCP client reads one holding register from a simulator or saved byte fixture. Request: ```modbus-tcp 00 2A 00 00 00 06 FF 03 00 09 00 01 ``` | Field | Example Value | |---|---| | Transport | Modbus TCP | | TCP port | `502` registered service name `mbap` | | Transaction Identifier | `0x002A` | | Protocol Identifier | `0x0000` | | Length | `0x0006`, counting Unit Identifier plus PDU bytes that follow | | Unit Identifier | `0xFF` in this fixture | | Function code | `0x03` Read Holding Registers | | Documented address | `40010` if the map uses one-based `40001` notation | | Actual PDU address | `0x0009` | | Quantity | `0x0001` register | | Data type and scale | unsigned 16-bit, scale `/10 V` | Normal response fixture: ```modbus-tcp 00 2A 00 00 00 05 FF 03 02 09 C4 ``` | Response Field | Meaning | |---|---| | Transaction Identifier `0x002A` | Matches the request. | | Protocol Identifier `0x0000` | Modbus. | | Length `0x0005` | Unit Identifier plus function, byte count, and two data bytes. | | Unit Identifier `0xFF` | Echoes the request fixture value. | | Function `0x03` | Normal read response. | | Byte count `0x02` and data `09 C4` | One 16-bit register, raw value `2500`; with the synthetic map scale, this means `250.0 V`. | Exception response fixture: ```modbus-tcp 00 2A 00 00 00 03 FF 83 02 ``` This is a valid Modbus TCP exception response: same transaction, protocol `0`, length `3`, Unit Identifier `0xFF`, exception function `0x83`, and exception code `0x02` Illegal Data Address. ## RTU-Over-TCP Contrast True Modbus TCP: ```modbus-tcp 00 2A 00 00 00 06 FF 03 00 09 00 01 ``` RTU-style bytes sometimes carried over a TCP socket by nonstandard or gateway-specific products: ```modbus-rtu 11 03 00 09 00 01 56 98 ``` The second byte string has a serial address and RTU CRC, not an MBAP header. Some client tools expose a mode such as "RTU over TCP" or "Modbus RTU encapsulated in TCP." Treat that as product/tool behavior and verify it against the gateway or device manual. ## Common Pitfalls - Looking for an RTU CRC in true Modbus TCP traffic. - Treating TCP connection success as proof that the Unit Identifier or downstream gateway path is correct. - Assuming TCP segment boundaries are Modbus message boundaries. - Treating Unit Identifier as irrelevant on every network. - Selecting RTU-over-TCP when the device expects true Modbus TCP, or the reverse. - Treating port `502` as a security control. It is a service port, not authentication. - Changing register addresses when the actual problem is blocked TCP, wrong Unit Identifier, wrong mode, gateway timeout, or a malformed MBAP length. ## Instructor Flow 1. Start with the PDU from Module 11 and wrap it in MBAP instead of RTU or ASCII. 2. Label one request byte string and count the MBAP Length field. 3. Compare normal response and exception response fixtures. 4. Show RTU-over-TCP bytes and ask why they are not true Modbus TCP. 5. Show the offline generated PCAP fixture as optional instructor evidence, but leave Wireshark filters, screenshots, live simulator capture, and PyModbus runs as tool-verified extensions until versions and expected outputs are pinned. ## Check-Your-Understanding 1. Which MBAP field pairs a response with its request? 2. Why does true Modbus TCP not include the RTU CRC? 3. In `00 2A 00 00 00 06 FF 03 00 09 00 01`, what bytes are counted by the Length field? 4. Why might a gateway path fail even when TCP port `502` is open? 5. What clue tells you that `11 03 00 09 00 01 56 98` is not a true Modbus TCP ADU? ## Source Notes - Official TCP basis: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP fields, Modbus TCP ADU structure, connection/gateway concepts, and port `502` usage. - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for PDU structure, function code `03`, exception-response shape, and exception code `02`. - Primary registry basis: IANA Service Name and Transport Protocol Port Number Registry for `mbap` on TCP `502`. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for MBAP header fields, MBAP Length field, Unit Identifier and gateway routing, TCP connection behavior and concurrency, IANA service name `mbap` on port `502`, PDU vs ADU and general frame structure, normal response vs exception response, and exception codes and exception response PDU shape. - Tool behavior: Wireshark display filters, PyModbus behavior, simulator output, and packet-capture screenshots require version-pinned verification before release. - Synthetic source: saved byte fixtures and `fixtures/packet-captures/modbus_tcp_synthetic_v1.pcap` are course-authored examples, not production or real-device traffic. ## Completion Checkpoint Before moving on, learners should count the MBAP Length field, identify the Unit Identifier, separate MBAP from PDU bytes, and explain why true Modbus TCP does not include an RTU CRC. ## Reusable Assets - [Modbus TCP packet inspection worksheet](https://learnmodbus.studioseventeen.io/resource/modbus-tcp-packet-inspection-worksheet) - [Modbus TCP MBAP inspection lab](https://learnmodbus.studioseventeen.io/lesson/modbus-tcp?page=lab-1) - [Generated synthetic PCAP fixture](https://learnmodbus.studioseventeen.io/api/public/fixtures/modbus_tcp_synthetic_v1.pcap) - [Module 12 quiz](https://learnmodbus.studioseventeen.io/lesson/modbus-tcp?page=quiz) - [RTU/ASCII frame worksheet](https://learnmodbus.studioseventeen.io/resource/rtu-ascii-frame-worksheet) ## Diagram source ```mermaid flowchart LR subgraph MBAP["MBAP header"] TI["Tx ID (2)"] --> PI["Proto ID (2)"] --> LN["Length (2)"] --> UI["Unit ID (1)"] end MBAP --> PDU["PDU
FC + data"] ``` ## Labs ### Lab 1 # Lab 5: Modbus TCP MBAP Inspection Without A Capture Tool ## Learner Outcome Learners can inspect saved Modbus TCP byte strings, label MBAP fields, count the Length field, distinguish normal and exception responses, and recognize RTU-over-TCP bytes that are not true Modbus TCP. ## Prerequisites - Module 2: PDU and ADU. - Module 4: function codes and exception responses. - Module 5: documented address versus PDU address. - Module 11: RTU/ASCII frames and CRC/LRC. - Module 12 lesson through MBAP fields. ## Safety And Scope This is a no-hardware and no-network lab. It uses saved byte strings and a synthetic generated PCAP fixture, not live captures. Do not scan networks or connect to production devices. Later Wireshark extensions must use version-pinned tools and expected outputs. ## Scenario A learner receives saved byte strings from a training simulator. The task is to label the Modbus TCP ADU before changing register-map assumptions. ## Packet Cards | Card | Saved Bytes | Context | |---|---|---| | A | `00 2A 00 00 00 06 FF 03 00 09 00 01` | True Modbus TCP request. Read one holding register. | | B | `00 2A 00 00 00 05 FF 03 02 00 FA` | True Modbus TCP normal response. | | C | `00 2A 00 00 00 03 FF 83 02` | True Modbus TCP exception response. | | D | `11 03 00 09 00 01 56 98` | RTU-style bytes carried elsewhere; not true Modbus TCP. | | E | `00 2A 00 00 00 06 FF 03 02 00 FA` | Looks like a response but has a Length mismatch. | | F | `00 2A 00 01 00 06 FF 03 00 09 00 01` | Protocol Identifier is not `0x0000`. | ## Procedure 1. For each card, classify the byte string as true Modbus TCP, Modbus TCP response with a defect, RTU-style bytes, or invalid/needs rejection. 2. Label Transaction Identifier, Protocol Identifier, Length, Unit Identifier, function code, and PDU fields when present. 3. Count the bytes covered by the MBAP Length field. 4. Predict the diagnostic bucket: normal response, exception response, malformed/invalid ADU, wrong mode, or needs tool/device evidence. 5. State what not to change yet. ## Worksheet | Card | Classification | Transaction ID | Protocol ID | Length Check | Unit ID | PDU Meaning | Expected Result | What Not To Change Yet | |---|---|---|---|---|---|---|---|---| | A | | | | | | | | | | B | | | | | | | | | | C | | | | | | | | | | D | | | | | | | | | | E | | | | | | | | | | F | | | | | | | | | ## Answer Key | Card | Classification | Transaction ID | Protocol ID | Length Check | Unit ID | PDU Meaning | Expected Result | What Not To Change Yet | |---|---|---|---|---|---|---|---|---| | A | True Modbus TCP request | `0x002A` | `0x0000` | `6` bytes: Unit ID + function + address + quantity | `0xFF` | FC `03`, PDU address `0x0009`, quantity `1` | normal response or exception depending on server/map | data type, scale, word order | | B | True Modbus TCP normal response | `0x002A` | `0x0000` | `5` bytes: Unit ID + function + byte count + two data bytes | `0xFF` | FC `03`, byte count `2`, raw `00 FA` | valid normal response | TCP mode, Unit ID, address if value is plausible | | C | True Modbus TCP exception response | `0x002A` | `0x0000` | `3` bytes: Unit ID + exception function + code | `0xFF` | exception function `83`, code `02` Illegal Data Address | valid exception response | TCP port, CRC, physical serial wiring | | D | RTU-style bytes, not true Modbus TCP | none | none | no MBAP header | serial address `0x11`, not Unit ID | FC `03`, PDU address `0x0009`, quantity `1`, RTU CRC `56 98` | wrong mode if expected true Modbus TCP | MBAP Unit ID or Length, because there is no MBAP | | E | Defective Modbus TCP-like response | `0x002A` | `0x0000` | says `6`, but only `5` bytes follow | `0xFF` | FC `03`, byte count `2`, raw `00 FA` | malformed/invalid ADU evidence | register address and scale | | F | Invalid/unsupported for Modbus TCP fixture | `0x002A` | `0x0001` | length would otherwise count | `0xFF` | FC `03`, PDU address `0x0009`, quantity `1` | protocol ID is not Modbus `0` | Unit ID and register map until protocol ID is resolved | ## Expected Observations - A true Modbus TCP ADU starts with an MBAP header, not a serial server address and CRC. - A valid exception response is still a Modbus response. - The Length field gives a fast way to catch malformed byte strings. - Unit Identifier evidence matters most when a gateway or product manual says it matters. ## Troubleshooting Notes - TCP connection success does not prove the Modbus ADU is valid. - If the Protocol Identifier is not `0`, stay in the packet/protocol evidence layer. - If the byte string is RTU-over-TCP, switch the client/tool mode or verify the gateway manual before changing register addresses. - Keep Wireshark display-filter names out of the answer key until verified against the course toolchain. ## Check Questions 1. Which card is a normal Modbus TCP response? 2. Which card proves an exception response can still be a valid Modbus response? 3. Which card is RTU-style framing rather than true Modbus TCP? 4. Which card has a bad Length field? 5. Why should a wrong Unit Identifier be considered before changing PDU address through a TCP-to-serial gateway? ## Instructor Notes - Ask learners to count Length aloud from Unit Identifier through the PDU. - Use Card D to connect Module 11 and Module 12 without blending the two modes. - Optional generated PCAP fixture: `fixtures/packet-captures/modbus_tcp_synthetic_v1.pcap`. - Add a Wireshark version-pinned extension only after `packet-capture-lab-notes.md` and [Packet Tool Evidence Appendix](https://learnmodbus.studioseventeen.io/resource/packet-tool-evidence-appendix) contain verified field names, fixture hash evidence, expected-output comparison, and screenshots. ## Source Notes - Official TCP source: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP fields and TCP ADU structure. - Official protocol source: Modbus Application Protocol Specification V1.1b3 for function `03`, exception response shape, and exception code `02`. - Primary registry source: IANA service-name registry for TCP `502` service name `mbap`. - Synthetic source: packet cards and `fixtures/packet-captures/modbus_tcp_synthetic_v1.pcap` are course-authored fixtures, not captured production or real-device traffic. ## Knowledge check # Module 12 Quiz: Modbus TCP And MBAP ## Questions ### Multiple Choice 1. Which fields are in the MBAP header? - A. Serial address, function code, data, CRC. - B. Transaction Identifier, Protocol Identifier, Length, Unit Identifier. - C. Colon, ASCII hex, LRC, CRLF. - D. Scale, unit, word order, quality. 2. In `00 2A 00 00 00 06 FF 03 00 09 00 01`, what does Length `0x0006` count? - A. The whole Ethernet frame. - B. The following bytes: Unit Identifier plus the PDU. - C. Only the function code. - D. The RTU CRC. 3. Which statement is safest about true Modbus TCP? - A. It includes the RTU CRC after the PDU. - B. It always ignores the Unit Identifier. - C. It carries an MBAP header plus PDU and has no serial CRC/LRC. - D. It is secure because it uses port `502`. 4. A TCP-to-serial gateway accepts a TCP connection on port `502`, but the downstream serial device does not answer. Which field should be checked before changing the register address? - A. Unit Identifier. - B. Word order. - C. Engineering-unit scale. - D. ASCII LRC. 5. Which byte string is not true Modbus TCP? - A. `00 2A 00 00 00 06 FF 03 00 09 00 01` - B. `00 2A 00 00 00 05 FF 03 02 00 FA` - C. `11 03 00 09 00 01 56 98` - D. `00 2A 00 00 00 03 FF 83 02` 6. In the Modbus TCP request `00 2A 00 00 00 06 FF 03 00 09 00 01`, which labeling of the MBAP header bytes is correct? - A. Transaction Identifier `00 2A`, Protocol Identifier `00 00`, Length `00 06`, Unit Identifier `FF`. - B. Unit Identifier `00 2A`, Length `00 00`, Protocol Identifier `00 06`, Transaction Identifier `FF`. - C. Protocol Identifier `00 2A`, Transaction Identifier `00 00`, Unit Identifier `00 06`, Length `FF`. - D. Serial address `00`, function code `2A`, CRC `00 00`, Length `00 06`. 7. In a true Modbus TCP MBAP header, what value should the Protocol Identifier carry, and which registered TCP port does the service use? - A. Protocol Identifier `0x0006`, port `102`. - B. Protocol Identifier `0xFFFF`, port `44818`. - C. Protocol Identifier `0x0000`, port `502`. - D. Protocol Identifier equal to the Transaction Identifier, port `502`. ### Short Answer 1. Explain why true Modbus TCP has no RTU CRC. 2. Explain what Transaction Identifier is used for. 3. Give one native-device and one gateway reason why Unit Identifier handling must be verified. 4. Why should learners count the MBAP Length field before interpreting a value? ### Applied Scenario A learner sees this saved Modbus TCP byte string: ```text 00 2A 00 00 00 05 FF 03 02 00 FA ``` Tasks: 1. Label the Transaction Identifier. 2. Label the Protocol Identifier. 3. Explain why the Length field is `0x0005`. 4. Label the Unit Identifier. 5. Classify the response as normal, exception, malformed, or wrong mode. 6. Explain what not to change yet. ## Answer Key 1. Multiple choice: B. MBAP contains Transaction Identifier, Protocol Identifier, Length, and Unit Identifier. 2. Multiple choice: B. Length counts the bytes following the Length field: Unit Identifier plus PDU. 3. Multiple choice: C. True Modbus TCP carries MBAP plus PDU and does not include serial CRC/LRC. Port `502` is not a security control. 4. Multiple choice: A. Through a TCP-to-serial gateway, Unit Identifier often selects the downstream serial server. 5. Multiple choice: C. `11 03 00 09 00 01 56 98` is RTU-style framing with serial address and CRC, not true Modbus TCP. 6. Multiple choice: A. The MBAP header is Transaction Identifier `00 2A`, Protocol Identifier `00 00`, Length `00 06`, Unit Identifier `FF`, followed by the PDU `03 00 09 00 01`. The other options scramble field order or apply serial RTU framing to a TCP ADU. 7. Multiple choice: C. The Protocol Identifier is `0x0000` for Modbus, and the registered service `mbap` uses TCP port `502`. `0x0006` is this frame's Length, `0xFFFF` is not a valid Protocol Identifier, and ports `102`/`44818` belong to other protocols. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A is serial RTU framing, C is ASCII framing, and D is source-map meaning rather than MBAP structure. | | 2 | B | A counts outside Modbus TCP ADU semantics, C ignores the rest of the bytes after Length, and D adds a serial error check not present in true TCP. | | 3 | C | A adds RTU CRC to true TCP, B overgeneralizes Unit Identifier handling, and D treats port `502` as security. | | 4 | A | B/C are value interpretation details, and D is an ASCII check byte rather than a TCP gateway routing field. | | 5 | C | A/B/D are valid MBAP plus PDU shapes; C is serial-style framing without an MBAP header. | | 6 | A | B/C shuffle the MBAP field order, and D reads the TCP ADU as an RTU frame with serial address and CRC. | | 7 | C | A uses the Length value as the Protocol Identifier and the wrong port, B invents an invalid Protocol Identifier and port, and D confuses Protocol Identifier with Transaction Identifier. | Short answer: 1. True Modbus TCP relies on TCP/IP transport checks for delivery/integrity at that layer and uses MBAP length/framing instead of RTU timing and CRC. This does not make it authenticated or encrypted. 2. Transaction Identifier pairs a response with its request, especially when multiple requests or connections may be active. 3. Native devices may ignore, require, or document a fixed Unit Identifier; gateways may use Unit Identifier to route to a downstream serial server. 4. A wrong Length field can indicate malformed bytes or wrong mode. Interpreting data values before confirming the ADU shape can send troubleshooting into the wrong layer. Applied scenario: 1. Transaction Identifier: `0x002A`. 2. Protocol Identifier: `0x0000`. 3. Length `0x0005` counts `FF 03 02 00 FA`: Unit Identifier, function, byte count, and two data bytes. 4. Unit Identifier: `0xFF`. 5. Normal Modbus TCP read response. 6. Do not change TCP mode, Unit Identifier, PDU address, data type, word order, scale, or unit without a symptom. First record the raw value `00 FA` and decode it against the source map. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for MBAP header fields, MBAP Length field, Unit Identifier and gateway routing, TCP connection behavior and concurrency, IANA service name `mbap` on port `502`, PDU vs ADU and general frame structure, normal response vs exception response, exception codes and exception response PDU shape, and RTU/ASCII frame fields where true TCP is contrasted with serial framing. - Saved byte strings remain course-authored fixtures until packet-capture and tool-version evidence is pinned. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 12/16 · v1.0.0 · Exported for offline / agent use._ # Module 13: Gateways & Mixed Networks > TCP↔RTU routing, unit IDs, latency, and how to keep mixed deployments diagnosable. **Phase:** Integration & Real Systems **Estimated time:** 11 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/gateways-mixed-networks ## What you'll be able to do - Route a TCP request to a serial server using the Unit ID. - Predict gateway-induced latency and exception behavior. - Diagnose 'works in dev, fails through the gateway' problems. ## Three things people get wrong 1. **Assuming the gateway forwards exceptions verbatim.** Some gateways synthesize their own exceptions on timeout. The exception code may not match the device's behavior. 2. **Polling faster than the slowest serial bus.** The serial side has a max throughput. Over-polling causes queueing and gateway-side timeouts. 3. **Reusing Unit ID 1 for two devices.** Each device behind the gateway needs a unique Unit ID — this is the gateway's only addressing handle. ## From the field **The gateway with a 50 ms quiet window** A perfectly working integration started timing out after a firmware bump. The new gateway enforced a 50 ms gap between RTU polls; the SCADA was issuing back-to-back reads. Spacing the polls fixed it; the lesson was to always profile the actual round-trip after a gateway change. ## References - [Modbus gateway design patterns (Modbus.org wiki)](https://modbus.org/) ## Lesson # Module 13 Lesson: Gateways And Mixed Networks ## Learner Outcome By the end of this module, learners can trace a Modbus request through a mixed TCP and serial path, explain how the Unit Identifier may affect gateway routing, distinguish transparent routing from mapped gateway behavior, and classify gateway failures without treating product-specific behavior as a universal Modbus rule. ## Key Concepts - A gateway connects different Modbus transports while preserving the Modbus PDU concept. - True Modbus TCP uses an MBAP header and does not include an RTU address byte or RTU CRC. - A TCP-to-RTU gateway may use the MBAP Unit Identifier as a downstream serial server address. - Some gateways use mapping tables, internal device profiles, cached values, or agent-style polling instead of transparent forwarding. - Gateway exceptions `0A` and `0B` are valid Modbus exception responses, not the same thing as client-side silence. - Polling through a gateway must account for downstream serial timing, retries, map gaps, read quantity limits, data freshness, and bus load. ## Key Terms - Gateway: a device or software path that bridges transports, routes requests, maps addresses, or exposes downstream devices. - Transparent routing: gateway behavior where the upstream request is forwarded with minimal application-level mapping. - Mapped routing: gateway behavior where a route table, profile, or internal mapping changes how requests reach downstream targets. - Downstream serial server: the serial-side Modbus server reached through a gateway. - Cache/freshness: whether returned data is current or stored by the gateway. - Gateway exception: a Modbus exception response related to gateway path or downstream target behavior. ## Source-Grounded Explanation ### The Gateway Boundary The Modbus PDU is the function code plus data. Each transport wraps that PDU differently: ```text Modbus TCP side: MBAP Header | Function Code | Data Serial RTU side: Server Address | Function Code | Data | CRC Low | CRC High ``` A TCP-to-RTU gateway sits at that boundary. It receives a Modbus TCP ADU, uses routing configuration such as the Unit Identifier or a mapping table, builds a serial request, waits for the downstream serial response, then returns a Modbus TCP response to the upstream client. The PDU may be the same operation on both sides, but the wrapper is not the same. If a client tool sends RTU-over-TCP bytes to a gateway expecting true Modbus TCP, the problem is the selected mode, not the register map. ### Unit Identifier And Route Evidence The Unit Identifier is part of the Modbus TCP MBAP header. It is not a generic documentation prefix and it is not the same thing as the `4xxxx` holding-register notation. Gateway paths commonly use the Unit Identifier to select a downstream serial server. For example, Unit Identifier `7` may route to downstream RTU server address `7`. That is a common gateway pattern, not a protocol guarantee for every product. Use this evidence hierarchy: | Evidence | What It Can Prove | Source Boundary | |---|---|---| | TCP request bytes | Transaction Identifier, Protocol Identifier, Length, Unit Identifier, function code, PDU address, and quantity. | Official TCP guide for field meanings; synthetic fixture unless captured. | | Gateway route table or manual | Whether Unit Identifier maps directly to a downstream server, a table entry, or an internal profile. | Vendor-specific note for the selected gateway. | | Downstream serial capture or gateway log | Which RTU server address, function, address, quantity, and CRC the gateway emitted. | Lab/tool evidence; not generic unless repeated by source. | | TCP response bytes | Whether the client received a normal response, Modbus exception response, or no response before timeout. | Official protocol for response shape; gateway reason may be product-specific. | Some manuals or tools may call the downstream route value a device ID, slave ID, server ID, unit ID, or address. In this course, use `Unit Identifier` for the MBAP byte and `downstream serial server address` for the RTU/ASCII address. Mention legacy `slave ID` only when reading older manuals or tool labels. ### Transparent Versus Mapped Gateways Gateway behavior belongs in one of three buckets until the selected product manual proves otherwise: | Gateway Pattern | Practical Meaning | Learner Question | |---|---|---| | Transparent routing | The gateway uses the TCP Unit Identifier as the downstream serial address and forwards the PDU with minimal application-level mapping. | Does Unit Identifier `7` actually generate a serial request to address `7`? | | Mapped routing | The gateway uses a route table, address map, tag map, or device profile to choose the downstream request. | What configured map turns the client's request into the downstream request? | | Cached or agent behavior | The gateway or data agent may poll downstream devices separately and answer upstream reads from stored values. | What proves the value is fresh and tied to the current downstream state? | Do not teach cache age, timeout defaults, concurrent-client limits, or mapping-table rules as generic Modbus facts. Those are product or lab-configuration facts. ### Gateway Exceptions The Modbus application protocol includes gateway-related exception codes: | Exception | Name | Practical Meaning | |---:|---|---| | `0A` | Gateway Path Unavailable | The gateway could not allocate or use the path needed for the request. | | `0B` | Gateway Target Device Failed To Respond | The gateway processed the upstream request but did not receive the expected response from the downstream target. | Exception `0B` is different from a client-side timeout. With `0B`, the gateway sent a valid Modbus exception response. With a timeout, the upstream client received no valid response before its own deadline. ### Timeout And Polling Strategy Mixed networks have a timing chain: ```text TCP client timeout must allow for gateway queueing + serial transmission + downstream response time + retries + gateway response ``` The upstream client timeout should be long enough for the gateway to finish the downstream attempt and return a normal response or a gateway exception. Numeric timeout values must come from the selected gateway manual, downstream device manual, lab configuration, or measured capture evidence. Polling design also changes through a gateway. A fast Ethernet client can overload one half-duplex serial trunk if it polls too many devices, too many registers, or too many clients at once. Group reads by device, function, register-map continuity, update rate, safety impact, data type, and freshness requirement. ## Practical Example: Transparent TCP-To-RTU Routing Scenario: A SCADA client reads a temperature value through a TCP-to-RTU gateway. | Item | Value | |---|---| | Upstream transport | Modbus TCP | | Downstream transport | Modbus RTU over RS-485 | | Gateway IP | `192.0.2.50` documentation example address | | TCP port | `502` for classic Modbus TCP | | Unit Identifier | `7`, intended downstream RTU server address | | Function code | `03` Read Holding Registers | | Documented register | Holding register `40021` | | Actual PDU address | `0x0014` if the map uses one-based `40001` notation | | Quantity | `2` registers | | Data type | 32-bit signed integer, high word first | | Scale/unit | `0.1 deg C` | | Expected normal response | Function `03`, byte count `4`, two registers of data | | Likely exception/failure mode | `0B` if downstream server `7` does not respond; client timeout if the gateway is unreachable; `02` if the address/range is invalid | Request path: 1. The TCP client sends an MBAP header with Unit Identifier `7`, then PDU `03 00 14 00 02`. 2. The gateway route configuration decides whether Unit Identifier `7` maps to downstream server address `7`. 3. In a transparent routing fixture, the gateway builds RTU request `07 03 00 14 00 02` plus CRC. 4. The downstream RTU server responds with function `03`, byte count `4`, and two register values. 5. The gateway removes the serial CRC, wraps the response PDU in a Modbus TCP ADU, and returns it with the matching Transaction Identifier and Unit Identifier. If the response contains plausible bytes but the engineering value is wrong, stay in the data-representation layer: address base, register order, signedness, scale, unit, word order, or freshness may be the issue. Do not blame the gateway path until route and response evidence says so. ## Common Pitfalls - Treating the Unit Identifier as irrelevant when it actually selects the downstream serial server. - Treating Unit Identifier routing as universal when the gateway uses a mapping table. - Selecting RTU-over-TCP in a client when the gateway expects true Modbus TCP. - Looking for an RTU CRC inside the true Modbus TCP payload. - Misreading exception `0B` as the same thing as upstream client timeout. - Assuming a successful Modbus response proves the value is fresh when a cache or agent mode may be involved. - Polling multiple upstream clients as if one gateway creates unlimited serial bandwidth. - Reading across reserved map gaps and treating exception `02` as a gateway failure. - Using one timeout value for every downstream path without checking serial speed, retries, and response time. ## Instructor Flow 1. Start with the Module 12 MBAP packet and ask what the Unit Identifier might mean in a gateway path. 2. Draw the same PDU inside two envelopes: MBAP on the TCP side and address/CRC on the RTU side. 3. Compare transparent routing, mapped routing, and cached or agent-style behavior. 4. Classify `0A`, `0B`, `02`, client timeout, stale value, and wrong mode using evidence cards. 5. Keep product-specific settings gated until a selected gateway manual or emulator path is reviewed. ## Check-Your-Understanding 1. A client receives Modbus exception `0B` from a gateway. What evidence does that provide that a client-side timeout does not? 2. Why is Unit Identifier `7` not enough by itself to prove the gateway used downstream serial server address `7`? 3. What is the difference between true Modbus TCP and RTU-over-TCP at the gateway boundary? 4. Why might a syntactically valid Modbus response still contain stale data? 5. What source should govern numeric timeout defaults for a real gateway integration? ## Source Notes - Official TCP basis: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP header fields, Unit Identifier context, and Modbus TCP ADU structure. - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for function code `03`, exception-response shape, and exception codes including `0A` and `0B`. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for MBAP header fields, Unit Identifier and gateway routing, TCP connection behavior and concurrency, IANA service name `mbap` on port `502`, RTU/ASCII frame fields where gateway paths bridge to serial, normal response vs exception response, and exception codes and exception response PDU shape. - Internal course basis: `course-phase-drafts/phase-4-integration-troubleshooting-real-systems.md`, `modbus-wiki.md`, and `gateway-source-notes.md`. - Vendor-specific basis: transparent routing, mapped routing, cache/freshness behavior, timeout defaults, retry settings, broadcast handling, and concurrent-client limits require a selected gateway manual or verified emulator before release. - Synthetic source: the worked example and gateway routing cards are course-authored fixtures, not captured traffic from a real gateway. ## Completion Checkpoint Before moving on, learners should trace one request from TCP client, through gateway route decision, to downstream target, then classify which parts are official Modbus evidence and which parts require selected gateway evidence. ## Reusable Assets - [Gateway routing lab](https://learnmodbus.studioseventeen.io/lesson/gateways-mixed-networks?page=lab-1) - [Gateway routing checklist](https://learnmodbus.studioseventeen.io/resource/gateway-routing-checklist) - [Gateway Evidence Appendix](https://learnmodbus.studioseventeen.io/resource/gateway-evidence-appendix) - [Module 13 quiz](https://learnmodbus.studioseventeen.io/lesson/gateways-mixed-networks?page=quiz) - [Modbus TCP packet inspection worksheet](https://learnmodbus.studioseventeen.io/resource/modbus-tcp-packet-inspection-worksheet) ## Diagram source ```mermaid flowchart LR SC["SCADA
(TCP client)"] -- "TCP : Unit 5" --> G["Gateway"] G -- "RTU : Addr 5" --> D1["Drive"] G -- "RTU : Addr 12" --> D2["Meter"] ``` ## Labs ### Lab 1 # Lab 15: Gateway Routing Without Hardware ## Learner Outcome Learners can trace a Modbus TCP request through a synthetic TCP-to-RTU gateway path, identify route evidence, distinguish transparent and mapped behavior, and classify gateway-related failures before changing register addresses or data types. ## Prerequisites - Module 5: documented address versus PDU address. - Module 11: RTU frame structure and serial server address. - Module 12: Modbus TCP MBAP fields and Unit Identifier. - Module 13 lesson through gateway exceptions and routing patterns. ## Safety And Scope This is a no-hardware and no-network lab. It uses course-authored routing cards, not a live gateway. Do not scan networks or connect to production devices. Later emulator or real-gateway extensions must use an isolated lab network, named gateway documentation, expected outputs, and the [Gateway Evidence Appendix](https://learnmodbus.studioseventeen.io/resource/gateway-evidence-appendix). ## Scenario A client is configured to read holding register `40021` through a TCP-to-RTU gateway. The learner receives saved upstream bytes, route notes, and observed outcomes. The task is to classify each attempt and name the next evidence-producing check. Base request: | Field | Value | |---|---| | Transport to gateway | Modbus TCP | | Downstream transport | Modbus RTU over RS-485 | | Gateway IP | `192.0.2.50` documentation example address | | TCP port | `502` | | Function code | `03` Read Holding Registers | | Documented register | `40021` | | Actual PDU address | `0x0014` | | Quantity | `2` registers | | Data type | 32-bit signed integer | | Scale/unit | `0.1 deg C` | ## Gateway Routing Cards | Card | Upstream Request PDU Context | Route Evidence | Observed Result | Question | |---|---|---|---|---| | A | Unit Identifier `7`, PDU `03 00 14 00 02` | Transparent route note says Unit ID `7` maps to downstream serial server `7`; simulated downstream request is `07 03 00 14 00 02` plus CRC. | Normal TCP response with function `03`, byte count `4`, two registers. | What proves this was a successful gateway path? | | B | Unit Identifier `8`, same PDU | Transparent route note says Unit ID `8` maps to downstream serial server `8`; downstream target is offline in the fixture. | Modbus TCP exception response with function `83`, exception `0B`. | Why is this not the same as a client timeout? | | C | Unit Identifier `7`, same PDU | No gateway response bytes are observed before the client deadline. | Client-side timeout. | What evidence is missing compared with Card B? | | D | Unit Identifier `7`, PDU `03 00 2F 00 08` | Gateway routes to downstream server `7`; selected range crosses a synthetic reserved gap. | Exception response with function `83`, exception `02`. | Why is this not automatically a gateway-path problem? | | E | Unit Identifier `3`, PDU `03 00 14 00 02` | Gateway mapping table says TCP Unit ID `3` and address range `0x0014-0x0015` route to downstream server `7`. | Normal TCP response with mapped-route note. | Why would transparent Unit ID assumptions be wrong here? | | F | Unit Identifier `7`, same PDU | Gateway cache note says value may be served from stored data when downstream polling is stale. | Normal TCP response plus stale-quality note in the scenario. | Why is this a freshness problem rather than a packet syntax problem? | | G | Client sends `07 03 00 14 00 02` plus RTU CRC over TCP. | Gateway expects true Modbus TCP with MBAP, not RTU-over-TCP. | No valid Modbus TCP response in the fixture. | Which client mode should be checked first? | | H | Unit Identifier `7`, same PDU | Gateway downstream attempt is still in progress when the upstream client timeout expires. | Client timeout in first run; normal or `0B` response after timeout alignment is corrected in the scenario. | What settings must be compared before choosing a numeric timeout? | | I | Unit Identifier `9`, same PDU | Gateway route note says no path is available for Unit ID `9` in the fixture. | Modbus TCP exception response with function `83`, exception `0A`. | What route/path evidence should be checked before changing the register map? | ## Procedure 1. For each card, identify the upstream transport, Unit Identifier, function code, documented register, PDU address, and quantity. 2. Decide whether the route looks transparent, mapped, cached/agent-style, wrong-mode, or unresolved. 3. Classify the observed result as normal response, exception `0A`, exception `0B`, exception `02`, client-side timeout, stale-value risk, or wrong mode. 4. Write the next evidence-producing check, such as route table, downstream serial capture, gateway log, timeout chain, cache/freshness setting, or client mode. 5. Record what not to change yet. ## Worksheet | Card | Route Pattern | Diagnostic Bucket | Evidence Used | Next Check | What Not To Change Yet | |---|---|---|---|---|---| | A | | | | | | | B | | | | | | | C | | | | | | | D | | | | | | | E | | | | | | | F | | | | | | | G | | | | | | | H | | | | | | | I | | | | | | ## Answer Key | Card | Route Pattern | Diagnostic Bucket | Evidence Used | Next Check | What Not To Change Yet | |---|---|---|---|---|---| | A | Transparent routing fixture | Normal response | Unit ID `7`, route note, downstream request to server `7`, normal response | Confirm response Transaction ID and Unit ID; decode value using map | scale, word order, timeout | | B | Transparent routing fixture | Gateway exception `0B` | Valid TCP exception response from gateway | Check downstream device power/address/serial settings and gateway log | upstream TCP reachability; it responded | | C | Unresolved path | Client-side timeout | No valid response bytes before client deadline | Check gateway reachability, firewall, client timeout, gateway queue, and route | exception-code interpretation; no exception was received | | D | Transparent route with invalid range | Exception `02` | Gateway routed, downstream or mapped target rejected address/range | Check register-map gap, address base, quantity, and read grouping | gateway reachability and RTU-over-TCP mode | | E | Mapped routing fixture | Normal mapped response | Mapping table overrides direct Unit ID assumption | Inspect configured route table and document mapping evidence | assuming Unit ID equals downstream server address | | F | Cached or agent-style fixture | Stale-value risk | Normal response plus scenario freshness note | Check timestamp, quality, cache age, and downstream live comparison | packet syntax and CRC; response can be syntactically valid | | G | Wrong mode | RTU-over-TCP versus true Modbus TCP mismatch | RTU-style bytes instead of MBAP header | Select true Modbus TCP mode or verify gateway manual for RTU-over-TCP support | PDU address, scale, word order | | H | Timeout-chain mismatch | Client timeout before gateway completes downstream attempt | Scenario says gateway attempt outlasts upstream client timeout | Compare client timeout, gateway serial timeout, retries, serial speed, and downstream response time | inventing a generic numeric timeout | | I | Unavailable gateway path fixture | Gateway exception `0A` | Valid TCP exception response from gateway | Check gateway route availability, path configuration, route table, and product diagnostics | register address, scale, word order | ## Expected Observations - Unit Identifier can be route evidence, but gateway configuration decides whether it maps directly to a downstream serial address. - Exception `0B` means the gateway produced a valid Modbus exception response about the downstream target. - Exception `0A` means the gateway reported path availability evidence, not a decoded-value problem. - A client timeout means the client saw no valid response before its deadline. - Exception `02` can indicate an address/range problem even through a gateway. - A normal response may still require freshness checks when caching or agent behavior is in play. - Wrong TCP mode should be fixed before register-map or data-type troubleshooting. ## Troubleshooting Notes - Keep `Unit Identifier`, downstream serial server address, and legacy `slave ID` labels separate in notes. - Treat mapping tables, cache behavior, retry counts, timeout defaults, and concurrent-client limits as selected-gateway facts, not generic Modbus facts. - Do not assign numeric timing values until the gateway manual, downstream device manual, and lab configuration are known. - If a later emulator is selected, preserve these cards as pre-lab reasoning before live testing. ## Check Questions 1. Which card proves the difference between exception `0B` and a client timeout? 2. Which card shows why Unit Identifier does not always equal downstream serial server address? 3. Which card is a true Modbus TCP versus RTU-over-TCP mode problem? 4. Which card should send you to freshness or quality evidence instead of packet syntax? 5. Which card should send you to address range and read grouping evidence? 6. Which card should send you to route/path availability evidence? ## Instructor Notes - Ask learners to draw Card A as two wrappers around the same PDU: MBAP on the TCP side and address/CRC on the RTU side. - Use Card E to prevent over-learning the transparent routing shortcut. - Use Cards B and C side by side to separate valid exception response from silence. - Use Card H to reinforce timeout chains without teaching made-up default values. ## Source Notes - Official TCP source: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP fields and Modbus TCP ADU structure. - Official protocol source: Modbus Application Protocol Specification V1.1b3 for function `03`, exception response shape, exception `02`, exception `0A`, and exception `0B`. - Internal course source: `gateway-source-notes.md` for candidate gateway behaviors and verification gates. - Synthetic source: all cards are course-authored fixtures, not captured gateway traffic. - Release gate: product-specific behavior requires a selected gateway manual or verified emulator plus the [Gateway Evidence Appendix](https://learnmodbus.studioseventeen.io/resource/gateway-evidence-appendix) before this lab becomes learner-release-ready. ## Knowledge check # Module 13 Quiz: Gateways And Mixed Networks ## Questions 1. A Modbus TCP client sends Unit Identifier `7` to a TCP-to-RTU gateway. Which statement is safest? A. Unit Identifier `7` always proves the downstream RTU server address is `7`. B. Unit Identifier `7` may be route evidence, but the gateway manual or route table must confirm how it is used. C. Unit Identifier is only a documentation prefix like `40001`. D. Unit Identifier is ignored by all gateways. 2. A client receives a valid Modbus TCP exception response with exception code `0B`. What does that prove? A. The upstream client received no response at all. B. The gateway reported that the downstream target failed to respond. C. The client selected RTU-over-TCP. D. The register value was decoded with the wrong word order. 3. Which byte pattern best indicates RTU-style bytes rather than true Modbus TCP? A. `00 2A 00 00 00 06 07 03 00 14 00 02` B. `00 2A 00 00 00 03 07 83 0B` C. `07 03 00 14 00 02` followed by an RTU CRC D. `00 2A 00 00 00 05 07 03 02 00 FA` 4. A gateway mapping table says TCP Unit ID `3` and address range `0x0014-0x0015` route to downstream serial server `7`. What should the learner document? A. Unit ID `3` is invalid because it does not match server `7`. B. The gateway uses mapped routing for this request, so direct Unit ID-to-server assumptions do not apply. C. The PDU address must be changed to `0x0003`. D. The response is stale by definition. 5. A gateway returns a normal Modbus response, but the route note says the gateway may answer from a cache when downstream polling is stale. What is the next best check? A. RTU CRC in the TCP payload. B. MBAP Length only. C. Freshness, timestamp, quality, cache age, or direct downstream comparison. D. Change the documented register from `40021` to `40022`. 6. Which timeout principle is correct for a gateway path? A. The upstream client timeout should be selected from a universal Modbus default. B. The upstream client timeout should allow the gateway downstream timeout, serial transmission, turnaround, retries, and response path. C. TCP clients never need timeout settings. D. Gateway timeout settings are official Modbus protocol constants. 7. A request through a gateway receives exception `02` after reading a range that crosses a reserved register gap. Which interpretation is most likely? A. The gateway is unreachable. B. The read range or address is invalid for the downstream or mapped target. C. The response is necessarily stale. D. The client must switch to RTU-over-TCP. 8. Which source should govern product-specific cache behavior for a real gateway integration? A. A generic Modbus addressing cheat sheet. B. The selected gateway manual or verified emulator/lab evidence. C. The existence of TCP port `502`. D. The fact that Modbus registers are 16 bits. 9. A gateway returns exception code `0A` for a request to Unit Identifier `9`. Which next check best matches the evidence? A. Check the route/path availability, route table, gateway diagnostics, or product-specific path configuration. B. Change the 32-bit word order. C. Add an RTU CRC to the Modbus TCP payload. D. Treat it as proof that the downstream target responded with bad data. ## Answer Key 1. B. Unit Identifier is route evidence in many gateway paths, but exact handling is product-specific. 2. B. Exception `0B` is a valid gateway exception response about downstream target response failure; it is not client-side silence. 3. C. RTU-style bytes use serial address/function/data plus CRC, not an MBAP header. 4. B. The mapping table is the governing evidence for that gateway route. 5. C. A syntactically valid response can still be stale if the gateway or agent caches data. 6. B. Timeout alignment is a chain; numeric values must come from selected source and lab evidence. 7. B. Exception `02` points to illegal data address/range evidence, not automatically gateway reachability. 8. B. Cache behavior is implementation-specific and must be tied to a named gateway/manual or verified lab setup. 9. A. Exception `0A` is gateway path unavailable evidence, so routing/path configuration comes before value decoding. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A overgeneralizes gateway behavior, C confuses Unit Identifier with address notation, and D denies common gateway routing use. | | 2 | B | A contradicts the valid exception response, C guesses a different transport mode, and D jumps to value interpretation. | | 3 | C | A/B/D include MBAP-style TCP framing; C shows serial address/function/data plus an RTU CRC. | | 4 | B | A assumes direct Unit ID mapping, C changes the data address without evidence, and D invents staleness. | | 5 | C | A adds RTU CRC to TCP, B checks only syntax, and D changes the address before proving freshness. | | 6 | B | A/D invent universal timeout constants, and C denies that TCP clients still need practical timeout handling. | | 7 | B | A would fit path failure evidence, C invents cache behavior, and D changes mode despite an address/range exception. | | 8 | B | A/C/D are generic facts that do not define a selected gateway's cache behavior. | | 9 | A | B decodes a value before route evidence, C mixes serial CRC into TCP, and D misreads gateway path-unavailable evidence as downstream data. | ## Instructor Notes - Use questions 1 and 4 together to prevent learners from overgeneralizing transparent Unit Identifier routing. - Use questions 2 and 6 to separate exception evidence from timeout evidence. - Use question 5 to connect gateway work to Module 8 quality and freshness concepts. - Add a product-manual scenario after a gateway source pack is selected. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for MBAP header fields, Unit Identifier and gateway routing, TCP connection behavior and concurrency, RTU/ASCII frame fields where RTU-style bytes are contrasted with true TCP, normal response vs exception response, and exception codes and exception response PDU shape. - Route tables, caching, timeout defaults, retries, broadcast handling, and concurrent-client limits remain gateway product behavior until a manual or emulator source pack is selected. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 13/16 · v1.0.0 · Exported for offline / agent use._ # Module 14: Troubleshooting Workflow > A repeatable evidence-first method for diagnosing failed reads, writes, and timeouts. **Phase:** Integration & Real Systems **Estimated time:** 13 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/troubleshooting-workflow ## What you'll be able to do - Apply a repeatable Observe → Hypothesize → Test → Record loop. - Choose the right layer to investigate first (transport, framing, addressing, decoding). - Produce a hand-off report another integrator can act on. ## Three things people get wrong 1. **Changing two things at once.** One variable per test. Otherwise you can't tell which change mattered. 2. **Skipping the capture.** Always capture the bytes. Conversations about Modbus without a capture are mostly fiction. 3. **Treating success as 'understood'.** If you don't know why a change worked, the bug will be back. ## From the field **The capture that ended the standoff** Two vendors blamed each other for a flaky meter for three months. A 15-minute capture showed the meter responded correctly to every poll — but the gateway re-asked the same question 11 ms later, before the bus had settled. The capture replaced the argument with a configuration change. ## References - [Wireshark Modbus dissector](https://www.wireshark.org/docs/dfref/m/modbus.html) ## Lesson # Module 14 Lesson: Troubleshooting Workflow ## Learner Outcome By the end of this module, learners can classify a Modbus problem as no response, exception response, or wrong value; choose the next evidence-producing test; and document one change at a time without confusing transport, addressing, gateway, and data-decoding faults. ## Key Concepts - Troubleshooting starts with the exact variant and path: RTU, ASCII, TCP, Modbus Security, RTU-over-TCP, or gateway path. - Use the 3-bucket method before changing settings: no response, exception response, wrong value. - Physical/network reachability comes before register-map edits. - Function code, table, documented address, PDU address, quantity, Unit Identifier or serial server address, and transport wrapper must be recorded together. - A valid exception response proves that something understood enough of the request to reject it. - A normal response with an implausible value is a data-meaning problem until proven otherwise. - Write tests require a safety gate; start with read-only evidence. ## Key Terms - Evidence bucket: the first troubleshooting classification, such as no response, exception response, wrong value, or safety stop. - No response: a client observation that no valid Modbus response arrived. - Wrong value: a valid response whose decoded meaning does not match expectation. - Hypothesis: the suspected cause selected from current evidence. - One-change test: a controlled next step that changes one variable and records the result. - Safety stop: a required pause before write-capable, hardware, or production-affecting action. ## Source-Grounded Explanation ### The 3-Bucket Method Most field symptoms can be sorted before deep analysis: | Bucket | What The Learner Sees | First Evidence To Collect | |---|---|---| | No response | Timeout, no bytes, connection failure, malformed frame discard, or no valid response before deadline. | Variant, reachability, serial settings, wiring, Unit Identifier or serial server address, gateway path, timeout chain, raw request evidence. | | Exception response | Function code with high bit set and an exception code. | Requested function, PDU address, quantity, data value, device access mode, safety state, gateway exception context. | | Wrong value | Normal response but decoded value is missing, stale, nonsensical, or outside expected range. | Raw response bytes, data type, signedness, word order, scale, unit, quality/freshness, state context, source map. | The bucket is not the root cause. It is the first sorting step that prevents random changes. A timeout should not send the learner straight to word order. A valid exception response should not send the learner straight to wiring. An impossible value should not be treated as a dead device until the bytes are checked. ### Step 1: Identify The Variant And Path Record the path before interpreting symptoms: - RTU, ASCII, TCP, Modbus Security, RTU-over-TCP, or vendor dialect. - Pure serial, pure Ethernet, secure TCP, or TCP-to-serial gateway. - Serial server address, MBAP Unit Identifier, or gateway route identifier. - Legacy labels in manuals or tools, such as slave ID, device ID, station number, or unit ID. Transport changes the evidence. RTU uses a serial address and CRC. ASCII uses ASCII hex characters, LRC, and text delimiters. True Modbus TCP uses MBAP plus PDU and no serial CRC. A gateway may add route behavior that is product-specific. ### Step 2: Prove Reachability Before Map Changes For serial paths, check baud rate, parity, data bits, stop bits, serial server address, wiring polarity labels, common conductor, termination, topology, adapter mode, and duplicate IDs before changing register addresses. For TCP paths, check IP reachability, TCP port, firewall, connection handling, Unit Identifier requirements, and gateway status before changing PDU address or scale. For gateways, compare upstream client timeout, gateway timeout, downstream serial settings, route table, retry behavior, and downstream target health. Do not invent timeout defaults; use selected product documentation or lab evidence. ### Step 3: Read A Known-Good, Read-Only Value Start with a safe read-only value when possible: - Model number. - Firmware version. - Device status. - Line frequency. - Temperature. - Input voltage. Record the request as a complete evidence row: | Field | Example | |---|---| | Function code | `03` or `04` as specified by the map | | Documented address | `40010`, `30051`, or vendor row reference | | Actual PDU address | zero-based offset actually sent | | Quantity | count of coils, bits, or registers | | Unit Identifier or serial server address | MBAP Unit Identifier or RTU/ASCII address | | Expected data meaning | type, width, scale, unit, word order, state/freshness note | | Expected normal response | function code, byte count, raw data length | | Likely failure mode | timeout, exception `01`, `02`, `03`, `04`, `0A`, `0B`, or wrong value | ### Step 4: Interpret Exceptions As Evidence An exception response is useful because it is still a Modbus response. The exception function sets the high bit on the requested function code. For example, a failed function `03` response uses exception function `83`. Use common exceptions as evidence, not as final diagnoses: | Exception | Practical Direction | |---:|---| | `01` Illegal Function | Function unsupported, forbidden, wrong access path, or device state does not allow it. | | `02` Illegal Data Address | Address, table, range, gap, or quantity crosses unsupported data. | | `03` Illegal Data Value | Quantity, byte count, written value, or request data shape is invalid. | | `04` Server Device Failure | Device could not perform the requested action; check device state and manual. | | `0A` Gateway Path Unavailable | Gateway path/route availability evidence is needed. | | `0B` Gateway Target Device Failed To Respond | Gateway responded but the downstream target did not answer. | Do not treat exception `02` as proof that the device is offline. It proves the responder rejected the addressed data range. ### Step 5: Verify Value Meaning If communication succeeds, the next question is whether the value is meaningful: - Did the tool use the correct table and function code? - Was the documented address converted to the correct PDU address? - Is the value signed or unsigned? - Is it one register, two registers, four registers, or a string? - Is word order high-word-first or low-word-first? - Is there a scale, offset, unit, enum, bitfield, or sentinel value? - Is the device in a state where the value should be valid? - Could a gateway, cache, or dashboard be showing stale data? Wrong decoded values should be handled with raw bytes and map evidence, not by changing serial settings at random. ## Practical Example: Dashboard Shows an Impossible `2.7e23 Hz` Scenario: an integrator expects AC line frequency near `60 Hz`, but the dashboard shows about `2.7e23 Hz` — a value far too large to be real, even though the Modbus response came back normal. | Item | Value | |---|---| | Transport | Modbus TCP | | Function code | `04` Read Input Registers | | Documented register | Input register `30051` | | Actual PDU address | `0x0032` if one-based `30001` notation is confirmed | | Quantity | `2` registers | | Data type | 32-bit IEEE-754 float | | Raw response registers | `0x4270 0x6666` (bytes `42 70 66 66`) | | Correct value | `60.1 Hz` when the two registers are combined in the documented word order | | Word order | Needs source-map verification | | Scale/unit | Direct `Hz` unless source map says otherwise | | Expected normal response | Function `04`, byte count `4`, two registers | | Likely failure mode | Wrong value from reversed word order or a type mismatch; exception `02` only if address/range is invalid | Troubleshooting flow: 1. Confirm whether the symptom is no response, exception response, or wrong value. Here the dashboard has a value, so start in the wrong-value bucket even though the number is absurd. 2. Capture or log the raw response bytes: `42 70 66 66`. 3. Confirm the function code is `04` because the map says input register. 4. Confirm the PDU address is `0x0032`, not the displayed `30051`. 5. Decode the two registers using the map's word order. Combined as `0x4270 0x6666` the float is `60.1 Hz`; combined in reversed word order as `0x6666 0x4270` the float is about `2.7e23 Hz`, which matches the wrong dashboard value. 6. Compare the result to a local HMI, vendor software, or expected operating range. 7. Record the final address, type, word order, scale, and evidence in the troubleshooting log. Because reversing the word order turns the absurd reading back into a plausible `60.1 Hz`, the root cause was decoded-value interpretation, not Modbus reachability. ## Common Pitfalls - Changing address, Unit Identifier, word order, scale, and timeout in one attempt. - Treating no response as an illegal-data-address exception. - Treating a valid exception response as a wiring failure. - Assuming exception `02` means the whole device is offline. - Reading input registers with function `03` or holding registers with function `04` without checking the source map. - Treating `40001` notation as bytes sent in the request. - Testing write functions before read-only communication and safety constraints are proven. - Retrying too aggressively through a slow gateway and increasing bus load. - Treating stale cached values as fresh device state. ## Instructor Flow 1. Put the 3-bucket table on screen and require a bucket before any fix is proposed. 2. Walk one no-response case, one exception case, and one wrong-value case. 3. Require learners to fill the evidence log with one hypothesis and one test at a time. 4. Use the worked frequency example to show why a normal response can still be wrong. 5. Stop any write-function scenario at the safety gate and route it to Module 15. ## Check-Your-Understanding 1. A client receives function `83` and exception code `02`. What does the high bit on the function code mean? 2. Why is a known-good read-only register a better first target than a write command? 3. What evidence separates an off-by-one address problem from a word-order problem? 4. Why do bad RTU CRC or parity cases often look like timeouts? 5. A TCP capture shows Unit Identifier `1`, but the intended downstream RTU server is `3`. Which configuration area should be inspected? ## Source Notes - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for PDU addressing, function codes, normal and exception response shape, exception codes, and public request/response behavior. - Official serial basis: Modbus over Serial Line Specification and Implementation Guide V1.02 for RTU/ASCII framing, serial settings, CRC/LRC, timing, serial addressing, and silent discard behavior. - Official TCP basis: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP, Unit Identifier, TCP behavior, and gateway context. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for normal response vs exception response, exception codes and exception response PDU shape, addressing model and zero-based PDU addresses, RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, MBAP header fields, Unit Identifier and gateway routing, and TCP connection behavior and concurrency. - Internal course basis: `modbus-wiki.md`, `course-phase-drafts/phase-4-integration-troubleshooting-real-systems.md`, `release/troubleshooting-evidence-log.md`, and Module 5-14 draft packages. - Tool behavior: Wireshark, Node-RED, PyModbus, mbpoll, simulator logs, and client UI wording require version-pinned verification before release. - Synthetic source: scenario cards in the Module 14 lab are course-authored fixtures, not captured production logs. ## Completion Checkpoint Before moving on, learners should classify a scenario into no response, exception response, wrong value, or safety stop, then record the next one-change test and the evidence that would confirm or reject the hypothesis. ## Troubleshooting Decision Tree Follow the branches in order — never skip a layer to "save time". ```mermaid flowchart TD S["Symptom reported"] --> Q1{"Any bytes on the wire?"} Q1 -- "No" --> T1["Transport
baud · parity · wiring · IP/port"] Q1 -- "Yes" --> Q2{"CRC / LRC / TCP length valid?"} Q2 -- "No" --> T2["Framing
cable · termination · bit timing"] Q2 -- "Yes" --> Q3{"Response FC ≥ 0x80?"} Q3 -- "Yes" --> T3["Exception
read exception code → addressing / value"] Q3 -- "No" --> Q4{"Value matches expected meaning?"} Q4 -- "No" --> T4["Decoding
type · word order · scale · unit · sentinel"] Q4 -- "Yes" --> Done["Solved — record root cause"] T1 --> Loop["Observe again"] T2 --> Loop T3 --> Loop T4 --> Loop Loop --> S ``` Text equivalent of the decision tree, in the same order: 1. **Any bytes on the wire?** If no, the problem is at the **transport** layer — check baud, parity, wiring, and IP/port — then observe again. If yes, continue. 2. **Are the CRC, LRC, or TCP length valid?** If no, the problem is **framing** — check cable, termination, and bit timing — then observe again. If yes, continue. 3. **Is the response function code `0x80` or higher?** If yes, it is an **exception** — read the exception code and follow it to an addressing or value problem — then observe again. If no, continue. 4. **Does the value match its expected meaning?** If no, the problem is **decoding** — check data type, word order, scale, unit, and sentinel handling — then observe again. If yes, the case is **solved**; record the root cause. Each layer loops back to observing the symptom again so you change one thing at a time and re-test. ## Reusable Assets - [Troubleshooting scenario lab](https://learnmodbus.studioseventeen.io/lesson/troubleshooting-workflow?page=lab-1) - [Troubleshooting decision tree](https://learnmodbus.studioseventeen.io/resource/troubleshooting-decision-tree) - [Troubleshooting evidence log](https://learnmodbus.studioseventeen.io/resource/troubleshooting-evidence-log) - [Module 14 quiz](https://learnmodbus.studioseventeen.io/lesson/troubleshooting-workflow?page=quiz) ## Diagram source ```mermaid flowchart TD S["Symptom"] --> O["Observe
(capture evidence)"] O --> H["Hypothesize
(layer + cause)"] H --> T["Test
(single change)"] T --> R["Record
(log + decide)"] R -->|Solved| Close["Close"] R -->|Not yet| O ``` ## Labs ### Lab 1 # Lab 19: Troubleshooting Scenario Cards ## Learner Outcome Learners can classify staged Modbus failures into no response, exception response, or wrong value, then choose one evidence-producing next step without changing unrelated settings. ## Prerequisites - Module 4: function codes and exception responses. - Module 5: documented address versus PDU address. - Module 7: data types and word order. - Module 8: scale, unit, quality, and freshness. - Module 9-13: serial, RTU/ASCII, TCP, and gateway evidence. - Module 14 lesson through the 3-bucket method. ## Safety And Scope This is a no-hardware paper lab using synthetic cards. It does not connect to a simulator, network, gateway, or real device. Do not scan networks, write to devices, or change production settings. Any write-function card stops at the safety gate and routes to Module 15 before a command is sent. ## Scenario Setup You are reviewing failed Modbus reads from a training system. Each card gives enough evidence to choose the first diagnostic bucket and next test. Record one hypothesis and one next action at a time. ## Scenario Cards | Card | Evidence | Learner Task | |---|---|---| | A | RTU client sends server `7`, function `03`, PDU address `0x0009`, quantity `1`. No bytes are accepted before timeout. Notes show client `9600 8-E-1`; device label `19200 8-E-1`. | Classify the bucket and name the next setting to verify. | | B | RTU client sends server `1`, function `03`, PDU address `0x0009`, quantity `1`. No response. Device label says serial address `7`. | Decide whether to change map address or serial server address first. | | C | TCP client reads function `03`, documented holding register `40010`, but sends PDU address `0x000A`. Response is `83 02`. | Explain why a valid exception response changes the troubleshooting path. | | D | TCP client reads function `04`, documented input register `30051`, PDU address `0x0032`, quantity `2`. Response is normal with two registers, but dashboard shows about `2.7e23 Hz` (raw registers `0x4270 0x6666`). | Classify as wrong value and name the raw-byte checks. | | E | Gateway request uses Unit Identifier `8`, PDU `03 00 14 00 02`. Gateway returns exception `83 0B`. | Separate downstream target failure from upstream timeout. | | F | Client receives normal response for function `03`, byte count `4`, but the route note says the gateway may answer from cache when downstream polling is stale. | Decide what freshness evidence is needed. | | G | Client configured for true Modbus TCP sends RTU-style bytes with serial address and CRC over TCP. No valid Modbus TCP response is seen. | Identify the mode mismatch before changing addresses. | | H | Request reads holding registers `40020-40035` as one block through a vendor map with a reserved gap at `40027`. Response is `83 02`. | Redesign the read grouping. | | I | Client reads a changing 32-bit counter as two separate one-register reads. Values occasionally jump backward. | Identify coherency risk and safer read strategy. | | J | Technician wants to test function `06` write single register on a live controller because reads are confusing. Process effect is unknown. | Apply stop conditions and route to safety review. | ## Procedure 1. For each card, choose one bucket: no response, exception response, wrong value, or safety stop. 2. Record the evidence that proves the bucket. 3. Identify the likely fault domain: transport, serial settings, server or Unit Identifier, function/table/address/quantity, gateway, data decoding, freshness, coherency, polling plan, or safety. 4. Choose exactly one next test. 5. Write what not to change yet. 6. Fill out the evidence log for at least three cards. ## Worksheet | Card | Bucket | Fault Domain | Evidence Used | Next Test | What Not To Change Yet | |---|---|---|---|---|---| | A | | | | | | | B | | | | | | | C | | | | | | | D | | | | | | | E | | | | | | | F | | | | | | | G | | | | | | | H | | | | | | | I | | | | | | | J | | | | | | ## Answer Key | Card | Bucket | Fault Domain | Evidence Used | Next Test | What Not To Change Yet | |---|---|---|---|---|---| | A | No response | Serial settings | Timeout plus baud mismatch note | Verify baud and match client to documented device setting | PDU address, word order, scale | | B | No response | Serial server address | Request sent to server `1`; device labeled `7` | Send read-only request to server `7` or confirm actual configured ID | Register map and word order | | C | Exception response | Addressing/range | Exception function `83`, code `02`, PDU address `0x000A` for `40010` | Recalculate one-based `40001` notation and try PDU `0x0009` if source supports it | Serial/TCP reachability; a response arrived | | D | Wrong value | Data decoding | Normal response but implausible engineering value | Inspect raw bytes, data type, word order, scale, unit, and source map | IP, port, serial settings | | E | Exception response | Gateway downstream target | Gateway returned exception `0B` | Check downstream target, route, serial settings, and gateway log | Treating it as upstream silence | | F | Wrong value | Freshness/cache | Normal response with stale-cache note | Check timestamp, quality, cache age, polling status, or direct downstream comparison | Packet syntax if response is structurally valid | | G | No valid response | TCP mode mismatch | RTU-style bytes used where true MBAP is expected | Select true Modbus TCP mode or verify RTU-over-TCP support | Address base and scale | | H | Exception response | Poll grouping/map gap | Exception `02` on a range crossing reserved gap | Split reads around the gap and document supported ranges | Gateway reachability | | I | Wrong value | Multi-register coherency | Separate reads of a changing multi-register value | Read both registers in one request or use device-supported snapshot/latch method if documented | Scaling until raw coherency is proven | | J | Safety stop | Write safety | Unknown process effect and live controller | Stop; complete write-safety checklist, authorization, preconditions, rollback, and independent verification | Sending the write command | ## Expected Observations - A timeout does not prove the register address is wrong. - A valid exception response proves that some responder parsed enough of the request to reject it. - Wrong value requires raw bytes and source-map evidence. - Gateway exceptions provide different evidence than client-side silence. - Polling design can create failures even when individual addresses are valid. - Safety stop is a correct troubleshooting outcome when the next test is a live write. ## Troubleshooting Notes - Change one variable per trial and record it. - When a card has a valid Modbus exception, do not start by changing wiring or firewall settings. - When a card has no valid response, do not start by changing word order. - When a card has a normal response, do not declare success until data type, scale, unit, and freshness make sense. - Keep tool-specific messages out of the final answer key until the toolchain is version-pinned. ## Check Questions 1. Which cards are no-response cases? 2. Which cards are exception-response cases? 3. Which cards are wrong-value cases? 4. Which card should stop before any Modbus write is sent? 5. Why is Card C not primarily a wiring problem? 6. Why is Card D not primarily an IP reachability problem? ## Instructor Notes - Require learners to defend why their chosen next test is narrower than a broad configuration reset. - Ask learners to fill [Troubleshooting Evidence Log](https://learnmodbus.studioseventeen.io/resource/troubleshooting-evidence-log) for Cards C, D, and E. - Use Card J as the bridge into Module 15 security and write safety. - Optional extension: convert Cards A-H into Node-RED or simulator exercises only after tool versions and expected outputs are verified. ## Source Notes - Official protocol source: Modbus Application Protocol Specification V1.1b3 for exception response shape and exception codes. - Official serial source: Modbus over Serial Line Specification and Implementation Guide V1.02 for RTU/ASCII framing, CRC/LRC, addressing, and silent discard behavior. - Official TCP source: Modbus Messaging on TCP/IP Implementation Guide V1.0b for MBAP and Unit Identifier context. - Internal course source: Modules 5-13 draft packages, `modbus-wiki.md`, and `release/troubleshooting-decision-tree.md`. - Synthetic source: all cards are course-authored scenario fixtures, not captured tool logs or production traffic. ## Knowledge check # Module 14 Quiz: Troubleshooting Workflow ## Questions 1. A client receives no valid response before timeout. Which first bucket should be assigned? A. No response B. Exception response C. Wrong value D. Safety stop 2. A response to function `03` comes back as exception function `83` with exception code `02`. What does the high bit on the function code indicate? A. The serial CRC was accepted as data. B. The response is a Modbus exception response to function `03`. C. The server sent a 32-bit float. D. The client used the wrong TCP port. 3. A normal response returns raw bytes, but the dashboard value is impossible. What should be checked first? A. Firewall rules. B. Serial termination. C. Data type, word order, scale, unit, address base, and freshness. D. Whether all write functions are enabled. 4. A Modbus RTU request has the wrong parity setting and the client times out. Why is an exception response unlikely? A. Malformed serial frames are normally discarded rather than parsed into Modbus exceptions. B. Exception responses only exist in Modbus TCP. C. Parity settings change the documented register number. D. The response must be a stale cached value. 5. A valid exception `02` appears when reading a large range that crosses a reserved map gap. What is the best next action? A. Change word order. B. Split the polling group around the gap and verify supported ranges. C. Add RTU CRC bytes to Modbus TCP. D. Increase writes until the device responds. 6. A gateway returns exception `0B`. Which statement is most accurate? A. The upstream client received no Modbus response. B. The gateway returned a valid exception saying the downstream target failed to respond. C. The value is definitely scaled incorrectly. D. The request must have used function `04`. 7. A technician wants to send function `06` to a live controller because reads are confusing and the process effect is unknown. What is the correct course action? A. Send the write and inspect the echo. B. Stop and complete write-safety, authorization, precondition, rollback, and independent-verification checks. C. Change baud rate first. D. Change word order first. 8. Which troubleshooting habit best preserves evidence? A. Change several settings at once to save time. B. Change one variable per trial and record observation, hypothesis, test, result, conclusion, and next action. C. Start with writes because they prove control. D. Ignore raw bytes when the dashboard is wrong. 9. A TCP capture shows MBAP Unit Identifier `1`, but the intended downstream RTU server is `3`. Which area should be inspected? A. Gateway route or Unit Identifier configuration. B. IEEE-754 exponent bits. C. Coil write mask. D. ASCII LRC delimiter. 10. Which source boundary is correct for troubleshooting workflows? A. Official specs define response shapes and protocol fields; tool UI messages, simulator logs, and field workflows need tool or lab evidence. B. Tool screenshots are official Modbus protocol rules. C. Field notes override the application protocol. D. A dashboard value is always enough evidence. ## Answer Key 1. A. Timeout or no valid response belongs in the no-response bucket. 2. B. Exception responses set the high bit on the requested function code, so `83` is an exception response to `03`. 3. C. A normal response with impossible meaning is a wrong-value problem until data meaning and freshness are checked. 4. A. Bad serial settings or corrupt frames often prevent a valid Modbus frame from being parsed, so clients see timeouts. 5. B. Exception `02` on a range crossing a gap points to address/range evidence and polling-group redesign. 6. B. Exception `0B` is gateway-response evidence about downstream target failure, not client-side silence. 7. B. Unknown live write effects require a safety stop and Module 15 write-safety workflow before any command. 8. B. One variable per trial keeps the evidence chain usable. 9. A. In a gateway path, Unit Identifier and route configuration are the first evidence to inspect. 10. A. Official specs govern protocol mechanics; tool behavior and workflows need verified tool/lab/source support. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | A | B requires a valid exception response, C requires a normal response with bad meaning, and D is reserved for unsafe action or write-risk conditions. | | 2 | B | A treats an exception function as data, C invents a float, and D confuses the function byte with transport configuration. | | 3 | C | A/B fit no-response connectivity or physical-layer cases, and D jumps to write policy before value interpretation evidence. | | 4 | A | B falsely limits exceptions to TCP, C confuses serial framing with addressing, and D invents cache behavior. | | 5 | B | A changes interpretation, C mixes RTU and TCP, and D escalates to unsafe writes instead of narrowing the range. | | 6 | B | A contradicts receipt of a valid exception, C jumps to scale, and D invents the request function. | | 7 | B | A trusts a write echo too much, while C/D change unrelated settings before safety boundaries are satisfied. | | 8 | B | A destroys evidence, C is unsafe, and D discards the raw evidence needed to debug a wrong value. | | 9 | A | B/C/D are data, write, or ASCII details that do not resolve a Unit Identifier route mismatch. | | 10 | A | B/C elevate secondary evidence above official protocol mechanics, and D treats a dashboard value as sufficient evidence. | ## Instructor Notes - Use questions 1-3 to reinforce the 3-bucket method. - Use questions 6 and 9 to connect Module 14 back to Module 13 gateway evidence. - Use question 7 as the bridge into Module 15. - Add real tool screenshots only after tool versions are pinned in `lab-toolchain-bom.md`. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for normal response vs exception response, exception codes and exception response PDU shape, addressing model and zero-based PDU addresses, RTU/ASCII frame fields, RTU timing and ASCII framing, CRC/LRC checking, MBAP header fields, Unit Identifier and gateway routing, TCP connection behavior and concurrency, and write single register shape and echo boundary. - Tool UI messages, simulator logs, PCAP workflows, and field troubleshooting steps remain versioned lab-evidence gates. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 14/16 · v1.0.0 · Exported for offline / agent use._ # Module 15: Security & Safety > What classic Modbus does not protect, write safety practice, and TLS / Modbus Security. **Phase:** Integration & Real Systems **Estimated time:** 9 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/security-safety ## What you'll be able to do - List what classic Modbus does not protect (authentication, encryption, integrity beyond CRC). - Apply defensive write practices (allowlists, rate limits, write-readback). - Describe Modbus/TCP Security at a high level. ## Three things people get wrong 1. **Relying on 'Modbus is internal'.** Flat OT networks are common. Assume the wire is reachable and design accordingly. 2. **Writing without read-back verification.** A successful FC 06/16 response says the bytes arrived, not that the device accepted them. Always read back a critical write. 3. **Ignoring Modbus Security because 'no one uses it yet'.** Adoption is rising. Even if not deploying it today, design with a migration path in mind. ## From the field **The pump that ran on weekend nights** An overnight pump cycle no one had scheduled turned out to be a misconfigured maintenance script writing to the wrong Unit ID. There was no authentication, no audit log, and no read-back — just a script running on a laptop someone forgot in a panel. ## References - [Modbus/TCP Security Protocol Specification v36](https://www.modbus.org/file/secure/modbussecurityprotocol.pdf) - [ISA/IEC 62443](https://www.isa.org/standards-and-publications/isa-standards/isa-iec-62443-series-of-standards) ## Lesson # Module 15 Lesson: Security And Safety ## Learner Outcome By the end of this module, learners can explain why classic Modbus needs compensating controls, distinguish read and write risk, identify write functions in isolated evidence, map Modbus-specific risks to defensive controls, and apply a write-safety stop before any command affects real equipment. ## Key Concepts - Classic Modbus RTU, ASCII, and TCP were not designed with modern authentication, authorization, or encryption. - Modbus Security protects the transport with TLS and certificate-based identity, but the underlying Modbus function codes and register meanings still matter. - Read functions can expose process state; write functions can change process or device state. - A Modbus write response confirms protocol-level acceptance shape, not the physical outcome. - Defensive controls include segmentation, allowlisting, write restrictions, monitoring, change control, and safe operating procedures. - Security labs must be isolated, defensive, authorized, and simulator-first. ## Key Terms - Classic Modbus: Modbus RTU/ASCII/TCP behavior without modern built-in authentication, authorization, or encryption. - Modbus Security: TLS-protected Modbus TCP profile associated with `mbap-s`. - TLS: Transport Layer Security, used to protect network communication. - Certificate: identity material used by TLS and, in Modbus Security, role-related authorization context. - Segmentation: network separation that limits which clients can reach Modbus servers. - Allowlisting: permitting only expected clients, functions, or paths. - Monitoring: recording and reviewing traffic or events for defensive purposes. - Write safety: the operational review boundary before any write-capable action. ## Source-Grounded Explanation ### Classic Modbus Is Not The Security Boundary Classic Modbus TCP commonly runs in plaintext on TCP port `502`. Classic Modbus RTU and ASCII also do not provide modern peer authentication, user authorization, or encryption at the protocol level. If a client can reach a device and the device accepts the request, the protocol itself does not normally prove that the client is authorized to read or write that register. This is a protocol design boundary, not a reason to panic. Many systems use classic Modbus safely because the surrounding architecture controls who can reach it, what can be changed, and how activity is monitored. ### Modbus Security Modbus Security, also called Modbus/TCP Security or `mbaps`, wraps Modbus TCP ADUs in TLS and is associated with TCP port `802`. The official security specification describes certificate-based identity and TLS transport protection. Role-based client authorization may be represented through certificate role extensions. Important boundary: Modbus Security protects the transport and identity layer. It does not make a wrong register map correct, does not define a device's write semantics, and does not prove that a process reached the intended physical state after a command. ### Read Risk Versus Write Risk Reads and writes deserve different safety treatment: | Activity | Risk Pattern | Evidence To Collect | |---|---|---| | Read coils/discrete inputs/registers | Process information, status, alarms, production context, or sensitive operational state may be exposed. | Source, destination, Unit Identifier or serial server address, function code, address range, polling rate, business need. | | Write single coil/register | A command, mode, setpoint, reset, or configuration may change state. | Documented meaning, allowed states, safe range, operating mode, rollback, independent feedback. | | Write multiple coils/registers | Several changes may happen in one request, including packed bits or multi-word values. | Full payload, bit order, word order, expected affected points, before/after state. | | Mask or read/write multiple registers | Partial bit changes or combined actions may be difficult to reason about. | Mask logic, unaffected bits, write range, read range, vendor semantics. | Function codes that deserve extra attention in monitoring and safety review include `05`, `06`, `15`, `16`, `22`, and `23` when supported by a device. ### Write Echo Is Not Physical Proof For common write functions, the normal Modbus response echoes the request address and written value or summarizes the written range. That response is useful protocol evidence, but it is not proof that the physical process reached the desired state. Real devices may: - Reject the command because local mode, interlock, safety state, or authority is wrong. - Accept a setpoint but clamp it internally. - Echo a command while an active setpoint ramps over time. - Require unlock registers, command confirmation, or multi-step sequences. - Store a persistent configuration value that has long-term effects. - Use product-specific command words, magic values, or role-limited registers. The safe pattern is: document the command, check preconditions, send only in an authorized isolated or approved context, read independent status, and record rollback or stop actions. ### Defensive Control Map Use source-backed controls rather than tool-specific magic: | Modbus Risk | Defensive Control | |---|---| | Any client can reach TCP `502` on a classic Modbus device. | Segment OT, block internet exposure, allow only required clients, log new sources. | | Broad engineering workstation access. | Least-required network paths, maintenance windows, change control, separate read/write access where possible. | | Unexpected write functions. | Block or alert on write functions except from approved control nodes and expected ranges. | | Repeated or replayed commands. | Monitor repeated writes, validate state before action, require independent feedback and operator procedure. | | Gateway path hides downstream target. | Monitor Unit Identifier, route configuration, gateway logs, and downstream target health. | | Tool syntax differs by version. | Verify Suricata, Zeek, Snort, Wireshark, firewall, and gateway behavior before publishing commands. | ### Safe Course Boundary This module teaches defensive recognition and safe decision-making. It does not teach unauthorized access, scanning public networks, exploiting devices, or bypassing controls. Labs use synthetic event cards, offline reviewed traffic, localhost simulators, or instructor-controlled lab networks only. ## Practical Example: Synthetic Write Event Scenario: a lab simulator exposes a synthetic command register with no physical effect. A learner reviews one write event. | Item | Value | |---|---| | Transport | Modbus TCP on isolated lab network or saved fixture | | Function code | `06` Write Single Register | | Documented register | Synthetic holding register `40020` | | Actual PDU address | `0x0013` | | Quantity | one register | | Data type | unsigned 16-bit command code | | Scale/unit | not an engineering measurement | | Expected normal response | Echo function `06`, address `0x0013`, and written value | | Defensive observation | New client writes to a command register outside approved context | | Safety decision | Alert and investigate in lab; in the field, stop and require authorization plus write-safety checklist | Learner task: 1. Identify the write function. 2. Record source, destination, Unit Identifier, function code, address, and value. 3. Decide whether the source is approved. 4. Draft a plain-language monitoring requirement. 5. Explain why a write echo is not physical proof of the process state. Plain-language monitoring requirement: ```text Alert when any unapproved client sends Modbus write function 05, 06, 15, 16, 22, or 23 to the synthetic command range. Record source, destination, Unit Identifier, function code, address or range, value when available, and time. ``` Do not convert this into deployable Suricata, Zeek, Snort, firewall, or gateway syntax until the selected tool version, parser behavior, field names, and lab traffic are verified. ## Common Pitfalls - Saying Modbus is secure because it is behind a VPN. - Treating read-only polling and write commands as the same operational risk. - Treating a write echo as proof that the physical process changed correctly. - Writing to reserved, hidden, installer-only, or unclear registers on real devices. - Ignoring local/remote mode, interlocks, active faults, and command authority. - Publishing detection-rule syntax before checking the selected tool version. - Running security labs against public IPs, production systems, or third-party devices. - Turning a defensive course into offensive instructions. ## Instructor Flow 1. Start with the protocol boundary: classic Modbus does not authenticate command authority. 2. Compare read exposure and write control risk. 3. Show the synthetic write event and ask learners what evidence they would record. 4. Use the threat-to-control worksheet to map risks to segmentation, allowlisting, monitoring, Modbus Security, and write-safety procedure. 5. Stop every real-device write scenario at the write-safety checklist and Safety Review Appendix unless a controlled training device and approved procedure exist. ## Check-Your-Understanding 1. Why does classic Modbus need network and operational controls around it? 2. What does Modbus Security add, and what does it not solve? 3. Why is function `06` higher risk than a read-only function in a live system? 4. What evidence should be recorded when a write function appears in lab traffic? 5. Why should tool-specific detection syntax stay gated until version verification? ## Source Notes - Official protocol basis: Modbus Application Protocol Specification V1.1b3 for function codes and write response behavior. - Official security basis: Modbus/TCP Security Protocol Specification for TLS wrapping, certificate identity, role-extension concept, and TCP port `802`. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for write single coil/register shape and echo boundary, write multiple coils/registers quantity limits, mask write register, read/write multiple registers, IANA service name `mbap` on port `502`, IANA service name `mbap-s` on port `802`, Modbus Security wraps Modbus/TCP in TLS, Modbus Security certificates and role authorization, and Modbus Security TLS requirements. - Authoritative OT security framing: [security-citation-map.md](https://learnmodbus.studioseventeen.io/resource/security-citation-map) rows for NIST SP 800-82 Rev. 3, CISA ICS defense-in-depth guidance, and MITRE ATT&CK for ICS defensive analysis language. - Internal course basis: `modbus-wiki.md`, `release/write-safety-checklist.md`, `release/threat-to-control-worksheet.md`, and Module 14 troubleshooting stop conditions. - Tool behavior: Suricata, Zeek, Snort, Wireshark, firewall/DPI gateways, public PCAPs, Node-RED, and simulator outputs require version-pinned verification before learner release. - Synthetic source: Module 15 lab events are course-authored fixtures, not captured production traffic. ## Completion Checkpoint Before moving on, learners should identify whether an event is read-only or write-capable, record source/destination/function/address/value evidence, and explain which safety or defensive control gate applies before any real-device action. ## Reusable Assets - [Defensive write monitoring lab](https://learnmodbus.studioseventeen.io/lesson/security-safety?page=lab-1) - [Threat-to-control worksheet](https://learnmodbus.studioseventeen.io/resource/threat-to-control-worksheet) - [Write-function risk reference](https://learnmodbus.studioseventeen.io/resource/write-function-risk-reference) - [Modbus write-safety checklist](https://learnmodbus.studioseventeen.io/resource/write-safety-checklist) - [Safety Review Appendix](https://learnmodbus.studioseventeen.io/resource/safety-review-appendix) - [Module 15 quiz](https://learnmodbus.studioseventeen.io/lesson/security-safety?page=quiz) ## Diagram source ```mermaid flowchart LR C["Client"] -- "TLS handshake" --> S["Server (Modbus Security)"] S -. "Cert pinning + auth role" .-> C C -- "Authorized writes only" --> S ``` ## Labs ### Lab 1 # Lab 20: Defensive Write Monitoring Without A Live Network ## Learner Outcome Learners can identify Modbus write-function events in synthetic evidence, separate read activity from write activity, draft a defensive monitoring requirement, and apply the write-safety stop before any real command is sent. ## Prerequisites - Module 4: function codes and write responses. - Module 12: Modbus TCP and MBAP fields. - Module 13: gateway Unit Identifier and route evidence. - Module 14: troubleshooting evidence log and safety stop. - Module 15 lesson through read/write risk and write echo limitations. ## Safety And Scope This is a no-hardware and no-network lab. It uses synthetic event cards, not live traffic. Do not scan networks, connect to production devices, or write to real equipment. Tool-specific detection syntax is intentionally out of scope until versions and expected outputs are verified. Any real-device or deployable monitoring extension must pass the [Safety Review Appendix](https://learnmodbus.studioseventeen.io/resource/safety-review-appendix). ## Scenario A lab system records Modbus TCP events from an isolated simulator. The process has no physical effect. Learners review the event cards and decide which events are ordinary reads, which are write actions, which are suspicious, and which require a safety stop. ## Event Cards | Card | Event Evidence | Learner Task | |---|---|---| | A | Approved HMI reads function `03`, Unit Identifier `1`, PDU address `0x0009`, quantity `2`, every 2 seconds. | Classify read activity and expected baseline evidence. | | B | Engineering laptop reads function `04`, Unit Identifier `1`, PDU address `0x0032`, quantity `2`, during approved maintenance. | Decide whether this is read exposure or write risk. | | C | Unknown client sends function `06`, Unit Identifier `1`, documented register `40020`, PDU address `0x0013`, value `0x0001`. | Identify write function and draft alert requirement. | | D | Approved controller sends function `16`, Unit Identifier `1`, documented registers `40033-40034`, PDU address `0x0020`, quantity `2`, byte count `4`, payload `00 32 00 00`, maintenance window noted. | Record full payload and required independent feedback. | | E | Unknown client repeatedly sends function `05` to documented coil `00001`, PDU address `0x0000`, value `FF00`, five times in one minute. | Identify repeated write pattern and risk. | | F | Client sends function `03` through a gateway with unexpected Unit Identifier `9`; gateway returns exception `0A`. | Classify as route/path evidence, not a write event. | | G | Technician proposes function `06` to a live drive setpoint because the dashboard is wrong. Process effect is unknown. | Apply safety stop and route to write-safety checklist. | | H | Saved event shows function `06` response echoing address `0x0013` and value `0x0001`; no status register is read afterward. | Explain why echo is incomplete evidence. | ## Procedure 1. Classify each card as read activity, write activity, gateway/path evidence, or safety stop. 2. For write activity, record source role, destination, Unit Identifier, function code, documented address if known, PDU address, value or quantity, approval context, and independent feedback. 3. Decide whether the event should be allowed, alerted, blocked, or escalated in a lab policy. 4. Draft one plain-language monitoring requirement for Cards C and E. 5. For Cards G and H, complete the stop condition and independent-feedback notes instead of sending a command. ## Worksheet | Card | Classification | Function | Address / Range | Source Context | Decision | Evidence To Record | |---|---|---|---|---|---|---| | A | | | | | | | | B | | | | | | | | C | | | | | | | | D | | | | | | | | E | | | | | | | | F | | | | | | | | G | | | | | | | | H | | | | | | | ## Answer Key | Card | Classification | Function | Address / Range | Source Context | Decision | Evidence To Record | |---|---|---|---|---|---|---| | A | Baseline read | `03` | `0x0009`, quantity `2` | approved HMI | Allow and baseline | source, destination, polling rate, Unit Identifier, function, range | | B | Read exposure | `04` | `0x0032`, quantity `2` | approved maintenance laptop | Allow if approved; monitor as new source | source, approval window, function, range, business need | | C | Write activity | `06` | documented `40020`, PDU `0x0013`, value `0x0001` | unknown client | Alert/escalate; block in real control policy if not approved | source, destination, Unit Identifier, function, address, value, time | | D | Approved write activity | `16` | documented `40033-40034`, PDU `0x0020`, quantity `2`, payload `00 32 00 00` | approved controller in window | Allow only with change record and independent feedback | full payload, expected meaning, echo, status readback, rollback | | E | Repeated write activity | `05` | documented coil `00001`, PDU `0x0000`, value `FF00` | unknown client | Alert/escalate; investigate repeated command pattern | count, timing, source, coil meaning, response, status effect | | F | Gateway/path evidence | `03` request plus exception `0A` | read request | unexpected Unit Identifier | Troubleshoot route; not a write alert | Unit Identifier, gateway route/path, exception, source | | G | Safety stop | proposed `06` | live drive setpoint unknown | technician request | Stop; require authorization and write-safety checklist | device, register, process effect, rollback, independent verification | | H | Incomplete write evidence | `06` response echo | `0x0013`, value `0x0001` | saved event | Require independent status read | echo, missing status, expected physical state, confirmation register | ## Plain-Language Monitoring Requirements Card C: ```text Alert when any unapproved source sends Modbus function 06 to the synthetic command register at PDU address 0x0013. Record source, destination, Unit Identifier, value, response, and time. ``` Card E: ```text Alert when a source sends repeated Modbus write function 05 requests to coil 0x0000 more than once inside the lab review window. Record count, timing, source, response, and coil meaning. ``` ## Expected Observations - Read events still matter for exposure and baselining, but write events require stricter safety review. - Unknown write sources deserve escalation even when the Modbus response is normal. - A write echo is protocol evidence, not physical proof. - Gateway exceptions are useful security context but not automatically write activity. - Tool-specific rules should come after the plain-language detection requirement. ## Troubleshooting Notes - Do not convert these requirements into production firewall, Suricata, Snort, Zeek, or gateway rules until a tool version, parser behavior, test PCAP, and expected output are verified. - Do not use this lab as permission to write to real devices. - Keep source IP examples and address ranges synthetic unless a reviewed lab PCAP is selected. ## Check Questions 1. Which cards contain write functions? 2. Which card proves that a write response echo is incomplete evidence? 3. Which card is a safety stop rather than a technical troubleshooting step? 4. Which card should be handled as gateway route/path evidence? 5. Why are plain-language requirements drafted before tool-specific syntax? ## Instructor Notes - Keep the exercise defensive: identify, record, alert, stop, and verify. - Use Card G to reinforce that the safest action may be not sending a Modbus command. - Add a Wireshark/PCAP extension only after packet-capture licensing and display fields are verified. - Add Suricata, Snort, or Zeek syntax only after selected versions are installed, expected outputs are documented, and the [Safety Review Appendix](https://learnmodbus.studioseventeen.io/resource/safety-review-appendix) confirms the exercise remains defensive and isolated. ## Source Notes - Official protocol source: Modbus Application Protocol Specification V1.1b3 for write function codes and response shape. - Official security source: Modbus/TCP Security Protocol Specification for TLS and certificate-based security context. - Defensive security basis: NIST SP 800-82 Rev. 3, CISA ICS guidance, and MITRE ATT&CK for ICS. - Internal course source: Module 15 lesson, [Threat-to-control worksheet](https://learnmodbus.studioseventeen.io/resource/threat-to-control-worksheet), and [Write-safety checklist](https://learnmodbus.studioseventeen.io/resource/write-safety-checklist). - Synthetic source: all event cards are course-authored fixtures, not captured traffic. ## Knowledge check # Module 15 Quiz: Security And Safety ## Questions 1. Which statement best describes classic Modbus TCP? A. It normally provides user authentication for each register. B. It is commonly plaintext and relies on surrounding architecture for access control. C. It encrypts every payload by default. D. It proves that every write is physically safe. 2. What does Modbus Security primarily add? A. TLS transport protection and certificate-based identity for Modbus TCP. B. A universal register map. C. Automatic proof that a motor started safely. D. A replacement for documenting function codes. 3. Which function codes should receive extra safety and monitoring attention when supported? A. `03` and `04` only. B. `05`, `06`, `15`, `16`, `22`, and `23`. C. `01` and `02` only. D. Exception functions only. 4. A function `06` response echoes the requested address and value. What does that prove? A. The physical process reached the intended final state. B. The server returned the expected protocol-level write response shape. C. The command was authorized by plant procedure. D. The write value is safe for every device. 5. An unknown client writes to a synthetic command register in isolated lab evidence. What is the best learner action? A. Ignore it because the response was normal. B. Record source, destination, Unit Identifier, function code, address, value, response, and time; draft an alert/escalation requirement. C. Run the same write against a production device. D. Change word order. 6. Why is a VPN not enough by itself to make classic Modbus commands safe? A. VPNs change holding registers into input registers. B. VPN access does not authorize specific Modbus commands or prove safe process state. C. VPNs make Modbus exception responses impossible. D. VPNs remove the need for monitoring. 7. A learner wants to test a write to a live drive setpoint because the dashboard value looks wrong. The process effect is unknown. What should happen? A. Stop and complete authorization, precondition, rollback, and independent-verification checks. B. Send function `06` and trust the echo. C. Increase polling rate. D. Try a different Unit Identifier first. 8. Which source boundary is correct? A. Tool-specific Suricata, Snort, Zeek, firewall, and Wireshark syntax must be verified against selected versions before release. B. Any blog post can define official Modbus write semantics. C. A synthetic lab card is captured production traffic. D. Modbus Security changes all register meanings. ## Answer Key 1. B. Classic Modbus TCP is commonly plaintext and normally lacks built-in user authentication or command authorization. 2. A. Modbus Security adds TLS and certificate-based identity around Modbus TCP; it does not solve register-map or process-safety semantics. 3. B. These are common write-related function codes and deserve extra monitoring and safety review where supported. 4. B. A write echo is protocol evidence, not proof of physical state, authorization, or safe effect. 5. B. Defensive handling starts with evidence capture and a plain-language alert/escalation requirement. 6. B. A VPN can protect transport access, but it does not authorize specific Modbus functions, ranges, or process states. 7. A. Unknown live write effects require a safety stop before any command. 8. A. Tool behavior and detection syntax are version-specific and must be verified. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A/C invent built-in authentication or encryption for classic Modbus TCP, and D treats transport access as physical safety proof. | | 2 | A | B invents a universal register map, C overstates physical safety guarantees, and D ignores that function codes still need documentation. | | 3 | B | A/C include only read functions, and D describes exception responses rather than write-capable operations. | | 4 | B | A/C/D overstate what a protocol-level write response proves about physical state, procedure, or universal safety. | | 5 | B | A ignores defensive evidence, C moves a lab finding into production unsafely, and D changes interpretation instead of recording the write event. | | 6 | B | A/C are false protocol claims, and D removes monitoring despite remaining command and process-risk concerns. | | 7 | A | B trusts the echo too much, while C/D change unrelated communication settings before authorization and safety checks. | | 8 | A | B elevates secondary sources above protocol authority, C mislabels synthetic evidence, and D gives Modbus Security semantic power it does not have. | ## Instructor Notes - Use questions 4 and 7 to reinforce that protocol acceptance is not physical safety. - Use question 8 to keep detection syntax gated until tool verification. - Add PCAP or monitoring-tool questions only after the lab evidence is version-pinned. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for write single coil/register shape and echo boundary, write multiple coils/registers quantity limits, mask write register, read/write multiple registers, Modbus Security wraps Modbus/TCP in TLS, Modbus Security certificates and role authorization, Modbus Security TLS requirements, and IANA service name `mbap-s` on port `802`. - Defensive architecture, monitoring, and operational-risk framing should remain tied to [security-citation-map.md](https://learnmodbus.studioseventeen.io/resource/security-citation-map) primary-source anchors and selected tool evidence before release. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 15/16 · v1.0.0 · Exported for offline / agent use._ # Module 16: Capstone: Real Device Integration > Bring a real or simulated device online with a reviewable evidence package. **Phase:** Capstone **Estimated time:** 8 min **Release status:** Published **Content version:** 1.0.0 **Source:** https://learnmodbus.studioseventeen.io/lesson/capstone-real-device-integration ## What you'll be able to do - Plan an integration from spec to first reliable poll. - Build an evidence package another engineer can review. - Hand off a register map with units, scales, and verification notes. ## Three things people get wrong 1. **Skipping the pre-flight read.** Before any write, do a complete read sweep and snapshot the device's pre-state. 2. **Treating 'works in the lab' as done.** Field cabling, baud limits, and gateway behavior re-test in production — budget for it. 3. **Not versioning the register map.** Treat the map as code. Pin a version with the firmware revision it was verified against. ## From the field **The handover that survived a rebadge** An integrator left a tidy package: register map, capture file, scaling notes, and a one-page test script. Two years later the device was rebadged by a competitor. The same package, with two register addresses changed, brought the new unit online in an afternoon. Documentation is the deliverable. ## References - [Modbus Application Protocol V1.1b3](https://www.modbus.org/file/secure/modbusprotocolspecification.pdf) - [Synthetic device spec — Stratos VFD 7.2](https://learnmodbus.studioseventeen.io/devices/stratos-vfd-72) ## Lesson # Module 16 Lesson: Capstone Real Device Integration ## Learner Outcome By the end of this module, learners can turn a synthetic or reviewed register map into a documented Modbus integration package with correct requests, decoded values, polling plan, troubleshooting evidence, safety notes, and a reusable normalized handoff structure. ## Key Concepts - A register map is not an integration until its assumptions are tested. - Every point needs both the source-facing reference and the protocol request actually sent. - Address base, table, function code, Unit Identifier or serial server address, quantity, type, word order, scale, unit, access, and validity conditions must be explicit. - Start with read-only evidence; write-capable points are boundaries unless the lab is simulated or formally approved. - Normalization turns vendor-specific raw points into consistent tags, values, quality, and context. - The final package should be repeatable by another learner or integrator without hidden assumptions. ## Key Terms - Source intake: the recorded source map, manual, fixture, or evidence used to start the integration. - Normalized tag: a stable internal name for a decoded point. - Evidence package: the set of source rows, requests, responses, decoded values, assumptions, and review notes that prove the integration work. - Reviewed vendor map: a named vendor source with revision, firmware/applicability, and license/source notes checked. - Commissioning handoff: the final package another reviewer can use to understand what was proven and what remains unresolved. - Modmapper-ready: structured enough for later import/export review after tool behavior is verified. ## Source-Grounded Explanation ### The Capstone Is Evidence Work The capstone combines the course skills into one workflow: 1. Identify the exact transport path: RTU, ASCII, TCP, Modbus Security, or gateway. 2. Select a source map: the synthetic course map by default, or a reviewed vendor map after source/license review. 3. Convert documented references into function code, table, PDU address, and quantity. 4. Poll read-only points first. 5. Decode raw values into engineering meaning with type, signedness, word order, scale, unit, state, and freshness. 6. Classify and resolve or explicitly defer at least two troubleshooting cases. 7. Review safety and security boundaries before any write-capable point is tested. 8. Package a normalized, reusable integration artifact. The grading target is not "the dashboard looks nice." The target is a defensible integration package: someone else can read it, repeat the tests, and understand what is proven, what is assumed, and what remains unresolved. ### Required Evidence Per Point Each selected point should include: | Field | Purpose | |---|---| | Source label | Synthetic course map, reviewed vendor manual, official rule, tool behavior, field note, or needs verification. | | Raw/vendor label | Preserves the original wording from the source map. | | Normalized tag | Creates a stable internal name such as `meter.voltage.l1_l2`. | | Transport and responder | TCP Unit Identifier, serial server address, or gateway route. | | Function code and table | Separates coil/discrete/input/holding register assumptions. | | Documented address | What the source says. | | PDU address | What the request sends. | | Quantity | Number of coils/registers requested. | | Data meaning | Type, signedness, word order, scale, unit, enum, bitfield, sentinel, state, quality. | | Expected response | Normal response shape and likely exception/failure mode. | | Evidence | Saved bytes, simulator output, tool log, source note, screenshot, or reviewer note. | ### Track A: Synthetic No-Hardware Capstone This is the default track until a simulator/toolchain is pinned and real vendor maps are reviewed. It uses `release/synthetic-course-device-map.md` and course-authored saved response examples. The learner must label synthetic behavior clearly and must not present it as a real device. Required minimum: - At least six normalized points. - At least one value from each category: bitfield/status, 16-bit scaled value, 32-bit value, enum/state, quality/sentinel/freshness, and write boundary. - Two troubleshooting cases from Module 14, such as off-by-one wrong value plus reserved-gap exception or unresolved source row. - One safety/security note from Module 15. - One commissioning-report excerpt. ### Track B: Reviewed Vendor-Map Extension Use this only after source and license review. The learner must record: - Vendor, model, document title, revision, firmware/applicability. - Source/license notes. - Configuration assumptions. - Any vendor-specific behavior, such as word order, read limits, local/remote mode, cache/freshness, or write workflow. - Evidence that vendor-specific behavior was not taught as a generic Modbus rule. ### Optional Modmapper-Ready Thinking After Tool Verification The capstone should separate raw protocol evidence from reusable tags: ```text Source row -> request fields -> raw response -> decoded value -> normalized tag -> quality/state -> evidence ``` A Modmapper-ready package should preserve enough structure to be imported, reviewed, validated, and reused later after import/export behavior and licensing are verified: - Stable tag names. - Source labels. - Request fields. - Decode rules. - Quality and validity rules. - Evidence and unresolved assumptions. ## Practical Example: Synthetic Energy Meter Package Scenario: learners use the synthetic course energy meter map. | Item | Value | |---|---| | Transport | Modbus TCP | | Unit Identifier | `1` for the synthetic simulator track | | Point | Line voltage L1-L2 | | Function code | `03` Read Holding Registers | | Documented register | `40010` | | Actual PDU address | `0x0009` | | Quantity | `1` register | | Data type | unsigned 16-bit | | Scale/unit | raw `/10 V` | | Expected normal response | Function `03`, byte count `2`, data `09 C4` | | Expected decoded value | `250.0 V` | | Likely failure mode | Off-by-one wrong value if PDU address `0x000A` is used; exception `02` in the synthetic fixture when the server reports an illegal data address | Evidence row: | Tag | Evidence | |---|---| | `meter.voltage.l1_l2` | Synthetic map row plus response `03 02 09 C4`; PDU address `0x0009`; decode `0x09C4 = 2500`, scale `/10 V = 250.0 V`. | The learner should also include an "assumption overturned by evidence." Example: the source row `40010` did not mean PDU address `40010`; it meant holding-register table with first PDU address `9` when using one-based `40001` notation. ## Common Pitfalls - Copying a vendor table without proving address base and function code. - Treating a dashboard screenshot as enough evidence. - Hiding word-order guesses. - Polling across reserved gaps because it is convenient. - Ignoring quality, sentinel, stale, or state context. - Including write-capable points without a safety boundary. - Treating synthetic behavior as product behavior. - Using a vendor map without document revision, firmware/applicability, or license notes. - Packaging only final settings and omitting troubleshooting evidence. ## Instructor Flow 1. Show the capstone brief and rubric before learners start. 2. Require a source intake row and normalized map excerpt. 3. Review one point together from documented address to decoded telemetry. 4. Require two troubleshooting cases and one safety/security stop. 5. Grade evidence quality, source labeling, and reusability more heavily than visual polish. ## Check-Your-Understanding 1. What fields must another integrator see to reproduce a Modbus read? 2. Why does the capstone start read-only? 3. What evidence proves an address-base assumption? 4. What evidence proves word order? 5. What makes a normalized tag different from a raw vendor register label? ## Source Notes - Official protocol basis: Modbus Application Protocol Specification for data model, function codes, PDU fields, normal/exception responses, and quantity limits. - Official TCP basis: Modbus Messaging on TCP/IP Implementation Guide for MBAP, Unit Identifier, and TCP behavior. - Official serial basis: Modbus over Serial Line Specification and Implementation Guide if a serial or gateway extension is selected. - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, normal response vs exception response, exception codes and exception response PDU shape, relevant function quantity rows, MBAP header fields, Unit Identifier and gateway routing, RTU/ASCII frame fields, serial server address range and broadcast address where the selected capstone path uses those transports, and Modbus Security TLS wrapping if the secure track remains listed. - Internal synthetic basis: `release/synthetic-course-device-map.md` and Module 5-16 draft packages. - Vendor-specific basis: real-device capstone work requires reviewed vendor map source, document revision, firmware/applicability, and source/license notes. - Tool behavior: simulator, Node-RED, screenshots, packet captures, Modmapper import/export, and decoder/test harness output require version-pinned verification before learner release. ## Completion Checkpoint Before completing the course, learners should assemble a synthetic no-hardware evidence package with source intake, normalized rows, request/response evidence, decoded values, troubleshooting cases, safety notes, unresolved assumptions, and a reviewer-ready handoff. ## Reusable Assets - [Capstone brief and rubric](https://learnmodbus.studioseventeen.io/resource/capstone-brief) - [Capstone integration lab](https://learnmodbus.studioseventeen.io/lesson/capstone-real-device-integration?page=lab-1) - [Sample evidence package](https://learnmodbus.studioseventeen.io/resource/sample-evidence-package) - [Commissioning report template](https://learnmodbus.studioseventeen.io/resource/commissioning-report-template) - [Normalized register map template](https://learnmodbus.studioseventeen.io/resource/normalized-register-map-template) - [Module 16 quiz](https://learnmodbus.studioseventeen.io/lesson/capstone-real-device-integration?page=quiz) ## Labs ### Lab 1 # Lab 32: Capstone Integration Package ## Learner Outcome Learners produce a reusable Modbus integration package from the synthetic course map or a reviewed vendor map, proving address conversion, request fields, data decoding, troubleshooting, safety boundaries, and normalized handoff structure. ## Prerequisites - Modules 1-4: message model, data tables, function codes, and exceptions. - Modules 5-8: addressing, register maps, data types, scaling, quality, and telemetry meaning. - Modules 9-13: serial, RTU/ASCII, TCP, and gateway evidence. - Module 14: troubleshooting workflow and evidence log. - Module 15: defensive security and write-safety stop. ## Safety And Scope Track A is no-hardware and uses synthetic data. Do not connect to production systems, scan networks, or write to real devices. Track B uses a real/vendor map only after source and license review. Optional hardware work is read-only by default and requires instructor approval before any write. ## Track A: Synthetic No-Hardware Capstone Use: - [Synthetic course device map](https://learnmodbus.studioseventeen.io/resource/synthetic-course-device-map) - [Normalized register map template](https://learnmodbus.studioseventeen.io/resource/normalized-register-map-template) - [Troubleshooting evidence log](https://learnmodbus.studioseventeen.io/resource/troubleshooting-evidence-log) - [Commissioning report template](https://learnmodbus.studioseventeen.io/resource/commissioning-report-template) - [Write-safety checklist](https://learnmodbus.studioseventeen.io/resource/write-safety-checklist) - [Sample evidence package](https://learnmodbus.studioseventeen.io/resource/sample-evidence-package) ## Required Deliverables | Deliverable | Minimum Standard | |---|---| | Source summary | Identifies synthetic map or reviewed vendor map, source label, transport, Unit Identifier/server address, and safety scope. | | Normalized map | At least six points with documented address, PDU address, function, quantity, type, scale/unit, access, validity, evidence, and assumptions. | | Request evidence | Saved bytes, simulator output, or tool log for at least four read-only points and one simulated write boundary. | | Decode notes | Shows raw-to-typed-to-engineering-value conversion for at least one 16-bit and one 32-bit value. | | Polling plan | Splits reads around reserved gaps and groups by function/table/update need. | | Troubleshooting log | Includes at least two no-response, exception, wrong-value, unresolved-source, polling-gap, or write-safety cases with evidence and resolution or explicit deferral. | | Safety/security notes | Identifies write boundary, write-safety stop, monitoring concern, and any unresolved risk. | | Handoff package | Includes commissioning report excerpt and Modmapper-ready normalized tags. | ## Synthetic Required Points | Tag | Source Row | Required Evidence | |---|---|---| | `meter.status.word` | Device status word `40001` | FC03, PDU `0x0000`, U16 bitfield, response `03 02 00 03`, running plus warning. | | `meter.voltage.l1_l2` | Line voltage `40010` | FC03, PDU `0x0009`, U16, scale `/10 V`, response `03 02 09 C4`, `250.0 V`. | | `meter.frequency.ac` | AC frequency `30021` | FC04, PDU `0x0014`, U16, scale `/100 Hz`, response `04 02 17 70`, `60.00 Hz`. | | `meter.energy.import.wh` | Total energy import `40031` | FC03, PDU `0x001E`, quantity `2`, U32 high-word-first, response `03 04 00 01 86 A0`, `100000 Wh`. | | `meter.mode.operating` | Operating mode `40093` | FC03, PDU `0x005C`, U16 enum, response `03 02 00 02`, `Remote`. | | `meter.temperature.sensor` | Lab temperature reading `40094` (Module 8 `lab_temperature_reading`) | FC03, PDU `0x005D`, S16, scale `/10 deg C`, sentinel `0x7FFF`; response `03 02 7F FF` publishes `null` with quality `invalid`. | | `meter.temperature.undocumented` | Temperature (undocumented) `Offset 60` | Mark table/function/address base unresolved unless additional evidence is supplied. | | `meter.command.word` | Command word `40101` | Simulated write boundary only; do not send real writes. Record FC06/FC16 response shape and independent-status requirement. | ## Procedure 1. Create a source summary with transport, Unit Identifier, address convention, safety scope, and source label. 2. Normalize at least six points into the template. 3. For each point, record function code, documented address, PDU address, quantity, data type, scale/unit, and expected response. 4. Decode at least one 16-bit scaled value and one 32-bit value from raw response bytes, and apply sentinel/quality handling to at least one value — for example, publish `null` with quality `invalid` when `meter.temperature.sensor` reads the `0x7FFF` sentinel instead of scaling it into a fake temperature. 5. Build a polling plan that avoids the reserved `40050-40059` gap. 6. Classify at least two troubleshooting cases: - off-by-one wrong value, - exception `02` from a map gap, - wrong table/function, - unresolved `Offset 60`, - or write-safety stop for `command_word`. 7. Complete the commissioning report excerpt. 8. Complete the safety/security notes. 9. Compare the package against the rubric. ## Answer Key / Instructor Notes Strong packages should: - Preserve `40010` as the documented reference and `0x0009` as the PDU address. - Use function `04` for `30021` input register evidence. - Decode `03 04 00 01 86 A0` as high-word-first U32 `100000 Wh`. - Mark `Offset 60` unresolved instead of inventing table/function/address base. - Apply the `0x7FFF` sentinel on `meter.temperature.sensor` before scaling, publishing `null`/invalid rather than a fabricated temperature. - Avoid contiguous reads across `40050-40059`. - Treat `40101` as a simulated write boundary and require independent status feedback. - Include at least one explicit source label per row. - Include one assumption overturned by evidence. - Include two troubleshooting entries, with at least one resolved by changing evidence-backed assumptions rather than guessing. ## Expected Observations - A strong package keeps documented references, PDU addresses, function codes, data types, scale/unit, and source labels visible in the same evidence trail. - Reserved gaps and unresolved source rows should cause split reads or explicit deferral, not guessed values. - Troubleshooting entries should distinguish no response, exception response, wrong-but-valid values, and unresolved source evidence. - Simulated write boundaries should remain simulator-only and should require independent status feedback before any real-device extension. ## Troubleshooting Notes - If a learner reads across `40050-40059`, split the polling plan and record the reserved-gap evidence. - If `Offset 60` is normalized without table/function/address-base evidence, mark the row unresolved and request a better source. - If a wrong value is plausible, test address base, table/function, data type, scale, and word order one at a time with evidence. - If a command word is included, stop at the safety gate unless authorization, reviewed device source, rollback, and independent feedback evidence exist. ## Optional Track B: Reviewed Vendor Map Only add a real/vendor map when: - Source/license review is complete. - Product, model, firmware/applicability, document title, and revision are recorded. - Optional hardware is isolated and read-only by default. - Any vendor-specific word order, read limit, gateway behavior, cache/freshness, write workflow, or safety interlock is labeled product-specific. ## Check Questions 1. Which points are safe read-only evidence points? 2. Which point must remain unresolved until table/function/address base are proven? 3. Which read should be split to avoid reserved gaps? 4. What proves that `meter.energy.import.wh` uses high-word-first word order? 5. What makes the final package reusable by another integrator? ## Source Notes - Synthetic source: all Track A values are course-authored fixtures from the synthetic course map. - Official protocol source: Modbus Application Protocol Specification for function codes, addressing, response shape, and exception behavior. - Internal course source: Module 5-16 packages, capstone brief, normalized map template, commissioning report template, troubleshooting log, and write-safety checklist. - Release gate: simulator output, Node-RED/dashboard screenshots, Modmapper import/export behavior, and real/vendor map track remain pending. ## Knowledge check # Module 16 Quiz: Capstone Real Device Integration ## Questions 1. Which capstone evidence is required to reproduce a Modbus read? A. Dashboard color and title only. B. Function code, documented address, PDU address, quantity, responder, data type, scale/unit, and source evidence. C. Vendor logo only. D. The final scaled value only. 2. A source map lists line voltage at `40010` using one-based `40001` notation. What PDU address should the capstone try first? A. `40010` B. `10` C. `9` D. `0` 3. The synthetic source row says `Offset 60` for temperature but does not prove table, function code, or address base. What should the learner do? A. Invent a holding-register address. B. Mark the point as unresolved until evidence is available. C. Treat it as a coil. D. Use it as proof of simulator failure. 4. Why should a capstone avoid reading one large block across `40050-40059` in the synthetic map? A. Reserved gaps may make a contiguous read fail even when documented points outside the gap are valid. B. Modbus never allows more than one register. C. TCP cannot carry register reads. D. Scaling requires one request per bit. 5. A write response echoes a command value for `40101`. What must the capstone also include? A. Independent status or simulator-state evidence and a write-safety boundary. B. A production write test. C. A claim that the process changed physically. D. No additional evidence. 6. What is the difference between a raw vendor label and a normalized tag? A. A raw vendor label preserves source wording; a normalized tag gives the integration a stable internal name and context. B. They are always identical. C. Normalized tags replace evidence. D. Vendor labels prove word order. 7. What must be true before using a real vendor map for Track B? A. The map is interesting. B. Source/license review, model, revision, firmware/applicability, and vendor-specific caveats are recorded. C. The learner hides document assumptions. D. The device is on the production network. 8. Which capstone grading principle is most important? A. Evidence quality and source labeling matter more than visual polish. B. The most colorful dashboard wins. C. Any copied vendor table is complete. D. Unresolved assumptions should be removed from the submission. ## Answer Key 1. B. Reproducible reads require both source-facing and wire-level request fields plus data meaning and evidence. 2. C. If `40001` is the first holding register, documented `40010` maps to PDU address `9`. 3. B. Unclear source rows should be labeled unresolved, not invented. 4. A. Reserved gaps are a common polling-plan hazard. 5. A. A write echo is not physical proof; capstones need safety boundaries and independent confirmation. 6. A. Normalization turns source-specific labels into reusable project tags without losing evidence. 7. B. Real/vendor tracks require source and applicability review before use. 8. A. The capstone is graded on defensible evidence and reusable handoff quality. ## Distractor Review Notes | Question | Correct | Why The Distractors Are Wrong | |---:|---|---| | 1 | B | A/C/D are presentation or partial-result details that cannot reproduce a Modbus read. | | 2 | C | A sends documentation notation, B uses a one-based item number as the PDU address, and D is the first holding-register offset, not `40010`. | | 3 | B | A invents a table and address, C changes the data model without evidence, and D blames the simulator before resolving the source row. | | 4 | A | B falsely limits register reads, C denies TCP register reads, and D confuses scaling with request grouping. | | 5 | A | B is unsafe, C overclaims physical effect, and D ignores the safety and independent-verification evidence required after a write echo. | | 6 | A | B erases the distinction, C removes evidence, and D treats a label as proof of word order. | | 7 | B | A is insufficient source qualification, C hides assumptions, and D violates the no-production-default course boundary. | | 8 | A | B rewards presentation over evidence, C overtrusts copied tables, and D hides uncertainty instead of labeling it. | ## Instructor Notes - Use questions 2 and 3 to check whether learners preserve address uncertainty. - Use question 5 to connect Module 16 back to Module 15. - Add tool or dashboard-specific questions only after simulator and UI evidence are verified. ## Source Notes - Official citation targets: [official-citation-map.md](https://learnmodbus.studioseventeen.io/resource/official-citation-map) rows for four primary logical data tables, addressing model and zero-based PDU addresses, public function-code categories, relevant function-specific rows, normal response vs exception response, exception codes and exception response PDU shape, write single register shape and echo boundary, MBAP header fields, Unit Identifier and gateway routing, RTU/ASCII frame fields, and serial server address range and broadcast address where the selected capstone path uses those transports. - Real/vendor capstone tracks require source/license review, model, revision, firmware/applicability, and source-specific caveats before publication. --- _Learn Modbus · learnmodbus.studioseventeen.io · Module 16/16 · v1.0.0 · Exported for offline / agent use._