Modbus Register Map Explained: How to Read Any Device’s Register Map

By | April 9, 2026

Every Modbus device comes with a register map. It is usually a table in the user manual or a separate PDF that lists all the data points the device makes available — voltages, currents, setpoints, alarms, status bits, and configuration parameters.

Reading a register map sounds simple. But it is one of the most common sources of errors in Modbus systems. Engineers misread the addressing (off by one), choose the wrong function code, misinterpret the data type (unsigned vs signed vs float), or get the byte order wrong for 32-bit values.

The result: the SCADA system shows 0, garbage data, or the wrong value — and nobody can figure out why.

This guide teaches you how to read any Modbus register map correctly. It covers the four register types, the zero-based offset trap, data types and byte order, how to match registers to function codes, and how to handle real register maps from actual devices.

1. What Is a Modbus Register Map

A register map is a table that documents every data point a Modbus device exposes. It tells you:

  • What data is available — voltage, current, power, frequency, temperature, setpoints, alarms
  • Where the data lives — the register address
  • What type of register — holding register, input register, coil, or discrete input
  • How to interpret the data — unsigned integer, signed integer, floating point, bitmask
  • The scaling factor — for example, a value of 2345 might mean 234.5 V (scale factor = 0.1)
  • Read/write access — whether you can only read the value or also write to it

Without the register map, you are guessing. And guessing with Modbus always leads to wrong data.

2. The Four Register Types

Modbus organizes data into four tables. Each table has its own address space and access rules.

Register TypeLegacy PrefixAddress RangeSizeAccessFunction Code (Read)Function Code (Write)
Coils0xxxx00001–099991 bitRead/WriteFC 01FC 05 / FC 15
Discrete Inputs1xxxx10001–199991 bitRead-OnlyFC 02
Input Registers3xxxx30001–3999916 bitsRead-OnlyFC 04
Holding Registers4xxxx40001–4999916 bitsRead/WriteFC 03FC 06 / FC 16

What Each Type Is Used For

  • Coils (0xxxx): Digital outputs you can control — relay outputs, motor start/stop, valve open/close.
  • Discrete Inputs (1xxxx): Digital inputs you can only read — limit switches, door contacts, alarm inputs.
  • Input Registers (3xxxx): Analog inputs you can only read — live measurements like voltage, current, temperature.
  • Holding Registers (4xxxx): General-purpose read/write registers — setpoints, configuration parameters, and often measurements too.

The Reality

Most modern devices map everything to holding registers (4xxxx). You use FC 03 to read and FC 06 or FC 16 to write. The four-table model exists in the spec, but many devices do not bother separating their data into different tables.

Always check the register map. If it says “holding register” or shows addresses starting with 4xxxx, use FC 03. If it says “input register” or 3xxxx, use FC 04.

3. The Zero-Based Offset: Why You Are Off by One

This is the single biggest source of Modbus configuration errors.

The Problem

The Modbus data model numbers registers starting at 1. Register 40001 is the first holding register.

The Modbus PDU (the actual bytes on the wire) addresses registers starting at 0. Address 0x0000 is the first holding register.

So when you want to read register 40001, you send address 0x0000 in the Modbus frame. When you want register 40002, you send 0x0001.

The rule: PDU address = register number − 1

Example

Your register map says: “Active Power is in register 40130.”

What the manual saysWhat you send in the PDU
Register 40130Address 0x0081 (129 decimal)
Register 40001Address 0x0000
Register 30001Address 0x0000 (but use FC 04)

The Confusion

Some register maps already show the PDU address (zero-based). Others show the data model number (one-based). Some show both. Some do not tell you which one they are using.

How to tell:

  • If the first register in the map is 0 or 0x0000 → the map shows PDU addresses (zero-based). Use these directly.
  • If the first register is 1, 40001, or 30001 → the map shows data model numbers (one-based). Subtract 1 (and drop the prefix) to get the PDU address.

SCADA Software Behavior

Different SCADA software handles the offset differently:

  • Some expect the data model number (40001) and subtract 1 internally.
  • Some expect the PDU address (0) and send it directly.
  • Some let you choose with a “zero-based” or “one-based” setting.

Always check your SCADA software documentation. If you configure register 40001 and get the data from register 40002, your software is not applying the offset — switch to zero-based or subtract 1 manually.

4. How to Match Registers to Function Codes

Register Map ShowsRegister TypeRead FCWrite FC
0xxxx or “Coil”CoilFC 01FC 05 (single) / FC 15 (multiple)
1xxxx or “Discrete Input”Discrete InputFC 02Not writable
3xxxx or “Input Register”Input RegisterFC 04Not writable
4xxxx or “Holding Register”Holding RegisterFC 03FC 06 (single) / FC 16 (multiple)

If the register map does not specify the type and just shows plain numbers (e.g., “register 100”), try FC 03 first. Most devices use holding registers for everything.

For a full explanation of each function code with frame examples, see: Modbus Function Codes Explained with Real Examples

