Problem Description
On a SIMATIC S7-1200 CPU communicating through a CM 1241 RS422/RS485 communication module, engineers frequently encounter Modbus RTU error code 16#8070 when scaling the polling list past a single-digit number of slaves. The classic symptom pattern is reproducible:
- Slaves at addresses 1 through 7 respond correctly and return valid data.
- Slaves at addresses 8, 9, 10 — and any slave polled by an additional
MB_MASTERinstance — transition toSTATUS = 16#8070. - Removing the eleventh
MB_MASTERinstance makes the error disappear, restoring correct operation of the remaining ten. - CPU diagnostic buffer shows the work memory at roughly 30% used and load memory at 9% used — well below the resource ceiling.
The condition is independent of the 32-device physical limit of the RS-485 bus. The fault is software-side, not electrical, and originates inside the MB_MASTER instruction instance itself.
Decoding Error Code 16#8070
16#8070 in the MB_MASTER.DONE / MB_MASTER.ERROR status word is defined in the S7-1200 Modbus RTU instruction set as "All internal instance memories are in use". The instruction is attempting to claim a temporary internal buffer (used to hold the request frame, the response frame, and the timeout/retry state machine) and the runtime cannot allocate it.
| STATUS (hex) | Meaning | Typical Trigger |
|---|---|---|
| 16#0000 | No error, transaction idle | Normal steady state |
| 16#7000 | No active request |
REQ low |
| 16#7001 | First request executing | Normal busy |
| 16#7002 | Subsequent request executing | Normal busy, queued |
| 16#8070 | All internal instance memories are in use | Instance pool exhausted; overlapping calls |
| 16#8180 | Modbus exception from slave (read access denied) | Slave returns 0x02 |
| 16#8181 | Modbus exception (write access denied) | Slave returns 0x02 |
| 16#82C8 | Slave response timeout | No response / wrong address |
| 16#82CA | CRC or parity error in response | Bus integrity issue |
Root Cause Analysis
The S7-1200 legacy Modbus RTU instruction set — MB_COMM_LOAD and MB_MASTER documented in the SIMATIC S7-1200 Manual Collection — is built around a single-master, single-channel design. Several architectural constraints are commonly violated when scaling past a small number of slaves:
Cause 1: Multiple MB_COMM_LOAD Instances on the Same Port
MB_COMM_LOAD is a one-time port-configuration block. It sets the baud rate, parity, stop bits, flow control, and RTS-on-delay/off-delay for the CM 1241 point-to-point port. Once it has executed, the port is configured and remains configured. Calling MB_COMM_LOAD a second time with different parameters re-initializes the port mid-transaction and can reset the internal state of an active MB_MASTER instance, causing the request queue to corrupt. Multiple MB_COMM_LOAD blocks on the same logical port is unsupported and is the most common trigger for the 11th-instance failure.
Cause 2: Multiple MB_MASTER Instances Triggered Simultaneously
The official Siemens documentation states explicitly: "Pre-emption of a Modbus master instruction by another Modbus master instruction in a higher priority execution priority level will result in improper operation." Each MB_MASTER instance holds an internal instance memory block. If two or more instances see a rising edge on REQ in the same OB1 scan, or if the OB priority is not identical, the runtime cannot arbitrate the shared port and returns 16#8070 for the loser. The CM 1241 driver has a fixed pool; once that pool is exhausted by overlapping calls, additional instances fail.
Cause 3: Timer-Based Polling Architecture
Polling every MB_MASTER on a cyclic timer (e.g., a 100 ms clock OB) guarantees that several instances raise REQ in the same scan. The instances are not synchronized to the actual response time of the slaves, so a slow slave causes its instance to remain BUSY when the next timer tick re-asserts REQ. The instruction drops the new request, the instance counter advances, and after a small number of slaves the pool is fully consumed.
Cause 4: Overlapping Instance DB Memory
When the calling function block is created with optimized block access, the instance data block layout is automatic; when it is non-optimized, the engineer controls the offsets. Two MB_MASTER instances inside the same FB with hand-laid offsets that share a work-word can corrupt the internal status word of one of them, surfacing as 16#8070 on the next rising edge.
Solution: Single MB_COMM_LOAD + Single MB_MASTER Multiplexer
The supported and field-proven pattern on S7-1200 with CM 1241 is a single MB_COMM_LOAD + single MB_MASTER with parameter multiplex. The master is asked to talk to a different slave on each cycle; the slave list is iterated by a sequencer. REQ is asserted only after the previous transaction reports DONE or ERROR.
Architecture Diagram
Implementation Pattern (SCL / Structured Text)
The REQ input of MB_MASTER is edge-sensitive. A rising edge starts a transaction; holding REQ high does not start another. Use a single rising-edge auxiliary bit that the sequencer raises only after a previous DONE or ERROR:
// FB "ModbusPoller" — call in OB1, single instance DB
VAR
iSlaveIndex : INT; // 0..N, points into aSlaveList
xReqEdge : BOOL; // rising-edge helper
xReqPrev : BOOL; // previous scan of REQ
xBusy : BOOL;
xDone : BOOL;
xError : BOOL;
wStatus : WORD;
aSlaveList : ARRAY[0..31] OF INT := [1,2,3,4,5,6,7,8,9,10,11,12];
END_VAR
// ---- Edge detect on REQ ----
IF NOT xReqPrev AND mb_master.DONE OR mb_master.ERROR THEN
xReqEdge := TRUE;
END_IF;
xReqPrev := mb_master.DONE OR mb_master.ERROR;
// ---- Single MB_MASTER call, multiplexed ----
mb_master.REQ := xReqEdge;
mb_master.MB_ADDR := aSlaveList[iSlaveIndex];
mb_master.MODE := MB_MODE_READ; // or MB_MODE_WRITE per slave
mb_master.DATA_ADDR := 40001; // remap per slave if needed
mb_master.DATA_LEN := 10;
mb_master.DATA_PTR := pSlaveData[iSlaveIndex];
mb_master();
xDone := mb_master.DONE;
xError := mb_master.ERROR;
wStatus := mb_master.STATUS;
// ---- Advance sequencer only on terminal state ----
IF xDone OR xError THEN
xReqEdge := FALSE;
IF xError AND wStatus = 16#8070 THEN
// log and continue — do NOT block the sequencer
END_IF;
iSlaveIndex := (iSlaveIndex + 1) MOD (MAX_INDEX + 1);
END_IF;
Single MB_COMM_LOAD
Place exactly one MB_COMM_LOAD in the startup OB (OB100) or in OB1 with a one-shot firstScan flag. After it reports DONE = TRUE, the port is configured and the block should never be called again until the next CPU restart.
// OB100, cold restart
IF "FirstScan" THEN
mb_comm_load.REQ := TRUE;
mb_comm_load.PORT := 1; // CM 1241 port identifier
mb_comm_load.BAUD := 9600;
mb_comm_load.PARITY := 0; // 0=None, 1=Odd, 2=Even
mb_comm_load.FLOW_CTRL := 0; // 0=None for RS-485 2-wire
mb_comm_load.RTS_ON_DLY := 0;
mb_comm_load.RTS_OFF_DLY := 0;
mb_comm_load();
"FirstScan" := FALSE;
END_IF;
Ladder Equivalent
For engineers working in LAD rather than SCL, the equivalent structure is well documented in the legacy sample project shipped with early TIA Portal versions and accessible through the CM 1241 entry in the Siemens Online Support. The pattern uses a STEP counter that increments on MB_MASTER.DONE or MB_MASTER.ERROR, a SHR or move ladder that maps STEP to slave address, and an explicit reset of the REQ coil after each terminal state.
Holding Registers Past Address 125 (Related Failure Mode)
A second failure mode that often surfaces when scaling Modbus polling is reading registers above address 400125. The Modbus RTU function codes 0x03 (read holding) and 0x06 (write single) address a 16-bit offset, but a historical limitation in some masters restricted reads to ≤125 words per transaction. The S7-1200 MB_MASTER itself does not impose this limit on the slave address range — registers at 40601 are read by setting DATA_ADDR = 601 with MODE = MB_MODE_READ. The 125-word DATA_LEN ceiling is per-transaction, not per-slave. If a slave requires 600 contiguous registers, split the request into multiple transactions across the sequencer rather than exceeding DATA_LEN.
Verification Procedure
- Open TIA Portal, compile the project, and download to the CPU. Confirm the CM 1241 is in
RUNand that the port LED shows activity when a slave is polled. - Open Online & Diagnostics → Diagnostics buffer. Verify no
16#8070entries are added as the sequencer cycles through all slaves. - Place a watch table on the
MB_MASTER.STATUSword. Expected values during healthy operation:16#0000idle,16#7001or16#7002while a request is in flight, then back to16#0000after a successfulDONE. - Force the sequencer to address 11 (the previously failing index) by writing to
iSlaveIndex. ConfirmSTATUS = 16#0000andDONE = TRUEwithin the configured response timeout. - With a Modbus sniffer (e.g., a third-party RS-485 tap) confirm one and only one request frame is on the bus at any time. Frame spacing should match the configured
RTS_OFF_DLYplus the slave response time. - Cycle the CPU power to confirm the single
MB_COMM_LOADin OB100 reinitialises the port cleanly on restart.
Workarounds If You Must Keep Multiple MB_MASTER Instances
There are cases where a sequencer is impractical (e.g., independent FB libraries per device, time-critical per-slave rate). In those cases, the following workarounds reduce — but do not eliminate — the risk of 16#8070:
| Workaround | Effect | Cost |
|---|---|---|
Place each MB_MASTER in its own priority class (e.g., OB1 + OB35) and let pre-emption arbitrate |
Prevents simultaneous REQ edges | May violate the Siemens pre-emption rule documented in the S7-1200 manual collection |
Switch to the newer Modbus_Master instruction from the PtP library (Firmware ≥ V4.2 of the CM 1241) |
Different pool, multi-master friendly | Requires firmware update and re-engineering |
| Add a second CM 1241 module and split slaves across two ports | Doubles the available instance pool | Hardware cost, two trunks |
| Use Modbus TCP via the PROFINET port of the CPU | Bypasses the RTU pool entirely | Slaves must support TCP |
MB_MASTER instances on the same port is not officially supported. The single-multiplexer pattern is the supported configuration. The workarounds above are field workarounds and are not endorsed by Siemens for new designs.Related Status Codes You Will See During Recovery
After moving to the single-master architecture, expect to see legitimate slave-side status codes that were previously masked by 16#8070. Recognising them is part of the fix:
-
16#82C8— Slave response timeout. Confirm baud rate, parity, and that the slave address matchesMB_ADDR. -
16#82CA— CRC or framing error. Check termination, shielding, and the 2-wire A/B polarity. -
16#8180/16#8181— Modbus exception 02 (illegal data address) or 03 (illegal data value) from the slave.
Key Takeaways
-
16#8070means local instance memory exhaustion, not a slave problem. - Use one
MB_COMM_LOADand oneMB_MASTERper CM 1241 port. - Drive
REQfrom theDONE/ERRORstate, not from a timer. - Multiplex the slave address, mode, and data pointer through a sequencer.
- Validate with a Modbus sniffer that one — and only one — request is in flight at a time.
What does Modbus error code 16#8070 mean on an S7-1200 MB_MASTER?
16#8070 means the instruction cannot allocate its internal instance memory — the local pool is exhausted. It is a local, not remote, error; the slave never receives the request. It is most often caused by multiple MB_MASTER instances with overlapping REQ edges, or by multiple MB_COMM_LOAD blocks resetting the port mid-transaction.
How many MB_MASTER instances can run on one CM 1241 port?
There is no fixed documented maximum, but the single-master pattern is the supported configuration. In practice, more than 7–10 instances frequently trigger 16#8070 because of overlapping requests. A single MB_MASTER with a slave-address sequencer scales to the full 32-node RS-485 physical limit.
Do I need more than one MB_COMM_LOAD for multiple slaves?
No. MB_COMM_LOAD configures the port once (baud, parity, flow control, RTS timing). Call it exactly once, typically in OB100 with a first-scan flag, and never re-call it during normal operation. Repeated calls re-initialise the port and corrupt active MB_MASTER state.
Can MB_MASTER read Modbus holding registers above address 400125?
Yes. The 125-word limit is per-transaction, not per-address range. Set DATA_ADDR to the offset above 400000 (for example, 601 to read 40601) and keep DATA_LEN ≤ 125. For blocks larger than 125 words, split the request into multiple sequencer steps.
Why must MB_MASTER.REQ see a rising edge on every transaction?
REQ is edge-triggered. A 0→1 transition starts a new Modbus request. Holding REQ high does not start a second request and does not re-arm the instruction after DONE. The sequencer must pulse REQ low for at least one scan, then high again, to issue the next transaction.