Modbus Register Address Calculator (Modicon ↔ PDU, byte order, data types)

PDU offset = Modicon_1based − 1 ; byte_order determines value interpretation Modicon 5/6-digit, PDU, hex, ABCD/CDAB/BADC/DCBA

Modbus addressing has three overlapping conventions in active use. Modicon 5-digit (40001) and 6-digit (400001) are 1-based with a type prefix. Standard Modbus PDU is 0-based with no prefix. When vendor documentation says "register 40001," it almost always means PDU offset 0 (holding register). If your value looks wrong, first check whether the vendor uses 1-based or 0-based addressing, then verify byte order for 32-bit types.

Why Modbus addressing confuses everyone

Modbus is one of the oldest and most widely deployed industrial communication protocols — and its addressing conventions are the single biggest source of “why doesn’t this work?” support tickets in the industrial world. The reason is that three overlapping addressing conventions are in daily use, and vendor documentation freely switches between them without explanation. This calculator exists to make the translation explicit.

How to use this calculator

  • Address converter — translate between Modicon-style addresses (like 40001) and PDU/protocol addresses (like 0x0000). Works both directions. Shows the applicable function codes so you know how to read or write each type.
  • Byte order / data type — enter one or more register values and see how they’re interpreted as INT16, INT32, REAL/FLOAT32, LREAL/DOUBLE64, etc. in all four common byte orders (ABCD, CDAB, BADC, DCBA). Also reverse: enter a target value and see what raw registers to send for each order.

The three addressing conventions

1. Modicon 5-digit addressing

The classic style you’ll see in older documentation and most SCADA / HMI tools:

  • 00001–09999 — Coils (1-bit read/write outputs)
  • 10001–19999 — Discrete Inputs (1-bit read-only)
  • 30001–39999 — Input Registers (16-bit read-only)
  • 40001–49999 — Holding Registers (16-bit read/write)

The first digit is a type marker, and the remaining four digits are the offset starting from 1. So 40001 is “holding register at 1-based offset 1” — which the protocol frame carries as PDU offset 0. This off-by-one trips up almost everyone the first few times.

2. Modicon 6-digit addressing

Same idea but extended for devices with more than 9999 registers. The offset is 5 digits instead of 4:

  • 000001–065536 — Coils
  • 100001–165536 — Discrete Inputs
  • 300001–365536 — Input Registers
  • 400001–465536 — Holding Registers

Same base rule: subtract 1 to get PDU offset. 400001 = PDU 0. 412346 = PDU 12345.

3. PDU / protocol addressing

What actually appears in the Modbus protocol frame on the wire. Always 0-based, no type prefix. The type is signalled by the function code instead:

  • FC01 (Read Coils) reads coils at their PDU offset
  • FC02 (Read Discrete Inputs) reads discrete inputs at their PDU offset
  • FC03 (Read Holding Registers) reads holding registers at their PDU offset
  • FC04 (Read Input Registers) reads input registers at their PDU offset
  • FC05, FC06, FC15, FC16 handle writes

Modern Modbus libraries (pymodbus, node-red-contrib-modbus, libmodbus) usually accept PDU offsets directly. Older tools and vendor documentation usually use Modicon addressing.

The formulas

Both directions of the addressing conversion:

PDU offset = Modicon 1-based offset − 1

Modicon 1-based offset = PDU offset + 1

The type prefix (0/1/3/4) is prepended to the padded Modicon offset for display. Function code selection follows from register type.

Function code reference

The nine standard function codes and what they operate on:

  • FC01 Read Coils (multiple 1-bit outputs)
  • FC02 Read Discrete Inputs (multiple 1-bit read-only)
  • FC03 Read Holding Registers (multiple 16-bit r/w) — the most common by far
  • FC04 Read Input Registers (multiple 16-bit read-only)
  • FC05 Write Single Coil (1 bit)
  • FC06 Write Single Holding Register (16-bit)
  • FC15 Write Multiple Coils
  • FC16 Write Multiple Holding Registers — the most common write
  • FC23 Read/Write Multiple Registers (both operations in one transaction)

If your device documentation only refers to register numbers (like “read register 40100”), it implicitly means using FC03 (holding register read) since the “4” prefix marks it as a holding register. Coils use FC01/05/15, discrete inputs use FC02, input registers use FC04.

Byte order — the second, worse trap

