1. Overview
Redundant Modbus RTU slave communication on a SIMATIC S7-300 stack is rarely delivered as a turnkey solution because the CP341 (6ES7 341-1CH02-0AE0) is a single-channel serial module. Field installations that require high availability (Yokogawa DCS polling, SCADA gateways, redundant HMIs) typically use two CP341 modules wired in parallel on the same RS-485 trunk, each loaded with the Modbus RTU slave dongle (6ES7 870-1AB01-0YA1) and addressed with a distinct Modbus slave ID. The same philosophy extends to the CPU: two S7-315-2DP controllers cross-linked over MPI for redundancy, sharing a single IM153 Profibus remote I/O rack on which both CP341 modules are mounted.
This document consolidates the field-proven configuration pattern for running two CP341 Modbus RTU slaves from one CPU, and the additional OB100 / OB1 logic required to keep both slaves alive across CPU master/standby switchover. The implementation uses the MODB_341 function block (FB80) shipped with the Siemens "MODBUS" library, two instance DBs, two independent flag ranges, and a watchdog that re-runs the CP initialization sequence when the controlling CPU changes.
2. Hardware Prerequisites
| Component | Order Number | Role |
|---|---|---|
| S7-300 CPU | 6ES7 315-2AG10-0AB0 (or compatible 315-2DP) | Controller, two required for warm-standby |
| CP341 (RS-485) | 6ES7 341-1CH02-0AE0 | Modbus RTU slave channel |
| Modbus RTU dongle | 6ES7 870-1AB01-0YA1 | Activates RTU protocol, parameter set stored in dongle |
| IM153-1 / IM153-2 | 6ES7 153-1AA03-0XB0 / -2BAx0 | Profibus slave interface for ET200M rack |
| Profibus cable | 6XV1 830-0AH10 | CPU DP port ↔ IM153 link |
| MPI cable | 6ES7 901-0BF00-0AA0 | CPU1 ↔ CPU2 redundancy link |
| RS-485 termination | 120 Ω across A/B on trunk end | Bus termination, mandatory for stable RTU |
Both CP341 modules must occupy distinct slots on the ET200M rack. The standard layout used in production cells is:
- Slot 4: CP341 #1 (Modbus slave ID 5)
- Slot 5: CP341 #2 (Modbus slave ID 6)
Logical addresses in HW Config are assigned automatically, e.g. PIW 256 / PQW 256 for CP #1 and PIW 288 / PQW 288 for CP #2. Record these addresses; they are passed to FB80 as the LADDR input.
3. Software Prerequisites
- STEP 7 V5.5 + SPx (or TIA Portal V13+ for classic CP341 blocks via "S7-300/400" import)
- Siemens MODBUS library, e.g. MODBUS_V33 shipped with the SIMATIC PCS 7 Modbus sample, or "Modbus_Master_Slave_PT100" example project from Siemens Support entry 22648304
- CP341 dongle parameter set loaded into the dongle with the Siemens dongle utility (PIP_PB or "Parameterize Modbus" tool). The dongle stores baud rate, parity, response timeout, and the Modbus register map. Both dongles must carry identical parameter sets (function codes 03/04/06/16, register window, byte order) so the master sees the same process image on either CP.
4. Hardware Topology
5. FB80 Interface (MODB_341) and Required Inputs
The MODBUS library FB80 ("MODB_341") implements the Modbus RTU slave side on the CP341. Each call must receive its own instance DB; sharing one IDB between two CPs corrupts the receive and transmit state machines. The interface used in the field-proven block is summarized below.
| Parameter | Type | Direction | Description |
|---|---|---|---|
| START_TIMER | TIMER | I | Initialization watchdog (e.g. T120 / T121) |
| START_TIME | S5TIME | I | Watchdog preset (typical S5T#5S) |
| OB_MASK | BOOL | I | Suppress OB122 access-error calls |
| CP_START | BOOL | I/O | Start initialization; held TRUE by OB100 |
| CP_START_FM | BOOL | I/O | Edge flag, must be reset in OB100 |
| CP_NDR | BOOL | I/O | New data ready from master |
| CP_START_OK | BOOL | I/O | Initialization completed without error |
| CP_START_ERROR | BOOL | I/O | Initialization failed |
| ERROR_NR | WORD | I/O | Error code from FB80 |
| ERROR_INFO | WORD | I/O | Additional error info word |
| LADDR | INT | STAT (IDB) | Logical base address of the CP341 (set inside the IDB, e.g. 256 / 288) |
Generate two instance DBs (e.g. DB101 for CP #1 and DB102 for CP #2). Open each IDB and set the LADDR static variable to the logical base address of the corresponding CP. This is the only parameter that must be edited in the IDB view; everything else is driven from the flag interface.
6. Flag, Timer and Register Allocation
Use two independent flag ranges so FB80 calls cannot cross-write each other. A common production layout:
| Signal | CP #1 range | CP #2 range | Note |
|---|---|---|---|
| CP_START | M 180.0 | M 190.0 | Held TRUE in OB100, pulsed in OB1 for re-init |
| CP_START_FM | M 180.1 | M 190.1 | Edge flag, reset in OB100 |
| CP_NDR | M 180.2 | M 190.2 | Set by FB80 on every successful reception |
| CP_START_OK | M 180.3 | M 190.3 | TRUE when CP is initialized |
| CP_START_ERROR | M 180.4 | M 190.4 | TRUE on init error |
| ERROR_NR | MW 182 | MW 192 | Word, error code (see Section 12) |
| ERROR_INFO | MW 184 | MW 194 | Word, extended info |
| Watchdog | T 120 | T 121 | 5 s init timeout |
7. OB100 Startup Implementation
OB100 is the warm-restart OB and runs once after power-up or CPU stop→run transition. Both CP_START flags must be set and both CP_START_FM edge flags reset here so the very first OB1 cycle starts the dongle handshake on both channels.
// OB100 - Warm restart (ladder)
NETWORK 1 CP #1 - prepare flags
AN M 180.0 // M180.0 not set yet?
S M 180.0 // set CP_START for CP #1
A M 180.1 // edge flag still set?
R M 180.1 // reset CP_START_FM
NETWORK 2 CP #2 - prepare flags
AN M 190.0
S M 190.0 // set CP_START for CP #2
A M 190.1
R M 190.1 // reset CP_START_FM
8. OB1 Cyclic Implementation
OB1 calls two FB80 instances. Only the flag ranges, the timers, and the IDB differ between networks; the ladder pattern is identical.
// OB1 - Network 10 FB80 instance for CP #1
CALL "MODB_341" , DB101
START_TIMER :=T120
START_TIME :=S5T#5S
OB_MASK :=TRUE
CP_START :=M180.0
CP_START_FM :=M180.1
CP_NDR :=M180.2
CP_START_OK :=M180.3
CP_START_ERROR:=M180.4
ERROR_NR :=MW182
ERROR_INFO :=MW184
// OB1 - Network 11 FB80 instance for CP #2
CALL "MODB_341" , DB102
START_TIMER :=T121
START_TIME :=S5T#5S
OB_MASK :=TRUE
CP_START :=M190.0
CP_START_FM :=M190.1
CP_NDR :=M190.2
CP_START_OK :=M190.3
CP_START_ERROR:=M190.4
ERROR_NR :=MW192
ERROR_INFO :=MW194
Inside the FB80, the internal instance DB also stores the receive/transmit pointers and the dongle handshake state. By keeping two IDBs you isolate the S7-300 process image of the two CPs; the master can then poll either slave independently without one FB instance clobbering the other's buffer index.
9. Re-initialization Logic for Redundant CPU Switchover
After CPU master/standby switchover the new CPU keeps running the program but the CP341 modules retain the dongle-protocol state from the previous owner. The first FB80 instance therefore reports CP_START_OK=TRUE even though the channel is stale, and only the last FB80 call (still in the warm state of the previous owner) actually carries traffic. Power-cycling the panel clears the dongle handshake and both slaves come back. The same effect can be achieved in software by re-pulsing CP_START on every CPU role change.
9.1 Detect the new master
Wire a "Master/Standby" handshake on the MPI side. One common pattern is a single bit toggled by whichever CPU is currently the master (e.g. a heartbeat from the supervisory logic). The new master writes the bit FALSE; the new standby writes it TRUE. Latch the previous value in a flag and detect a 1→0 transition with an edge flag.
// OB1 - Network 20 Master-takeover edge detection
A "MASTER_HEARTBEAT" // global, TRUE = local CPU is master
FP "M_PREV_MASTER" // edge flag, static
= "M_NEW_MASTER" // one-shot TRUE on master take-over
A "MASTER_HEARTBEAT"
= "M_PREV_MASTER" // shadow bit for next scan
9.2 Re-trigger both CP_START flags
On every rising edge of MASTER_HEARTBEAT, drop CP_START for both CPs for at least one OB1 cycle and re-arm. The dongle re-handshakes within ~3-5 s; the 5 s START_TIME watchdog is therefore the right order of magnitude.
// OB1 - Network 21 Re-init CP #1
A "M_NEW_MASTER"
S "M_DO_REINIT" // latch a one-cycle pulse
A "M_DO_REINIT"
R M 180.0 // drop CP_START
R M 180.3 // clear CP_START_OK
R M 180.4 // clear CP_START_ERROR
AN "M_DO_REINIT"
S M 180.0 // re-arm CP_START
A "M_DO_REINIT"
R "M_DO_REINIT" // clear the pulse
// OB1 - Network 22 Re-init CP #2 (identical, with 190.x range)
9.3 Optional: verify remote I/O is back
The first symptom of a switchover is the new CPU's Profibus link to the IM153 returning. Standard S7-300 does not expose a single "rack OK" flag, but you can derive one from the slot-status of the IM153. Add the IM153 to HW Config and place a "DP slave diagnostics" call in OB82/OB86, or simply time-slice a heartbeat (e.g. write a known pattern into the first input word of the rack and read it back in the first output word). If the readback matches the pattern within 2 s the rack is alive; only then re-arm CP_START.
10. Communication Parameters and Timing
| Parameter | Recommended value | Notes |
|---|---|---|
| Baud rate | 19200 bit/s | Yokogawa and most SCADA masters default to 19200; reduce to 9600 for long trunks > 600 m |
| Parity | Even | Match between dongle parameter set and master |
| Response timeout | 2000 ms (dongletool) | Tuned to expected OB1 cycle + RTU inter-frame gap (3.5 char) |
| Inter-frame gap | 3.5 char ≈ 4 ms @ 19200 | CP341 enforces automatically; do not poll faster than 50 ms from the master |
| Master poll period | ≥ 200 ms per CP | Two slaves polled in round robin; total 400 ms |
| Modbus function codes | 03 (read holding), 04 (read input), 06 (write single), 16 (write multi) | Enabled in the dongle parameter set |
| Data update rate observed (Yokogawa) | 2 s with reduced map, > 2 min with full map | Slow update indicates the master is reading more registers than fit in one RTU frame (max 125 registers / 250 bytes per FC03/04 transaction) |
Frame budget check. A typical Modbus RTU request/response pair for 100 holding registers at 19200 bit/s is:
Frame size = 8 bytes (header) + 2*N bytes (data) + 5 bytes (CRC)
= 8 + 2*100 + 5 = 213 bytes
Byte time @19200,10,N,1 ≈ 1/1920 s ≈ 0.52 ms
Frame time = 213 * 0.52 ms ≈ 111 ms
Round trip = 111 ms request + 111 ms response + 4 ms gap ≈ 226 ms
Two slaves polled sequentially on a 200 ms period therefore finish in ~450 ms, comfortably inside the 2 s Yokogawa default. If you need a faster update, split the data set across both CPs (FC03 on CP #1 for a subset, FC03 on CP #2 for the rest) so the master only requests 50-60 registers per CP.
11. Yokogawa DCS Master Configuration Notes
When the Modbus master is a Yokogawa CENTUM or Exaquantum gateway:
- Configure the Yokogawa Modbus communication subsystem with two child devices (one per CP), both pointing to the same physical COM port of the gateway if the CPs are on a single RS-485 trunk, or to separate ports if isolated.
- Set slave addresses 5 and 6 to match the dongle parameter set.
- Match the byte order (big-endian Modbus vs. little-endian S7 data). The CP341 Modbus dongle ships big-endian by default; in the S7 program you must therefore use
TAW(swap bytes in a word) when reading word-sized values from the master. - Yokogawa default retry count = 3 with retry interval = 1 s. If both CPs go down simultaneously, suppress Yokogawa alarms to avoid storming the event log.
- For the "very slow update" symptom reported with the PCS 7 sample Modbus slave program: the bottleneck is almost always the single FB80 instance being polled for the entire data map. Splitting the map across two FB80 calls (one per CP) is the standard fix and brings the update period back to ≤ 2 s.
12. FB80 Error Codes
| ERROR_NR | ERROR_INFO | Likely cause | Remedy |
|---|---|---|---|
| 0 | 0 | No error | - |
| 0x0001 | 0 | Dongle not present or invalid | Re-seat 6ES7 870-1AB01-0YA1, re-license with PIP_PB |
| 0x0002 | 0 | Dongle parameter set corrupt | Re-load parameter set, re-power CP341 |
| 0x0005 | Slot | Logical address in IDB does not match CP slot | Check LADDR in IDB vs. HW Config |
| 0x0007 | 0 | CP341 in wrong mode (e.g. ASCII, not Modbus) | Switch dongle protocol to Modbus RTU |
| 0x000B | Char delay | Response timeout too short for the configured baud rate | Increase Response timeout in dongle parameter set |
| 0x0010 | 0 | Watchdog elapsed (init did not finish in START_TIME) | Increase START_TIME; check that IM153 is reachable |
| 0x00FF | Any | Internal CP341 firmware error | Power-cycle CP341, re-run CP_START |
Codes are documented in the Siemens Support FAQ on CP341 error codes and the MODBUS library manual.
13. Verification Procedure
- Compile and download the S7 project to CPU-A. With CPU-B in stop, power up the IM153 and both CP341 modules. In OB1 watch
M180.3andM190.3; both must turn TRUE within 5 s.MW182andMW192must be 0. - Connect a Modbus RTU master (laptop with Modbus Poll, or Yokogawa gateway) to the RS-485 trunk. Poll holding registers starting at address 0 on slave 5, then slave 6. Both slaves must respond with identical register contents.
- Trigger a forced toggle of a coil (FC05) on slave 5 and verify the corresponding bit in the S7 process image. Repeat on slave 6.
- Bring CPU-A to stop, allow CPU-B to take over. Both
CP_START_OKflags must drop to FALSE briefly, then re-assert within 5 s thanks to the re-init logic from Section 9. The Modbus master must observe uninterrupted polling on both slaves. - Disconnect the RS-485 cable from one CP. The master's polls to that slave must return "no response" within the configured timeout, while the other CP continues to serve data. Reconnect the cable and verify the slave re-appears within 5 s without manual re-init.
- Use the S7 diagnostic buffer to confirm only the expected info entries (CP341 initialized, dongle loaded). Any "OB122 access error" suggests
OB_MASKis FALSE or the LADDR is wrong.
14. Troubleshooting Matrix
| Symptom | Likely root cause | Action |
|---|---|---|
| Only the first CP responds; second stays silent | Both FB80 calls use the same IDB, or M180.x flags are shared with CP #2 | Generate a second IDB (DB102), set its LADDR to the second CP base address, and use M190.x for the second FB80 |
| Both CPs respond on first power-up, but after CPU switchover only the "last" CP works | CP_START not re-issued on master take-over; dongle handshake on first CP goes stale | Implement the re-init pulse from Section 9.2 on the rising edge of MASTER_HEARTBEAT |
| CP_START_ERROR after 5 s, ERROR_NR = 0x0010 | Watchdog too short, or IM153 not yet online at OB1 start | Increase START_TIME to S5T#10S, gate CP_START on the IM153 heartbeat |
| Master sees CRC errors, no response | RS-485 termination missing or wrong | Place 120 Ω across A/B on the last slave; remove from middle devices |
| Yokogawa sees inverted word values | Byte order mismatch (S7 little-endian vs. Modbus big-endian) | Apply TAW in S7 to swap bytes after reading via FB80's data DB |
| Update time > 2 min on Yokogawa | Single FB80 serves a large register map | Split the data set between CP #1 and CP #2, halve the per-CP register count |
| CP341 communication SF LED on, BF blinking | Dongle missing or wrong protocol | Re-seat dongle, re-license with dongle tool, check protocol = Modbus RTU |
| No "DP slave OK" for the IM153 in the new CPU | Profibus address conflict between the two CPU DP ports | Use the same DP address for the IM153 from both CPUs and let MPI redundancy arbitrate; verify with the diagnostic buffer |
15. Field-Proven Caveats
- Do not reuse the same Modbus address mapping on both CPs unless the data on the wire must be identical. The Modbus register window in the dongle is what the master sees, not the S7 process image. If both CPs share the same Modbus register range, the master can poll either CP for the same data and you get true transparent redundancy.
- Sharing the same flag range (e.g. M180.x for both CPs) does not "initialize both at once" - it overwrites the edge flag of the first FB80 and breaks its handshake. The Siemens "securised bloc" (FB80) reads and clears internal status bits; if a single flag is touched from outside the call, the next cycle observes an inconsistent state.
- On Yokogawa gateways, the communication timeout on the Modbus driver must be > 3 × baud-rate-byte-time × max frame size. At 19200 bit/s with 250-byte frames this is ≥ 800 ms; many default Yokogawa templates ship with 500 ms which causes silent drops.
- CP341 initialization is non-reentrant. Do not call FB80 inside a faster OB (e.g. OB35) or you risk mid-init interrupts. Stick to OB1 and OB100.
- If you migrate the CP341 to a CM PtP (ET200S) for a newer installation, the block changes (use FB80 from the "MODBUS PN" library) but the dual-flag / dual-IDB discipline is identical.
FAQ
Do I need two instance DBs for two CP341 modules on the same S7-300?
Yes. Each FB80 (MODB_341) call must reference its own instance DB (e.g. DB101 for CP #1, DB102 for CP #2). The instance DB stores the receive/transmit pointers and the dongle handshake state; sharing one IDB between two CPs corrupts both channels and typically results in only the first CP responding.
Can I reuse the same flag range (M180.x) for both CP341 modules?
No. The flag range is the I/O interface of FB80; if two FB80 calls share the same M180.x bits, the second call's CP_START or CP_START_FM manipulation will overwrite the first call's state, causing a stale dongle handshake. Use M180.x for the first CP and M190.x for the second, and pair them with independent timers (T120 / T121) and error words (MW182/184 vs. MW192/194).
Why does only the last-initialized CP341 keep working after a CPU switchover?
The CP341 dongle handshake is stateful; after a CPU switchover the new CPU's first FB80 call sees CP_START_OK=TRUE on the first CP because that flag reflects the previous owner's view, while the dongle itself is no longer bound to a live session. Manually re-issuing CP_START on both channels whenever the local CPU takes over (rising edge of a master heartbeat) re-runs the handshake on both CPs and restores redundant operation without a panel power cycle.
How do I split a large Modbus register map between two CP341 modules to improve Yokogawa update time?
Halve the process data set and load one half into the CP #1 dongle parameter set, the other half into CP #2. The Yokogawa gateway then issues FC03 (read holding) on slave 5 for the first half and on slave 6 for the second half. With 50-60 registers per CP at 19200 bit/s the round-trip per CP is ~60 ms, giving a full update every ~200 ms when the master polls both slaves in round robin.
What is the correct dongle order number for CP341 Modbus RTU slave?
Use 6ES7 870-1AB01-0YA1 (Modbus RTU slave dongle). The dongle stores the protocol parameter set including baud rate, parity, response timeout, and the Modbus register window. Each CP341 requires its own dongle; both dongles must carry identical parameter sets if the master expects the same data on either CP.