5. Reading a Real Register Map: Step by Step

Here is a typical register map entry from an energy meter:

RegisterDescriptionData TypeUnitScaleR/W
40001Voltage L1-NUINT16V×0.1R
40002Voltage L2-NUINT16V×0.1R
40003Voltage L3-NUINT16V×0.1R
40004–40005Active Power TotalFLOAT32kWR
40006–40007Reactive Power TotalFLOAT32kVArR
40050CT Ratio PrimaryUINT16×1R/W
40051CT Ratio SecondaryUINT16×1R/W

Step 1. Identify the Register Type

Addresses start with 4xxxx → these are holding registers. Use FC 03 to read and FC 06 / FC 16 to write.

Step 2. Calculate the PDU Address

Register 40001 → PDU address = 40001 − 40001 = 0 (0x0000) Register 40004 → PDU address = 40004 − 40001 = 3 (0x0003) Register 40050 → PDU address = 40050 − 40001 = 49 (0x0031)

Step 3. Determine How Many Registers to Read

  • Voltage L1-N: 1 register (UINT16)
  • Active Power Total: 2 registers (FLOAT32 uses 2 × 16-bit registers)
  • To read all three voltages at once: start at address 0, quantity = 3

Step 4. Apply the Scale Factor

Your SCADA reads register 40001 and gets the raw value 2301. The scale factor is ×0.1.

Actual voltage = 2301 × 0.1 = 230.1 V

Step 5. Handle the Data Type

Register 40004–40005 is FLOAT32. You need to read 2 consecutive registers and combine them into a 32-bit IEEE 754 floating-point number. The register map should tell you the byte order (see Section 7).

6. Data Types Inside Registers

A single Modbus register is 16 bits. But the value it represents depends on the data type.

Data TypeSizeRegistersValue RangeExample
UINT1616 bits10 to 65,535Raw value 2301 = 2301
INT1616 bits1−32,768 to +32,767Raw value 0xFFF6 = −10
UINT3232 bits20 to 4,294,967,295Two registers combined
INT3232 bits2−2,147,483,648 to +2,147,483,647Two registers combined
FLOAT3232 bits2±3.4 × 10³⁸IEEE 754 floating point
FLOAT6464 bits4±1.7 × 10³⁰⁸IEEE 754 double precision
ASCIIVariableNText string2 characters per register

Common Pitfalls

  • UINT16 vs INT16: If a temperature register shows 65526 instead of −10, you are reading it as unsigned when it should be signed.
  • Scale factors: A value of 2301 with scale ×0.1 means 230.1. A value of 2301 with scale ×0.01 means 23.01. Wrong scale = wrong reading.
  • FLOAT32: If the value looks like 4.567E+15 or −0.0000001, the byte order is probably wrong.

For a deep dive into all Modbus data types, see: Modbus Data Types & Formats Guide

7. 32-Bit and Floating-Point Values: Byte Order Matters

When a value spans two registers, the order in which you combine them depends on the device manufacturer. There is no universal standard.

The Four Possible Byte Orders

For a FLOAT32 value using registers R1 (high word) and R2 (low word):

NameByte OrderAlso CalledExample
Big-EndianR1 R2 (AB CD)Standard, MotorolaMost common
Little-EndianR2 R1 (CD AB)Word-swappedSiemens, some ABB
Mid-BigR1 R2 (BA DC)Byte-swappedRare
Mid-LittleR2 R1 (DC BA)Byte-and-word-swappedRare

How to Find the Right Order

  1. Read the register map — some manuals explicitly state the byte order.
  2. If not documented, read a known value. For example, read a voltage that the device displays as 230.5 V.
  3. Try each byte order in your SCADA software until the value matches the device display.
  4. Document the correct order for all future configuration.

Example

Registers 40004 and 40005 contain: 0x4368 and 0xC000.

Byte OrderCombined HexFloat Value
AB CD (Big-Endian)0x4368C000232.75
CD AB (Little-Endian)0xC0004368−2.004

If the device displays 232.75 V, big-endian is correct.

8. Bit-Level Data Inside Registers

Some registers pack multiple status flags or alarm bits into a single 16-bit word. The register map will show which bit means what.

Example: Alarm Register (40100)

BitDescription0 =1 =
0Overvoltage alarmNormalAlarm
1Undervoltage alarmNormalAlarm
2Overcurrent alarmNormalAlarm
3OvertemperatureNormalAlarm
4–15Reserved

If the register reads 0x0005 (binary 0000 0000 0000 0101), bits 0 and 2 are set → overvoltage and overcurrent alarms are active.

How to Extract Bits in SCADA

Most SCADA software has a “bit extraction” function. You read the full 16-bit register with FC 03, then extract individual bits using masking:

  • Bit 0: value AND 0x0001
  • Bit 1: (value AND 0x0002) >> 1
  • Bit 2: (value AND 0x0004) >> 2