Modbus registers are 16-bit. Modern industrial data types are almost always larger:

  • INT32 / DINT / UINT32 — 32-bit integer, needs 2 registers
  • REAL / FLOAT32 — 32-bit IEEE 754 float, needs 2 registers
  • LREAL / FLOAT64 / DOUBLE — 64-bit IEEE 754 double, needs 4 registers
  • INT64 / LINT — 64-bit integer, needs 4 registers

The question that’s not answered by the Modbus spec: in what order are those bytes and words arranged? There are four common conventions:

ABCD — big-endian (IEEE 754 standard)

Bytes and words in their natural order. Most modern vendors use this: the first register contains the most significant word, the first byte of that register is the most significant byte. This is what the IEEE 754 float standard specifies.

CDAB — word swap (Schneider/Modicon default)

Bytes are big-endian within each word, but the two words are swapped. So a 32-bit float is stored with the least-significant word in the first register. This is Schneider Electric’s historical default and appears in many legacy Modicon installations.

BADC — byte swap within word

Bytes swapped inside each register, but registers in normal order. Rare, but appears in a few legacy systems and cheap Chinese gateways.

DCBA — little-endian (fully reversed)

Full byte-order reversal. Sometimes appears on Intel-based industrial PC gateways that pass through the underlying x86 byte order without conversion.

The classic example: 3.14 as a REAL/FLOAT32

The bytes of the IEEE 754 encoding of 3.14 (single precision) are 40 48 F5 C3. The four byte-order interpretations of those bytes as a REAL:

  • ABCD (as-is): 3.14 ✓ — correct if source used big-endian
  • CDAB (word swap): −4,95×10³² — a wildly wrong number
  • BADC (byte swap in word): 197,391 — plausible-looking but wrong
  • DCBA (fully reversed): −490,6 — plausible-looking but wrong

The trap: two of the four interpretations produce “reasonable-looking” values that might not obviously be wrong. Always verify against a known reference value at commissioning.

Vendor byte-order defaults

Not authoritative — always check the specific device datasheet — but common defaults:

  • Schneider Electric / Modicon PLCs — CDAB (word swap) for legacy compatibility
  • Siemens S7 — ABCD (big-endian) natively; Siemens Modbus gateways usually preserve this
  • Allen-Bradley Logix (via Modbus gateway) — often configurable; ABCD is the modern default
  • Delta, INVT, and many Chinese-brand VFDs — ABCD, but check individual manuals
  • Older DCS / HART concentrators — sometimes BADC or DCBA due to historical byte-flip issues
  • SCADA to PLC gateways — usually configurable; check both ends of the gateway match

Common troubleshooting scenarios this calculator helps with

  1. “I’m reading holding register 40001 but getting zero when the device should have a value.” — Check whether your tool expects Modicon addressing (40001) or PDU addressing (0). Reading Modicon 40001 as PDU 40001 hits an address that either doesn’t exist or has a completely different meaning.
  2. “The device says register 40100, my library needs the “starting address.” — Convert: PDU offset = 40100 − 40001 = 99.
  3. “My float value is wildly wrong even though I’m reading the right registers.” — Almost certainly a byte order mismatch. Try all four orders and see which one gives a sensible value.
  4. “The device manual only shows offsets in hex.” — Enter the hex directly (with 0x prefix) in the PDU field. The calculator handles both formats.
  5. “Register 12345 doesn’t fit the 5-digit Modicon format.” — Use the 6-digit format (412346) instead. Some SCADA tools only accept one format — check the tool docs.

What this calculator doesn’t cover

  • Enron / Daniel Modbus extensions — some flow meters use extended Modbus with 32-bit registers natively (not two 16-bit) and non-standard function codes. Vendor-specific — check the device manual.
  • Slave / server unit ID — the calculator focuses on the address within the device. The Modbus unit ID (1-247) selects which device on the bus you’re talking to.
  • TCP vs RTU vs ASCII framing — the addressing math is the same; the framing (CRC vs LRC vs TCP header) doesn’t affect register addresses.
  • Register mapping beyond the standard four types — some devices expose diagnostic information, event logs, or configuration through non-standard function codes (FC17, FC22, FC24, or vendor extensions).
  • Signed vs unsigned interpretation of INT16 — the calculator supports both explicitly; the device datasheet tells you which to use for a given register.

For serious commissioning work, use this calculator alongside a Modbus scanner tool (Modscan, Simply Modbus, mbpoll, modpoll) to verify register contents against the device documentation. When in doubt about byte order, try all four and check which produces a sensible engineering value.