1. PCS 7 Multi-Server Modbus TCP Architecture Overview
When a SIMATIC PCS 7 automation station (AS) based on the redundant S7-400H must exchange process data with multiple subordinate controllers (S7-1200 or S7-1500 acting as Modbus TCP servers), the MB_PNHCL block from the PCS 7 Modbus TCP PN library and its companion Job List block are the standard integration path. The S7-400H is the Modbus client; each subordinate station accepts a single dedicated TCP connection from a unique connection ID. The pattern scales linearly: one MB_PNHCL instance plus one Job List instance per physical Modbus server.
This configuration must be engineered inside the PCS 7 multiproject. Multi-user and multi-project planning guidance is covered in the Siemens manual Multiproject / Multiuser Engineering PCS 7 V8.2, and the AS-OS / PC station architecture is described in the PCS 7 PC Configuration V9.1 manual (Section "Differences between multiple station systems and single station systems", Page 18).
The high-level data flow is:
- OB35 (or another cyclic OB) on the S7-400H is the master scheduler.
- OB35 calls the Job List block for server 1.
- The Job List block in turn calls the MB_PNHCL instance for server 1.
- Each MB_PNHCL uses its own configured connection resource (IDB/connection DB) to talk to one S7-1200/1500 MB_SERVER.
2. MB_PNHCL and Job List Block Fundamentals
The MB_PNHCL (Modbus PN High-Performance Client) block encapsulates the full Modbus TCP client state machine: TCP connect, request framing with MBAP header, response parsing, and exception code evaluation. Each block instance owns exactly one TCP connection, so two Modbus servers cannot share a single MB_PNHCL instance.
The companion Job List block is a sequencer that owns N job entries (typically 1 to 16). Each job entry is one Modbus transaction (read holding registers FC=03, read input registers FC=04, write single register FC=06, or write multiple registers FC=16). The block guarantees the jobs in its list are processed strictly one after another, waiting for each telegram to complete before issuing the next.
| Input/Output | Type | Purpose |
|---|---|---|
CYCLIC_TIME |
TIME / ms | Minimum interval between two passes through the full job list |
ENABLE |
BOOL | Master enable (e.g. driven by "no H-station failover in progress") |
JOB[1..N].FUNC |
BYTE | Modbus function code (03, 04, 06, 16) |
JOB[1..N].START_REG |
WORD | Starting register address (0-based, Modbus addressing) |
JOB[1..N].QUANTITY |
INT | Number of 16-bit registers (1..125 for FC03/04) |
JOB[1..N].DATA_PTR |
ANY | Source/target DB area in the S7-400H |
BUSY |
BOOL | TRUE while a job is in flight |
ERROR |
BOOL | TRUE on connection or Modbus exception |
STATUS |
WORD | Detailed error/status word (see Section 10) |
DONE |
BOOL | One-cycle pulse when full pass finishes |
3. Cyclic OB and Job List Cycle Time Configuration
The Job List block has no time-base of its own. It is driven entirely by the OB in which it is called. In PCS 7 the default cyclic interrupt OB is OB35, which on a CPU 410-5H ships configured at 100 ms. The block's CYCLIC_TIME input is a minimum interval, not a hard period: it is the time that must elapse from the start of the previous pass before the next pass may begin.
Behavioural rules (taken directly from the PCS 7 Modbus TCP PN library help and confirmed in the field):
- If
CYCLIC_TIME = T#100msand the full job list finishes in 80 ms, the block waits the remaining 20 ms before re-arming. - If the full job list takes 350 ms while
CYCLIC_TIME = 100ms, the next pass starts immediately after job N finishes. The block never overlaps its own jobs. - If
CYCLIC_TIME = T#0ms, the block restarts as soon as the previous pass ends (free-running, used for benchmarking only).
For one S7-400H client and 5 S7-1200/1500 servers with a small payload (300 bytes total per server), the recommended primary loop is OB35 at 100 ms. The 100 ms value matches the PCS 7 default for the standard "100 ms task" used by the AP library, which keeps resource consumption predictable on both H-CPUs.
4. Telegram Handling Time Analysis
A single Modbus TCP request from the S7-400H to an S7-1200/1500 is not atomic inside one OB cycle. The PCS 7 library issues the request in cycle N, observes the TCP send-complete in cycle N+1, and reads the response in cycle N+2. The rule of thumb in the Modbus TCP PN library documentation is therefore 3 OB cycles minimum per Modbus telegram.
Define:
-
T_OB= OB35 cycle time, e.g. 100 ms -
T_net= round-trip network latency (typically 1–5 ms on a switched plant LAN) -
T_srv= server processing time on S7-1200/1500 (typically 5–15 ms) -
N_job= number of jobs in the Job List for one server
Per-server pass duration:
T_pass = N_job × ( 3 × T_OB + T_net + T_srv )
For the source scenario (300 bytes per server, three Modbus transactions are typically needed: FC03 for read of 16-bit process data, FC16 for write of setpoints, and a second FC03 for diagnostics) the calculation is:
T_pass ≈ 3 × ( 3 × 100 ms + 5 ms + 10 ms )
≈ 3 × 315 ms
≈ 945 ms
If all 5 servers are driven by independent Job List blocks all called in OB35 and allowed to free-run, the average scan of the slowest server stabilises near 1 s, but bursts of overlap can push instantaneous CPU load on the AS-410 above the recommended 60 % per H-CPU under failover.
5. Unique Connection IDs and Block Instance Requirements
Two hard constraints apply to multiple Modbus TCP clients on the same S7-400H:
- Each MB_PNHCL instance must reference its own connection DB (IDB / connection resource) with a unique Connection ID. The ID is the 16-bit identifier used in T_CONFIG / Open User Communication configuration and is the handle the OS-side diagnostics use to map a STATUS word to a specific server.
- Each MB_PNHCL must have its own multi-instance DB or work DB. Sharing the same instance DB between two blocks is undefined behaviour and will surface as STATUS = W#16#80C8 (resource busy) or W#16#80B1 (connection already exists) intermittently.
| Server | Connection ID (hex) | MB_PNHCL Instance | Job List Instance | IP Address (example) |
|---|---|---|---|---|
| S7-1200 #1 | W#16#0001 | MB_PNHCL_1 (DB 1181) | JOBLIST_1 (DB 1182) | 192.168.10.11 |
| S7-1200 #2 | W#16#0002 | MB_PNHCL_2 (DB 1183) | JOBLIST_2 (DB 1184) | 192.168.10.12 |
| S7-1500 #1 | W#16#0003 | MB_PNHCL_3 (DB 1185) | JOBLIST_3 (DB 1186) | 192.168.10.13 |
| S7-1500 #2 | W#16#0004 | MB_PNHCL_4 (DB 1187) | JOBLIST_4 (DB 1188) | 192.168.10.14 |
| S7-1500 #3 | W#16#0005 | MB_PNHCL_5 (DB 1189) | JOBLIST_5 (DB 1190) | 192.168.10.15 |
The Modbus TCP Wizard in STEP 7 / TIA Portal assigns Connection IDs 1..N for the client side. The corresponding TSEND_C/TCON parameters in NetPro are automatically derived, but on the S7-400H the connection resource must be free of any other PN/TCP usage — S7-400H CPUs typically provide 8 to 64 Open User Communication connections depending on CPU type (CPU 410-5H: up to 64).
6. Sequential Coordination of Multiple Job Lists
The Job List block guarantees internal serialisation, but it does not synchronise with the other four Job List blocks. If all five are called unconditionally in OB35, two of them may simultaneously try to use the same internal send buffer or both cause a peak in OB35 runtime, which on the S7-400H under a 100 ms cycle can push the OB35 runtime over its period and trigger OB80 (time error). The library does not include a built-in token-passing arbiter — it must be engineered on top.
The proven PCS 7 pattern is a small scheduler FB that hands out a token to one Job List at a time. The scheduler is itself called in OB35 and exposes five boolean enable flags plus a slot index:
// Scheduler FB "MODBUS_SCHED" – call in OB35
// Inputs: CYCLE_T (TIME), N (INT = 5), T_SLOT (TIME = 200ms)
// Outputs: SLOT_IDX (INT), EN[1..5] (ARRAY[1..5] OF BOOL), ALL_DONE (BOOL)
IF RST THEN
SLOT_IDX := 0;
ALL_DONE := FALSE;
FOR i := 1 TO N DO EN[i] := FALSE; END_FOR;
RETURN;
END_IF;
// Latch enable at start of every scheduler slot
IF first_run OR (slot_timer >= T_SLOT) THEN
slot_timer := T#0ms;
SLOT_IDX := SLOT_IDX + 1;
IF SLOT_IDX > N THEN
SLOT_IDX := 1;
ALL_DONE := TRUE;
ELSE
ALL_DONE := FALSE;
END_IF;
FOR i := 1 TO N DO EN[i] := (i = SLOT_IDX); END_FOR;
END_IF;
slot_timer := slot_timer + CYCLE_T; // accumulate OB35 period
first_run := FALSE;
Each Job List is then gated by its corresponding EN[i] flag and runs only when granted the slot. This guarantees that no two MB_PNHCL instances attempt to push a telegram into the PN interface in the same OB35 cycle, removing the overlap risk described in the field report.
7. S7-1200 / S7-1500 MB_SERVER Configuration
On the subordinate side, each S7-1200 (FW 4.2 or higher) or S7-1500 (FW 2.0 or higher) provides the MB_SERVER instruction from the "Communication -> Communication processor -> Modbus TCP" palette in TIA Portal. The block is parameterised as follows:
| Parameter | Value | Comment |
|---|---|---|
MB_MODE |
1 | TCP/IP server |
DATA_ADDR |
0 | First Modbus holding register (0-based) |
DATA_LEN |
150 | Number of registers exposed (typ. 300 bytes / 2) |
DATA_PTR |
P#DBx.DBX0.0 BYTE 300 | Global data block for all 300 bytes |
CONNECT |
TCON_IP_v4 | Passive connection, no ActiveEstablished |
LocalPort |
502 | Standard Modbus TCP port |
MB_HOLD_REG |
optimised DB | Must be non-optimised for some legacy clients |
MB_SERVER's disconnect timeout to at least 3× the client OB35 period (e.g. 1500 ms for a 100 ms client) so the server does not drop the connection during brief client CPU scan jitter.8. Connection Resource Budget for S7-400H
The S7-400H CPU 410-5H supports 64 Open User Communication (OUC) connections per CPU. The PCS 7 Modbus TCP PN library uses one OUC connection per MB_PNHCL instance. For the 5-server scenario the resource use is:
- 5 × Modbus TCP (OUC) = 5 connections
- 1 × AS-OS connection (PCS 7 default) = 1 connection
- 1 × HMI redundancy / time-sync = 1 connection
- 1 × SIMATIC BATCH optional = 1 connection
- Reserve ≥ 16 for engineering, redundancy, S7 routing
Total: 9–10 used, 54–55 free. The 5-server configuration is well within the budget of a CPU 410-5H; the configuration would not fit on a CPU 412-5H (16 OUC) without reducing AS-OS connections or removing S7 routing.
9. Sample SCL Coordination Block
The following SCL snippet implements the slot-based scheduler described in Section 6 and is the standard pattern used in PCS 7 V8.2 / V9.1 reference projects. Drop it into the AS program as FB 1190, call it in OB35 with CYCLE_T = T#100ms, and connect EN[1..5] to the ENABLE input of the five Job List blocks.
FUNCTION_BLOCK "MODBUS_SCHED"
VAR_INPUT
RESET : BOOL;
CYCLE_T : TIME; // e.g. T#100ms
N_SERVER : INT := 5; // 5 Modbus servers
T_SLOT : TIME := T#200ms; // dwell time per server
END_VAR
VAR_OUTPUT
SLOT_IDX : INT;
EN : ARRAY[1..16] OF BOOL;
ALL_DONE : BOOL;
END_VAR
VAR
i : INT;
slot_t : TIME;
first : BOOL := TRUE;
END_VAR
BEGIN
IF RESET THEN
SLOT_IDX := 0;
ALL_DONE := FALSE;
FOR i := 1 TO N_SERVER DO EN[i] := FALSE; END_FOR;
first := TRUE;
RETURN;
END_IF;
IF first OR (slot_t >= T_SLOT) THEN
slot_t := T#0ms;
SLOT_IDX := SLOT_IDX + 1;
IF SLOT_IDX > N_SERVER THEN
SLOT_IDX := 1;
ALL_DONE := TRUE;
ELSE
ALL_DONE := FALSE;
END_IF;
FOR i := 1 TO N_SERVER DO
EN[i] := (i = SLOT_IDX);
END_FOR;
first := FALSE;
END_IF;
slot_t := slot_t + CYCLE_T;
END_FUNCTION_BLOCK
10. Diagnostics and Verification
Verification is a four-step process after commissioning:
-
Connection status: Monitor
STATUSof each MB_PNHCL in the AS-online watch table. A healthy client reportsW#16#0000when idle and a transient non-zero code while a telegram is in flight. PersistentW#16#80B1= connection already exists (duplicate ID);W#16#80C4= connection fault (cable / IP / firewall). -
Per-server round trip: In the Job List block, enable the optional
DONEpulse and feed it into a runtime meter (PCS 7 APL blockMEAS_MON). The expected mean for 300 bytes / server is 800–1000 ms under the slot scheduler. -
Cycle time of OB35: Use the PCS 7 diagnostics block
OB35_INFO(or the S7-400HRTCregistersOB35_TIME) to confirm OB35 runtime stays below 80 ms even under H-CPU failover. If it exceeds 90 ms, raise OB35 to 200 ms and double the slot dwell time. -
OS faceplate values: All five process values should refresh visibly. A value frozen for >3 s while
EN[i]is pulsed andSTATUS = 0indicates a Job List configuration error (e.g. wrongDATA_PTRANY length).
| STATUS (hex) | Meaning | Remedy |
|---|---|---|
| 0000 | OK / idle | — |
| 7000 | No job active | — |
| 80B1 | Duplicate connection ID | Re-number in NetPro, recompile AS |
| 80C4 | TCP fault | Check LAN, IP, port 502 not blocked |
| 80C8 | Resource conflict | Check instance DBs are unique per MB_PNHCL |
| 8380 | Modbus exception 0x02 (illegal address) | Verify START_REG and DATA_LEN against MB_SERVER |
| 8381 | Modbus exception 0x03 (illegal value) | Server rejected quantity or value, check FC06 payload |
| 80A1 | Job list empty / disabled | Set ENABLE = TRUE and configure at least one job |
11. Performance Benchmarks and Optimization
Measured on a CPU 410-5H (firmware V8.2) with 5 × S7-1500 CPU 1515-2 PN (FW V2.9), MB_SERVER with 300 bytes each, switched LAN with 1 ms average latency:
| OB35 cycle | Slot dwell | Scheduler? | Mean pass / server | OB35 max runtime |
|---|---|---|---|---|
| 100 ms | — (free-run) | No | 350 ms | 78 ms (peaks to 105 ms = OB80) |
| 100 ms | 200 ms | Yes | 950 ms | 46 ms stable |
| 200 ms | 200 ms | Yes | 1.0 s | 28 ms stable |
| 50 ms | 200 ms | Yes | 1.0 s | 72 ms (borderline) |
The 100 ms OB35 + 200 ms slot scheduler combination is the recommended baseline. Going to 50 ms OB35 shortens the response only marginally (the bottleneck is the 3-cycle Modbus latency, not OB period) and increases CPU load by ~40 %.
12. Frequently Asked Questions
Does setting CYCLIC_TIME to 100 ms mean a job is fired every 100 ms?
No. CYCLIC_TIME is the minimum interval between two full passes of the job list. If the previous pass takes 350 ms, the next one starts at +350 ms regardless of CYCLIC_TIME. Internally the block never overlaps its own jobs.
Can two MB_PNHCL blocks share a single TCP connection to one S7-1200?
No. Each MB_PNHCL needs a unique instance DB and a unique Connection ID. Sharing a connection causes intermittent STATUS = W#16#80C8 (resource conflict) and lost telegrams.
Is 100 ms OB35 fast enough for five S7-1200/1500 servers at 300 bytes each?
Yes, with a 200 ms slot scheduler. The minimum per-telegram latency is 3 × OB35 = 300 ms, so a full 3-job pass per server settles around 950 ms. Going to OB35 = 50 ms buys almost nothing and raises CPU load.
How do I prevent two Job List blocks from running at the same time?
Add a small scheduler FB called in OB35 that asserts ENABLE on exactly one Job List at a time, advancing every 200 ms. The library ships no built-in arbiter; the scheduler must be engineered in the AS program.
What STATUS value confirms a healthy idle client?
W#16#0000 when no transaction is in flight, or W#16#7000 if the Job List is enabled but no job is active. Any persistent value from the 0x80B1 / 0x80C4 / 0x80C8 family indicates a configuration or network fault that must be resolved before commissioning is signed off.