9. Coil Maps vs Register Maps

Coils are single-bit values (ON/OFF). They use a different addressing space and different function codes.

FeatureCoils (0xxxx)Holding Registers (4xxxx)
Size1 bit16 bits
Read FCFC 01FC 03
Write FCFC 05 (single) / FC 15 (multiple)FC 06 (single) / FC 16 (multiple)
Typical useRelay control, motor start/stopMeasurements, setpoints, configuration

Some devices use coils for control outputs and holding registers for everything else. Others pack everything into holding registers and use bit extraction for digital values. Check the register map.

10. Common Register Map Formats You Will Encounter

Register maps come in different formats depending on the manufacturer. Here are the most common:

Format A: One-Based with Prefix

RegisterDescription
40001Voltage L1
40002Voltage L2

PDU address = register − 40001. Very clear, no ambiguity.

Format B: Zero-Based (PDU Address)

AddressDescription
0Voltage L1
1Voltage L2

PDU address = address as shown. No math needed. But you must know these are holding registers (use FC 03).

Format C: One-Based without Prefix

RegisterDescription
1Voltage L1
2Voltage L2

Ambiguous. Is register 1 = PDU address 0 or PDU address 1? Check if the document says “zero-based” or “one-based.” If not stated, try both.

Format D: Hex Addresses

AddressDescription
0x0000Voltage L1
0x0001Voltage L2

PDU address = hex value directly. Always zero-based.

Format E: Mixed Table with Function Code

FCAddressDescriptionType
030Voltage L1UINT16
040Current L1UINT16

This is the clearest format. It tells you the function code and the PDU address. No guessing.

11. Mistakes Engineers Make Reading Register Maps

MistakeWhat HappensFix
Not subtracting the offsetReading register 40002 instead of 40001Check if your SCADA uses zero-based or one-based addressing
Using FC 03 for input registersException code 02 on some devicesCheck the register type. Use FC 04 for 3xxxx registers.
Reading FLOAT32 from one registerGarbage valueFLOAT32 needs 2 consecutive registers. Set quantity = 2.
Wrong byte order for 32-bit valuesValue is completely wrong (e.g., −2.004 instead of 232.75)Try all four byte orders. Match against the device display.
Ignoring the scale factorValue is 10× or 100× too large or too smallApply the scale factor from the register map.
Reading signed value as unsignedTemperature shows 65526 instead of −10Set data type to INT16 (signed) in your SCADA.
Assuming all devices start at 40001First registers return zero or exceptionSome devices start at 40000, others at 40100. Read the map.
Reading too many registers at onceTimeout or exception code 02Some devices limit reads to 50 or 100 registers per request. Split into smaller blocks.

12. How to Test Your Register Map Configuration

Before connecting a device to production SCADA, always test the register map independently.

Step 1. Use a Standalone Modbus Tool

Use a free tool like ModbusPoll, QModMaster, or OpenModScan. Connect directly to the device and read individual registers to verify values match the device display.

Step 2. Start with Known Values

Read a register with a known physical value — for example, the device displays 230.1 V. Read the voltage register and verify:

  • The raw value makes sense (e.g., 2301 with scale ×0.1)
  • The data type is correct (UINT16, FLOAT32, etc.)
  • The byte order matches (for 32-bit values)

Step 3. Test Edge Cases

  • Read the first and last register in the map — verify no offset errors.
  • Write a test value to a writable register — verify the device accepts it.
  • Read a bitmask register — verify individual bits match the device status LEDs.

Step 4. Document Everything

Create a configuration sheet listing: register address, PDU address, function code, data type, scale factor, byte order, and verified value. This saves hours during SCADA configuration and future troubleshooting.

💡 Tip: Use the free Modbus Frame Decoder Tool to verify that your request frames are addressing the correct registers and that the response data matches your expected values.

Summary

A Modbus register map is your only guide to communicating with a device correctly. Every error — wrong address, wrong function code, wrong data type, wrong byte order — starts with misreading the register map.

The key things to remember:

  • Subtract the offset — register 40001 = PDU address 0
  • Match the register type to the function code — FC 03 for holding registers, FC 04 for input registers
  • Check the data type — UINT16, INT16, FLOAT32 all look different for the same raw bytes
  • Verify byte order for 32-bit values — there are four possible orders, only one is correct
  • Apply the scale factor — raw value × scale = real value
  • Test with a standalone tool first — never configure SCADA from the register map alone

Get the register map right, and Modbus is the simplest protocol you will ever work with. Get it wrong, and you will spend days debugging a problem that takes five minutes to fix.

Author: Zakaria El Intissar

I'm an automation and industrial computing engineer with 12 years of experience in power system automation, SCADA communication protocols, and electrical protection. I build tools and write guides for Modbus, DNP3, IEC 101/103/104, and IEC 61850 on ScadaProtocols.com to help engineers decode, analyze, and troubleshoot real industrial communication systems.

Leave a Reply

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