— Coils, Inputs & Registers

(Module 4 · Modbus Data Model & Function Codes)


Learning objectives

By the end of this chapter you will be able to

  1. Name, locate, and differentiate the four canonical Modbus data tables.
  2. Convert between “human” address notation (e.g. 40017) and zero-based PDU addresses (0x0010).
  3. Explain the read/write permissions and typical payload widths of each table.
  4. Detect and fix the three most common addressing mistakes (off-by-one, map overlap, 32-bit packing error).
  5. Design a clean, future-proof register map for a brand-new device.

10.1 Why a Data Model?

Modbus frames are payload-agnostic; the protocol doesn’t know you’re sending “motor speed” or “tank level”. Consistent semantics come from a logical model that every master and slave agrees on:

TableAbbrev.PurposeTypical Real-World Item
Coils0XRead/Write single bitsStart pump, open valve
Discrete Inputs1XRead-only bitsLimit switch, E-stop status
Input Registers3XRead-only 16-bit wordsTemperature, pressure
Holding Registers4XRead/Write 16-bit wordsSet-point, PID gain

Memory model mantra “Bits live in 0-/1-tables; words live in 3-/4-tables.”


10.2 Table 0X — Coils (Read/Write Bits)

Address space: 00001 – 09999 (spec) PDU offset: 0×0000 – 0×270E
Function codes: 01 Read Coils, 05 Write Single Coil, 15 Write Multiple Coils

Field noteDetail
Size1 bit each; packed LSB-first into bytes in responses.
LatencyFastest write path (single‐byte toggle).
Use-casesStart/stop, open/close, enable/disable, heartbeat LED.

Tip Group change-of-state coils into a contiguous block so a single FC15 can toggle up to 1 968 coils in one telegram.


10.3 Table 1X — Discrete Inputs (Read-Only Bits)

Address space: 10001 – 19999 PDU offset: 0×0000 – 0×270E
Function code: 02 Read Discrete Inputs

Field noteDetail
Electrical originUsually externally wired to the slave; PLC may scan card and mirror results here.
PollingRead-only → safest table to burst‐poll at high frequency.
Edge detectionMaster must implement software debouncing if contact bounces faster than poll rate.

10.4 Table 3X — Input Registers (Read-Only 16-bit Words)

Address space: 30001 – 39999 PDU offset: 0×0000 – 0×270E
Function code: 04 Read Input Registers

Field noteDetail
Data width16 bits each; devices may store sensor value raw or scaled.
Scaling patterns• Integer with implicit decimal (e.g. 123 → 12.3 °C)• Fixed-point (Q15, Q8.8)• IEEE-754 floating-point (32-bit spans two regs).
When to chooseMeasurements that the controller must not overwrite (true read-only).

10.5 Table 4X — Holding Registers (Read/Write 16-bit Words)

Address space: 40001 – 49999 PDU offset: 0×0000 – 0×270E
Function codes: 03 Read, 06 Write Single, 16 Write Multiple, 23 Read/Write Multiple

Field noteDetail
VersatilityMost‐abused table – holds everything from recipe strings to 32-bit floats to packed BCD.
Multi-word values32-bit / 64-bit numbers span consecutive registers.
Read-modify-write hazardTwo masters writing overlapping blocks may clobber each other. Use FC23 where possible or allocate non-overlapping address blocks per master.

10.6 Addressing Conventions — Zero vs One Based

10.6.1 The dual-world dilemma

Human Notation (Datasheet)PDU Fields (Hi byte + Lo byte)
Coil 00001Start Addr = 0x0000
Holding Register 40017Start Addr = 0x0010

Why? The spec’s “human” table numbers start at 1, but the PDU uses zero-based offsets.

10.6.2 Conversion formulae

PDU_offset = Human_number  -  Table_base
Human_number = PDU_offset + Table_base

Where Table_base is 0, 10000, 30000, or 40000 depending on table.

Pitfall #1 Many PLC IDEs (e.g. Siemens TIA) already expect zero-based values; if you paste datasheet numbers directly, every read will be off by 1.

10.6.3 Prefix vs full numeric style

StyleExampleComment
Prefixed4x0017Unambiguous, preferred in mixed systems.
Full numeric40017Common in legacy manuals, can mislead newcomers.

10.7 Mapping Real-World Data to Registers

TagTypeScalingSuggested TableReason
Motor Run/StopboolCoil 0XCommand must be writable.
Motor RunningFBboolDiscrete Input 1XRead-only status.
Tank Levelfloat32 (cm)IEEE-754Holding 4X (2 regs)Supervisor may need to write simulated value.
Firmware VersionASCII(8)2 chars per regHolding 4XRarely changed but writable by OEM flasher.

Design tip Allocate even addresses for the first word of every multi-word value—this preserves alignment if you ever migrate to 32-bit “extended registers”.


10.8 Common Data-Packing Patterns

WidthRegistersWord OrderByte OrderWhere found
32-bit float2Big > Little (Modbus default)Big > LittleSchneider drives
32-bit float (“ABCD”)2BigBigWago, Beckhoff
32-bit inverted words (“BADC”)2SwappedBigRockwell legacy
32-bit unsigned int2BigBigEnergy meters kWh
64-bit double4Big–little pairBigNewer RTUs

Byte-swap cheatsheet

# Python helper: convert two Modbus regs to float32 with possible word swap
def regs_to_float(reg_hi, reg_lo, swap=False):
    import struct
    words = [reg_hi, reg_lo]
    if swap:
        words.reverse()
    raw = struct.pack('>HH', *words)   # big-endian words
    return struct.unpack('>f', raw)[0]

10.9 Troubleshooting Address & Data Errors

SymptomRoot causeQuick testFix
All values zeroOff-by-one start addressRead 40000 and 40001; one will show expectedSubtract 1 from start register
Value 256× too highByte-swapSwap words in logicAdjust word order toggle
Coil write appears but resetsWriting to Discrete Input (read-only)Check FC05 response; slave returns exception?Use address 0X not 1X
High word stuck at 0xFFFFSigned/unsigned mismatchCompare hex dump vs datasheetTreat as signed 16-bit

10.10 Best-Practice Register-Map Design

  1. Freeze the map early — downstream SCADAs will hard-code it.
  2. Group by poll frequency – fast-changing telemetry in one contiguous block, slow config in another.
  3. Avoid bit-packing inside words – modern bandwidth is cheap; clarity beats density.
  4. Reserve 20 % head-room at the end of each table for future tags.
  5. Publish a spreadsheet with: address, mnemonic, units, data-type, scaling, R/W flag, last-changed date.

(A ready-to-use Excel template is provided in Appendix A4.)


Chapter Recap

  • Four tables = two bit domains (0X/1X) + two word domains (3X/4X).
  • Datasheet numbers start at 1; PDUs start at 0 → watch the offset!
  • Holding registers are workhorses but risky without a clear write policy.
  • Multi-word data must document word + byte order to avoid endian hell.
  • A disciplined register map today saves months of retro-fits tomorrow.

[Placeholders for your media team]

IDVisual idea
Fig-10-14-table “memory map” heat-map graphic
Fig-10-2Off-by-one conversion diagram
Fig-10-332-bit float packing (normal vs swapped)
Fig-10-4Sample best-practice register sheet screenshot

Next up: Chapter 11 – Mastering Modbus Function Codes — The Verbs of Communication, where we’ll pair the data tables you just learned with the exact opcodes that read, write, and diagnose them.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts