Quick answer: Give every Modbus value an IEC type ID, a common address (CA) and a unique information object address (IOA). Map coils and discrete inputs to single points (M_SP_NA_1), 16-bit registers to scaled values (M_ME_NB_1) and Float32 register pairs to short floats (M_ME_NC_1), scale raw values to engineering units, map commands to coil or register writes, then verify every point with a general interrogation.
A Modbus to IEC 60870-5-104 gateway does two jobs: it reads registers from Modbus devices, and it presents each value to the SCADA master as an IEC information object with a type ID, a common address (CA) and an information object address (IOA). Most commissioning problems come from the mapping, not from the protocols. This guide walks through the decisions in the order you make them on a real project.
What do you need to know about each Modbus value?
Start from the device's register map and write down, for every value you want in SCADA:
- Object type and function code: coil (FC01), discrete input (FC02), holding register (FC03) or input register (FC04).
- Address: the 0-based protocol address. Manuals often print Modicon numbers such as 30001 or 40001; register 40001 is protocol address 0 of the holding registers. The register addressing guide explains the off-by-one trap.
- Data type: 16-bit signed or unsigned, 32-bit integer, Float32 (two registers) or Float64 (four registers).
- Word and byte order for multi-register values (ABCD, CDAB, BADC, DCBA). See the float byte-order guide.
- Scale and unit: for example "0.1 °C per bit" or "W, Float32".
Which IEC 104 type ID should each Modbus value use?
Pick the type that matches how SCADA will use the value, not only how the device stores it:
| Modbus value | Typical IEC type | Notes |
|---|---|---|
| Coil or discrete input (status) | M_SP_NA_1 (1), with time: M_SP_TB_1 (30) | 0 = OFF, 1 = ON |
| Breaker/isolator position | M_DP_NA_1 (3), with time: M_DP_TB_1 (31) | States: 0 intermediate, 1 OFF, 2 ON, 3 faulty |
| 16-bit register, integer quantity | M_ME_NB_1 (11) scaled value | Range -32768 to 32767 |
| Float32 or 32-bit integer | M_ME_NC_1 (13), with time: M_ME_TF_1 (36) | IEEE 754 single precision |
| Value as a fraction of full scale | M_ME_NA_1 (9) normalized value | Range -1 to +1 − 2-15 |
| Status word (bit pattern) | M_BO_NA_1 (7) bitstring of 32 bits | SCADA decodes the bits |
| Tap position | M_ST_NA_1 (5) step position | Range -64 to +63 |
| Energy counter | M_IT_NA_1 (15) integrated totals | Read by counter interrogation |
Types with the suffix TB/TF add a 7-octet CP56Time2a time tag. In IEC 104 only the CP56Time2a variants are allowed; the short CP24Time2a types (M_SP_TA_1, M_ME_TC_1 and so on) exist only in IEC 101. For a list of all codes see IEC 104 type IDs and COT.
How should IOAs and common addresses be planned?
The common address (CA, also called ASDU address) identifies the station; in IEC 104 it is 2 octets (1–65534 for normal stations, 65535 is the global/broadcast address). The IOA identifies the point inside the station; in IEC 104 it is 3 octets, so values up to 16,777,215 are possible. IOA 0 is reserved for station-level objects such as the general interrogation command.
Two practical conventions make signal lists easier to maintain:
- Use one CA per outstation (one per gateway, or one per connected Modbus device if the SCADA system models each device as a station).
- Reserve IOA blocks per signal class, for example 1001–1999 single points, 2001–2999 double points, 3001–3999 measured values, 4001–4999 set-points and 5001–5999 commands. Leave gaps for future signals.
Whatever you choose, the IEC 104 master must use the same CA and IOAs. A master that sends a command to an unknown CA or IOA receives a negative confirmation with cause of transmission 46 (unknown common address) or 47 (unknown IOA).
How do scaling and offset work?
A gateway usually converts the raw register to engineering units with IEC value = raw × scale + offset. Then check that the result fits the IEC type:
| IEC type | Valid range | Typical scaling |
|---|---|---|
| M_ME_NC_1 short float | IEEE 754 single (about 7 significant digits) | Engineering units directly |
| M_ME_NB_1 scaled value | -32768 to 32767 (integer) | Multiply by 10 or 100 to keep decimals, or divide large values |
| M_ME_NA_1 normalized value | -1 to +1 − 2-15 | Divide by full scale (scale = 1 / nominal) |
Example: a temperature register reads 234 with a resolution of 0.1 °C. For M_ME_NC_1 use scale 0.1 to send 23.4. For M_ME_NB_1 many projects keep the raw 234 and document "value × 0.1 = °C" in the signal list, because the scaled type carries integers only.
Do you need time-tagged types?
Time-tagged types carry a timestamp for each change. When the source is Modbus, the gateway can only stamp the time at which its poll saw the change, so the resolution is the poll interval (for example 1 s) plus network delay. That is still useful for event lists and alarm sequences, but it is not a device-level sequence-of-events record. If the SCADA system requires time tags for spontaneous events, use M_SP_TB_1, M_DP_TB_1 and M_ME_TF_1 and keep the gateway clock synchronized (NTP).
How do IEC commands map back to Modbus writes?
| IEC command | Modbus write | Notes |
|---|---|---|
| C_SC_NA_1 (45) single command | FC05 write single coil | ON writes 1, OFF writes 0 |
| C_DC_NA_1 (46) double command | FC05 write single coil | DCS 2 = ON, 1 = OFF; 0 and 3 are not permitted |
| C_SE_NB_1 (49) set-point, scaled | FC06 write single register | 16-bit value after reverse scaling |
| C_SE_NC_1 (50) set-point, short float | FC16 write multiple registers | Two registers for a Float32 |
Commands can be executed directly or with select-before-operate (SBO): the master first sends the command with the select bit set, the outstation confirms, and only the following execute command operates the output. SBO protects against a single corrupted or mistaken message operating equipment. After execution the outstation sends an activation confirmation (COT 7) and, if configured, an activation termination (COT 10). Always map the resulting status as a separate monitoring point, so the operator sees the real device state rather than the command.
How should communication failures be shown?
IEC 60870-5 carries a quality descriptor with each value. The important bits are IV (invalid), NT (not topical, i.e. not updated recently), SB (substituted), BL (blocked) and, for measured values, OV (overflow). A gateway should set IV when the Modbus device stops answering and report that change spontaneously, so SCADA marks the values as invalid instead of showing a frozen last value.
Step by step: mapping and testing
- Collect the Modbus register list. From the device manual, note each value's register type, 0-based address, data type, word order, scale and unit.
- Choose an IEC type ID per value. Coils and status bits become single or double points; 16-bit values scaled values; floats short floats.
- Agree the addressing with the SCADA owner. Fix the common address (CA) of the outstation and a block of IOAs per signal type, and write it into the signal list.
- Configure the gateway. Add the Modbus device, create one mapping per value with IEC type, IOA, CA, scale and offset, then apply and reload.
- Test with general interrogation and commands. Connect an IEC 104 master, send STARTDT and a general interrogation, compare every value with the device, then test each command.
In Max IEC Gateway these steps are the Devices, Mappings and Settings pages; saved mappings are active immediately, without restarting the gateway. The Traffic page shows the Modbus polls and the IEC messages side by side.
How can you test without the real devices?
Run a Modbus slave simulator that serves the same register map, for example the ModbusBB slave simulator, and point the gateway at it. On the IEC side use any IEC 60870-5-104 test master. Check each point against the signal list: value, scaling, quality when you stop the simulator, and the response of every command.
Frequently asked questions
Should a Modbus coil be a single point or a double point?
Use a single point (M_SP_NA_1) for a simple on/off status. Use a double point (M_DP_NA_1) for switchgear position when the SCADA system expects the four states OFF, ON, intermediate and faulty; in that case both position contacts should ideally come from the device.
Can one Modbus register feed several IEC points?
In the IEC model every information object has its own IOA, so each IEC point is a separate mapping. Several mappings may read the same register, for example to send it once as a scaled value and once as a float.
What happens when the Modbus device goes offline?
The gateway keeps the last value but sets the invalid (IV) quality bit, and reports that change spontaneously, so the SCADA system shows the points as invalid instead of silently frozen.
Try it with Max IEC Gateway. The gateway polls Modbus TCP and RTU devices and serves the values as an IEC 60870-5-104 server or IEC 60870-5-101 outstation, with a traffic monitor that shows every exchange.
Related guides
Modbus basics on the ModbusBB site: register addressing, function codes, Modbus timeouts.