Overview: Modbus RTU on S7-1200 for Energy Monitoring
Modbus RTU is the de facto serial protocol for low-cost energy meters, multifunction power transducers, branch-circuit monitors, and serial smart sensors installed in sub-distribution switchgear. The S7-1200 PLC family exchanges Modbus RTU frames through serial point-to-point (PtP) interfaces implemented either by a plug-in Communication Board CB 1241 or by a left-mounted Communication Module CM 1241. Both expose RS-485 (and, in selected variants, RS-232) and rely on the Siemens MODBUS instruction library inside TIA Portal to make the CPU act as a Modbus RTU master polling field devices, or as a Modbus RTU slave responding to a supervisory controller.
According to the official Siemens TIA Portal documentation "Modbus RTU (S7-1200, S7-1500)", the protocol uses the RS-232 or RS-422/485 electrical layer for serial data, transports a binary-encoded payload, validates each frame with a CRC-16 integrity check, and follows a strict master/slave polling model. Each transaction is initiated by the master, addressed to a single slave (addresses 1 to 247), and replied to by the slave with the requested payload or an exception code.
On a typical energy monitoring panel, the S7-1200 acts as master, periodically reading voltage, current, active/reactive power, power factor, energy counters, and harmonics from each connected meter. The remainder of this reference covers hardware selection, library block choice, MB_COMM_LOAD and MODBUS_MASTER configuration, the status/error codes observed in commissioning (16#7000, W#16#8281, 16#7001), RS-485 wiring, and multi-slave polling optimisation.
Hardware Prerequisites: CM 1241, CB 1241, and CPU-integrated RS-485
Modbus RTU on the S7-1200 is not available through the PROFINET port; it requires an RS-485 (or RS-232) physical interface. Three product options exist:
| Module | Article number | Electrical layer | Mounting | Typical use |
|---|---|---|---|---|
| CB 1241 RS-485 | 6ES7241-1CH30-1XB0 | RS-485 half-duplex | Plug-in slot on CPU front | Single-bus, low-cost panels |
| CB 1241 RS-232 | 6ES7241-1AH30-1XB0 | RS-232 full-duplex | Plug-in slot on CPU front | Single short-distance meter |
| CM 1241 RS-485 | 6ES7241-1CH32-0XB0 | RS-485 half-duplex | Left of CPU (max 3 modules) | Up to 32 slaves, isolated |
| CM 1241 RS-232 | 6ES7241-1AH32-0XB0 | RS-232 full-duplex | Left of CPU | Point-to-point radios/meters |
| CPU 1217C onboard RS-485 | 6ES7217-1AG40-0XB0 | RS-485 half-duplex | CPU-integrated (port 1) | Compact machines, no extra module |
The CM 1241 RS-485 (6ES7241-1CH32-0XB0) is the most common choice for energy panels because it is galvanically isolated, supports 1200 to 115 200 bit/s, and can be located up to 1000 m of twisted pair from the farthest slave at reduced baud. Up to three CM 1241 modules can be stacked on a single CPU, giving a theoretical ceiling of three independent RS-485 buses (Bus 1 / Bus 2 / Bus 3 in TIA Portal device configuration).
Pinout on the CM 1241 RS-485 front connector:
- Pin 1 = shield/functional earth (terminal M or FE)
- Pin 2 = unused / reserved
- Pin 3 = TxD+/RxD+ (non-inverting, often labelled A or D+)
- Pin 4 = RTS (TTL level, only used in RS-232 mode)
- Pin 5 = TxD-/RxD- (inverting, often labelled B or D-)
- Pin 6 = +5 V auxiliary (only for termination biasing in some variants)
TIA Portal Library: MODBUS vs MODBUS (RTU) Block Selection
Inside TIA Portal V14 (and later versions), the Modbus RTU instruction palette exposes two sets of function blocks under Communication > MODBUS:
-
MODBUS (RTU) - the current instruction set, also referenced as the "PTP_Modbus" library variant. Block names use the prefix
MB_(e.g. MB_COMM_LOAD, MB_MASTER, MB_SLAVE). - MODBUS - the legacy instruction set, retained for backward compatibility with projects migrated from STEP 7 Basic V11/V12/V13 or from libraries exported by older projects.
Both instruction sets implement the same protocol on the wire, but the underlying FB signatures, instance DB structure, and the way the block references the serial port differ. When you drag MODBUS (RTU) into a network, TIA inserts the modern MB_COMM_LOAD and MB_MASTER blocks. When you drag MODBUS, TIA inserts the legacy MODBUS_COMM_LOAD (or simply MB_COMM_LOAD from the older library) plus MODBUS_MASTER with slightly different input parameters.
Field experience (and reports on commissioning forums) consistently show that engineers starting a fresh S7-1200 project should select MODBUS (RTU). If a project migrated from an older TIA Portal version uses the legacy MODBUS blocks and they function correctly, leave them in place - mixing the two sets in the same project causes instance DB conflicts and inconsistent status reporting.
The troubleshooting case discussed later in this article (16#7000 / W#16#8281 / 16#7001 on MB_COMM_LOAD and MODBUS_MASTER) was resolved by switching to the MODBUS block. This is consistent with a project originally compiled against TIA V13 or V13 SP1 where the MODBUS (RTU) instruction library is not yet fully resolved by the CPU firmware in use, and the legacy block's parameter signature is matched. For all new greenfield deployments, use MODBUS (RTU) on CPU firmware V4.2 or higher.
MB_COMM_LOAD Configuration
MB_COMM_LOAD initialises the serial port selected by the HW_ID input. It must be called once on cold restart (OB100), on restart (OB101), and on warm restart - in practice it is called once in OB1 with a rising-edge REQ trigger, so that a port parameter change in TIA Portal takes effect after download.
Key input parameters:
| Input | Data type | Typical value | Meaning |
|---|---|---|---|
| REQ | BOOL | Edge-triggered TRUE | Rising edge triggers (re-)initialisation of the port |
| PORT | HW_IO / UINT | HW identifier from device configuration (e.g. 269 for CM 1241 on slot 1) | Identifies which physical interface is configured |
| BAUD | DINT / UINT | 9600, 19200, 38400, 115200 | Serial bit rate (bit/s) |
| PARITY | UINT | 0 = None, 1 = Odd, 2 = Even | Parity bit (most energy meters use Even) |
| FLOW_CTRL | UINT | 0 = None, 1 = Hardware RTS/CTS (RS-232 only) | Flow control |
| RTS_ON_DLY | UINT | 0 | RTS-on delay (RS-232 only) |
| RTS_OFF_DLY | UINT | 0 | RTS-off delay (RS-232 only) |
| RESP_TO | UINT | 1000 (ms) | Slave response timeout in milliseconds |
| MODE | USINT | 4 for Modbus RTU | Protocol mode (4 = RTU master, see below) |
The MODE parameter selects the operating mode of the CM/CB. The full mapping is documented in the Siemens Modbus RTU library reference:
- 0 = PPI (legacy, S7-200 compatibility)
- 1 = ASCII (Modbus ASCII)
- 2 = RK512 (S7-300/400 legacy)
- 3 = USS (drive protocol)
- 4 = RTU (Modbus RTU master)
- 5 = RTU slave
If MODE is left at the default (0) or set incorrectly, MB_COMM_LOAD returns status 16#7000 and never actually opens the port. This is one of the most common root causes of the "TX LED never blinks" symptom.
Locating the correct HW_ID for the PORT input:
- Open Devices & networks, click the CM 1241 module.
- Switch to Properties > System constants and note the HW identifier for the interface (e.g. "Local~CM1241_1~MODBUS\~1"). The numeric HW identifier (e.g. 269 decimal) is what the PORT input expects.
- Alternatively, drag the interface onto the PORT input from the system constants - TIA will auto-fill the correct identifier.
MODBUS_MASTER Configuration
MODBUS_MASTER (or MB_MASTER in the modern library) executes a single Modbus request per call. To poll multiple registers or multiple slaves, call the block multiple times in OB1 - one instance per slave or one instance per register group, each with its own DATA_ADDR and DATA_LEN. Only one MODBUS_MASTER instance can be active on the same HW_ID at any instant; trigger them sequentially using a small state machine, or use one instance per slave with interleaved REQ pulses.
Standard inputs:
| Input | Data type | Meaning |
|---|---|---|
| REQ | BOOL | Rising edge starts a new request |
| MB_ADDR | USINT | Modbus slave address (1 to 247) |
| MODE | USINT | Modbus function code: 1=Read Coils, 2=Read Discrete Inputs, 3=Read Holding, 4=Read Input, 5=Write Single Coil, 6=Write Single Register, 15=Write Multiple Coils, 16=Write Multiple Registers, 23=Read/Write Multiple Registers |
| DATA_ADDR | UINT | Starting Modbus register / coil address (0-based, protocol address) |
| DATA_LEN | UINT | Number of registers/coils to transfer (max 125 words / 2000 coils) |
| DATA_PTR | VARIANT | Pointer to source/destination DB or tag; word-consistent (e.g. ARRAY[0..9] of WORD for 10 registers) |
| DONE | BOOL | TRUE for one cycle on successful completion |
| BUSY | BOOL | TRUE while a request is in progress |
| ERROR | BOOL | TRUE on error |
| STATUS | WORD | Detailed status / error code |
Sample ST code for polling slave 1 holding registers 0 to 9 (active power, reactive power, voltage L-L, etc.):
// OB1 - cyclic poll of slave 1 holding registers
#Poll_Trigger := #Poll_Trigger XOR TRUE; // 0.5 Hz edge generator (uses OB1 cycle)
MODBUS_MASTER_DB(
REQ := #Poll_Trigger,
MB_ADDR := 1,
MODE := 3, // Read Holding Registers (FC 03)
DATA_ADDR := 0, // Modbus address 40001 -> 0-based = 0
DATA_LEN := 10, // 10 registers = 20 bytes
DATA_PTR := P#DB1.DBX0.0 WORD 10,
DONE => #Done1,
BUSY => #Busy1,
ERROR => #Error1,
STATUS => #Status1
);
DATA_ADDR = 0; "30001" maps to 0 for FC04 input registers; "00001" coils map to 0 for FC01/02. The function code in MODE handles the storage class.Status and Error Code Reference
When commissioning a Modbus RTU link on the S7-1200, the most useful diagnostics are the STATUS word of MB_COMM_LOAD and MODBUS_MASTER, together with the TX and RX LEDs on the CM/CB front panel. The codes observed during a typical troubleshooting session are listed below.
| Code | Block | Meaning | Field interpretation |
|---|---|---|---|
| 16#0000 | Both | No error / idle | Normal idle state of an instance that has completed its last request. |
| 16#7000 | MB_COMM_LOAD | Block is initialised but the serial port is not yet active, or no valid configuration has been loaded | Check MODE = 4, HW_ID matches the module, and REQ has been pulsed at least once. |
| 16#7001 | MODBUS_MASTER | Request accepted; first execution cycle after REQ rising edge |
Normal transient. If it persists, the master has not yet gained bus access or RESP_TO is too short. |
| 16#7002 | MODBUS_MASTER | Request in progress - transmission or reception underway | Healthy state during polling. Poll rate must be longer than this period, or BUSY collisions will trigger ERROR = TRUE. |
| W#16#8281 | MODBUS_MASTER | Parameter assignment warning - typically DATA_LEN = 0, DATA_PTR is not a word-aligned DB, or MB_ADDR is out of range |
Verify the target DB is a non-optimised (classic) DB or that the ARRAY of WORD has the same length as DATA_LEN * 2 bytes. |
| 16#8381 | MODBUS_MASTER | No response from slave within RESP_TO | A/B reversed, wrong baud, slave not powered, parity mismatch, RESP_TO too short, or termination missing on a long bus. |
| 16#8382 | MODBUS_MASTER | CRC error in slave response | Electrical noise, missing termination, mismatched baud between master and slave. |
| 16#8383 | MODBUS_MASTER | Exception response from slave - check low byte for Modbus exception code (01 illegal function, 02 illegal address, 03 illegal value, ...) |
For the symptom set reported in the field (16#7000 in MB_COMM_LOAD together with W#16#8281 and 16#7001 in MODBUS_MASTER), the root cause is almost always a wrong PORT HW_ID or an unassigned MODBUS instance DB that prevents the FB from posting a request. Switching to the legacy MODBUS block resolved the case because the project carried an instance DB originally generated by TIA V13 SP1 that referenced an older block signature, and the re-insertion of the modern MODBUS (RTU) block forced regeneration of compatible instance DBs.
RS-485 Wiring, Termination, and Bus Topology
Modbus RTU over RS-485 is a 2-wire half-duplex multi-drop bus. The recommended topology is a linear (daisy-chain) trunk with short stubs (max 0.3 m) to each meter, and 120 Ω termination resistors installed only at the two physical ends of the trunk.
Wiring checklist:
- Use a shielded twisted pair rated for RS-485 (characteristic impedance 120 Ω): Belden 3106A, Lapp ETHERLINE 2-PVC, or equivalent.
- Connect the shield to functional earth at one point only (typically the panel ground bar near the CM 1241). Avoid ground loops.
- Install 120 Ω termination resistors in parallel between A+ and B- at the two physical ends of the trunk. The CM 1241 RS-485 has no on-board termination; bring an external 120 Ω, 1/4 W resistor inside the meter terminal block or at the master end.
- Keep stubs shorter than 0.3 m. Multi-drop spurs longer than 1 m cause reflections and CRC errors.
- Total trunk length: up to 1200 m at 9600 bit/s, 800 m at 19 200 bit/s, 400 m at 38 400 bit/s, 200 m at 115 200 bit/s (per Modbus over serial line specification).
- Maximum of 32 unit loads on a standard RS-485 bus; some modern transceivers support 1/8 unit load and up to 256 nodes - verify meter specification.
- Do not route the bus cable in the same conduit as VFD power cables or switchgear above 600 V; cross at 90° if unavoidable.
Polling Optimisation for Multiple Slaves
The reported symptom - "3 to 4 second response delay with 10 slaves at 9600 bit/s" - is normal sequential polling behaviour and is not a hardware fault. The minimum per-request time at 9600 bit/s, 8N1 is approximately:
Frame length = 1 (addr) + 1 (FC) + 1 (start addr) + 1 (count) + 2 (CRC) = 6 bytes request
Response = 1 (addr) + 1 (FC) + 1 (byte count) + 2*N (data) + 2 (CRC) = 5 + 2*N bytes
Bit time at 9600 baud = 1 / 9600 = 0.104 ms
3.5 character gap = 3.5 * 11 / 9600 = 4.0 ms (per Modbus RTU spec)
Per-cycle (request + response + 2 gaps) for 10 holding registers (N = 10):
T_one = (6 + 25) bytes * 11 bits / 9600 + 2 * 4.0 ms
= 341 bits / 9600 + 8 ms
= 35.5 ms + 8 ms = 43.5 ms
T_total = 10 slaves * 43.5 ms = 435 ms (one polling pass)
If each meter is polled for 4 register groups (voltage, current, energy, harmonics), the single-threaded pass time rises to roughly 1.7 s, and with a 1000 ms RESP_TO guard band the apparent latency reaches the 3 to 4 s figure observed in the field. To reduce this:
- Increase baud rate. At 38 400 bit/s the per-cycle time drops to about 12 ms; at 115 200 bit/s to about 5 ms. Verify that every meter on the bus supports the chosen rate.
- Combine registers into a single multi-block read. Most energy meters expose a contiguous map of 60-100 holding registers (voltage, current, power, energy, demand, THD). One FC 03 read of 60 registers replaces four or five smaller reads and reduces the per-cycle overhead to one frame turnaround (8 ms gap) instead of several.
- Use parallel OB1 instances. With three independent CM 1241 modules (Bus 1 / Bus 2 / Bus 3), split the 10 slaves across three buses. Each bus has its own MODBUS_MASTER instance and its own polling time.
-
Interleave REQ edges on a single bus. Use one MODBUS_MASTER instance per slave and trigger REQ from a cyclic interrupt OB30 (e.g. 100 ms base) so each slave is queried once every 1 s. Verify that no two instances have
BUSY= TRUE simultaneously, or implement a small state machine that fires the next REQ only after the previous DONE pulse. - Tune RESP_TO. 1000 ms is conservative. Once stable, reduce to 200-300 ms to fail fast on a defective slave without stalling the bus.
- Reduce the inter-frame gap on the meter (where supported) from the default 3.5 character time to 1.75 characters. This saves roughly 2 ms per cycle.
BUSY = FALSE before issuing the next REQ. Two simultaneously busy instances will garble the response and trigger CRC errors (16#8382) at the master.Verification and Online Diagnostics
After downloading the project, perform this verification sequence:
- Go online with the CPU and watch MB_COMM_LOAD
DONErising edge - it should pulse TRUE on every port parameter reload. - Check the TX LED on the CM 1241. It must blink on each outgoing Modbus request. No blink = MODE wrong or HW_ID wrong.
- Check the RX LED. It must blink on each incoming slave response. RX dark but TX blinking = wiring, address, or slave baud mismatch.
- Open the MODBUS_MASTER instance DB in Monitor / Modify and watch the
STATUSword. Healthy code is 16#0000 between polls and 16#7002 during a poll. - For intermittent CRC errors, enable the TIA Portal Trace function on the
BUSY,ERROR, andSTATUStags to correlate electrical noise with VFD starts or contractor operations. - Use a USB-to-RS485 sniffer (e.g. Anybus Communicator, Eltima Advanced Serial Port Monitor, or simply a generic FTDI USB-RS485 cable with the open-source "Modbus Poll" tool) wired in parallel to capture bus traffic and verify that the slave is sending the expected function code and register count.
- Once polling is stable, expand the energy DB and add a debounced
LastSuccessfulPolltimestamp to alarm on communication loss (>5 s without DONE = TRUE).
Migration and Compatibility Notes
If you inherit a project from a colleague and the MODBUS block is already configured, do not change it to MODBUS (RTU) "just because". Check the project library versions first. Mixing legacy MODBUS instances with the new MODBUS (RTU) library in the same PLC produces inconsistent STATUS codes and lost responses. The safer migration path is:
- Document the existing instance DB numbers and the slave map.
- Create a fresh project, copy the CPU hardware, drag MODBUS (RTU) blocks, and rebuild the slave map.
- Validate on a single bench meter before touching the live panel.
Firmware requirements: S7-1200 CPU firmware V4.0 or higher is required for the MODBUS (RTU) instruction set. CPU 1211C / 1212C / 1214C / 1215C / 1217C with article numbers ending in -1AE40 or -1AG40 support the library. Older -0AE40 CPUs require firmware V4.2 upgrade. Always verify firmware with Online > Accessible nodes in TIA Portal before commissioning.
Which MODBUS block should I use in TIA Portal V14 for an S7-1200 energy meter project?
Use MODBUS (RTU) for new projects on CPU firmware V4.2 or higher. The legacy MODBUS block is kept only for projects migrated from TIA V13 / V13 SP1. Mixing both in the same PLC produces inconsistent STATUS codes and should be avoided.
What does status 16#7000 in MB_COMM_LOAD mean?
The serial port is initialised but not active. Verify MODE = 4 for Modbus RTU, verify the HW_ID on the PORT input matches the CM 1241 in the device configuration (e.g. 269 decimal), and pulse REQ with a rising edge at least once after every download.
How do I clear warning W#16#8281 in MODBUS_MASTER?
W#16#8281 indicates a parameter assignment error. Confirm that DATA_LEN is greater than 0, that DATA_PTR points to a word-aligned ARRAY[0..N] of WORD in a non-optimised DB, and that MB_ADDR is between 1 and 247. Most often the target DB has been declared as an optimised DB and must be switched off in the DB properties ("Optimised block access" = unchecked).
Why is my polling slow with 10 slaves at 9600 bit/s?
Sequential RS-485 polling at 9600 bit/s requires roughly 40 ms per slave per register block, so 10 slaves polled four times each take 1.5 to 2 s for one full pass. Increase the baud rate to 38 400 or 115 200, consolidate multiple register reads into one FC 03 read of 60+ registers, and trigger each instance from a cyclic interrupt OB to interleave requests without bus collisions.
Do I need a CM 1241 or is the onboard RS-485 on CPU 1217C enough?
The CPU 1217C has an integrated RS-485 port that supports Modbus RTU and is electrically identical to the CM 1241 RS-485 for one bus. For more than 32 nodes, for electrical isolation, or for multiple independent buses, use the CM 1241 RS-485 (6ES7241-1CH32-0XB0). The CB 1241 RS-485 (6ES7241-1CH30-1XB0) is the lowest-cost option for compact machines and shares the same library instructions.