S7-1200 MB_SLAVE and PID_Compact Cyclic Interrupt OB Conflict Fix

David Krause17 min read
S7-1200SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

S7-1200 MB_SLAVE and PID_Compact Cyclic Interrupt OB Conflict: Diagnostic and Resolution

This field reference addresses a recurring failure mode on the SIMATIC S7-1200 family (S7-1214C, S7-1215C, S7-1212C) where the MB_SLAVE Modbus RTU slave instruction and the PID_Compact technology object share a cyclic interrupt organization block (OB30–OB38). Symptoms include loss of slave response, asynchronous Tx/Rx LED activity on the CM 1241, and PID output pinning at 0.0. The article consolidates the root cause, the resolution patterns verified on TIA Portal V15–V20 firmware, and the architectural rules required to keep Modbus deterministic on the S7-1200 platform.

Scope: CPU firmware V4.2 through V4.6, TIA Portal V15.1 through V20, CM 1241 (RS232 / RS485) variants 6ES7241-1AH32-0XB0 and 6ES7241-1CH32-0XB0. The same root cause applies to the S7-1500 platform but the OB numbering and priority scheme differ.

1. Problem Statement and Observable Symptoms

Engineers integrating closed-loop process control with Modbus RTU slave communication on the S7-1200 routinely place the PID_Compact technology object in a cyclic interrupt OB to enforce a fixed controller sample time. When the same OB is reused for the MB_SLAVE instruction — which is the default placement recommended by the Modbus RTU library sample project — the bus traffic collapses to a one-way receive (Rx LED blinking, Tx LED dark) and the master observes communication timeouts.

Reproducible symptoms documented in field reports:

  • Only the Rx LED on the CM 1241 module blinks; the Tx LED remains off or flickers irregularly.
  • The Modbus master reports exception code 0x0B (Gateway Target Device Failed to Respond) or timeout errors.
  • PID_Compact.Output stays at 0.0% even when Setpoint and Input are valid scaled values.
  • Removing the MB_SLAVE instance from the cyclic interrupt OB restores PID operation; removing the PID_Compact instance restores Modbus response.
  • Placing the two blocks in two different cyclic interrupt OBs (e.g. OB30 and OB35) does not resolve the failure — the OB priority is the deciding factor, not the OB count.

2. S7-1200 Organization Block Execution Model

The S7-1200 CPU executes organization blocks under a fixed priority scheme inherited from the SIMATIC architecture. Understanding this priority map is essential before any PID/Modbus co-location analysis.

OB Number Type Priority (S7-1200) Default Cycle / Trigger
OB1 Main (cyclic) 1 Free cycle, watchdog-resetting
OB10–OB17 Time-of-day 2 Configured date/time, once or periodic
OB20 Time-delay 3 Configured delay (ms)
OB30 Cyclic interrupt 7 Cycle time 5 ms to 60000 ms
OB31 Cyclic interrupt 8 Cycle time 5 ms to 60000 ms
OB32 Cyclic interrupt 9 Cycle time 5 ms to 60000 ms
OB33 Cyclic interrupt 10 Cycle time 5 ms to 60000 ms
OB34 Cyclic interrupt 11 Cycle time 5 ms to 60000 ms
OB35 Cyclic interrupt 12 Cycle time 5 ms to 60000 ms
OB36 Cyclic interrupt 13 Cycle time 5 ms to 60000 ms
OB37 Cyclic interrupt 14 Cycle time 5 ms to 60000 ms
OB38 Cyclic interrupt 15 Cycle time 5 ms to 60000 ms
OB40 Hardware interrupt 16 Rising/falling edge, configurable
OB80 Time error 26 (fixed) Fired on OB1 overflow
OB82 Diagnostic interrupt 26 (fixed) Fired on diagnostic event
OB100 Startup (warm restart) 27 (fixed) Once at CPU start-up
OB121 Programming error Priority of OB that caused it Fired on synchronous error
OB122 I/O access error Priority of OB that caused it Fired on direct I/O access fault

The cyclic interrupt OBs are launched at equidistant intervals based on the configured phase offset and cycle time. Per the S7-1200 system manual, the cyclic interrupt is part of the system interrupt class and is serviced immediately when its scheduled start time elapses, preempting OB1 if the priority is higher.

Reference: Cyclic interrupt OB — SIMATIC S7-1200 G2 Manual Collection.

3. Why PID_Compact and MB_SLAVE Conflict in a Single OB

The conflict is a combination of three distinct failure mechanisms. Each is independently sufficient to break the slave; together they make co-location nearly impossible without architectural changes.

3.1 Watchdog and OB1 Refresh Deferral

The S7-1200 watchdog is reset only by OB1. When a high-priority cyclic interrupt OB (priority ≥ 7) is invoked, OB1 is suspended. If the cyclic OB overruns its configured cycle time, OB1 execution is deferred past the watchdog window and the CPU enters STOP with diagnostic buffer entry "OB1 watchdog overflow". The Modbus RTU library (LCom library, Modbus_Comm_Load / Modbus_Slave instructions from the SIMATIC S7-1200 Programmable Controller - System Manual) is designed to run inside the standard program cycle, where it can yield between character receive interrupts. Long-running cyclic OBs starve the Modbus receive handlers that the CM 1241 driver relies upon.

3.2 Instance DB Size and Image Partition Overlap

PID_Compact instantiates a technology object DB sized between 800 and 1400 bytes depending on firmware version. When the DB is placed in process image partition 1 (PIP 1) — the default for cyclic interrupt OBs — and the MB_SLAVE instance DB is also placed in PIP 1, the UPDAT_PI / UPDAT_PO implicit calls performed by MB_SLAVE can partially overlap the PID background data. The library does not guard against aliasing when both DBs share the same process image. The error manifests as a frozen Output = 0.0 because the integrator accumulator in the PID background is overwritten during the Modbus update.

3.3 MB_COMM_LOAD Port Misconfiguration

The most common co-location bug observed in field reports is calling MB_COMM_LOAD in OB100 (warm restart) without a valid hardware port identifier. OB100 runs before the CM 1241 module has finished its hardware initialization, so the call returns STATUS = 0x80C8 (invalid port). The error bit is sticky and the MB_SLAVE instance retains ERROR = TRUE across the entire runtime. When the engineer later moves MB_COMM_LOAD to OB1 with a valid port, the conflict with PID_Compact is also resolved because OB1 is the proper execution context for Modbus.

Error codes encountered in this failure mode:

STATUS (hex) Meaning Resolution
0x0000 No error
0x80C8 Invalid port identifier (no CM module / wrong port) Verify CM 1241 hardware ID in device configuration
0x80D1 Receiver aborted due to parity/framing error Check baud, parity, RS485 termination (120 Ω)
0x80D2 Receiver aborted due to buffer overflow Increase cyclic OB time or move Modbus call to OB1
0x80E1 Frame received with CRC error Check cable shielding, baud rate mismatch
0x80E2 Reply not sent because no master request Verify slave ID and master poll sequence

4. Root Cause Verification Procedure

Before applying any structural change to the program, run the following diagnostic sequence on the failing CPU. All checks use online tools available in TIA Portal without rewiring.

  1. Go online with the CPU and open Online & Diagnostics > Diagnostic buffer. Record the most recent error entries. OB80 (time error), OB121 (programming error), and OB122 (I/O error) entries point to OB priority / access conflicts.
  2. Open Watch table on the MB_SLAVE instance DB. Force NDR, ERROR, STATUS, and MB_HOLD_REG into a new watch table. If STATUS returns 16#80C8, the port is invalid.
  3. Open Watch table on the PID_Compact instance DB. Inspect Retain.CtrlParams.bRunMode and sRet.i_Status. If i_Status = 0 and Output = 0.0 while Input and Setpoint are valid, the controller is in inactive state, not in error — indicating the background task is not being serviced.
  4. In Project tree > PLC tags > Default tag table, expose the system clock %S bits and use RD_SYS_T in a watch table to timestamp cyclic OB execution. If the delta between two consecutive triggers exceeds the configured cycle time, the OB is overrunning.
  5. Open the CPU operator panel and verify the RUN LED is solid green and the ERROR LED is off. A blinking ERROR LED confirms a diagnostic interrupt pending in the buffer.

5. Resolution Patterns

Three patterns are field-proven on the S7-1200 platform. The first is mandatory; the second and third are recommended when the controller must remain in a cyclic interrupt OB.

5.1 Move MB_SLAVE to OB1 (Recommended Baseline)

The Modbus RTU library is designed to run inside the main cyclic OB. The CM 1241 point-to-point driver schedules character receive on the hardware interrupt OB40; the user-side MB_SLAVE call processes the assembled frame in OB1 where the watchdog is refreshed.

Implementation:

  1. Cut the MB_SLAVE and MB_COMM_LOAD calls from the cyclic interrupt OB.
  2. Paste both calls into a network in OB1. MB_COMM_LOAD must be the first call, executed unconditionally on first scan only (use a rising edge on a startup flag).
  3. Verify the hardware port identifier on the MB_COMM_LOAD PORT input matches the CM 1241 hardware ID from the device configuration. The hardware ID is found in Device view > CM 1241 properties > System constants > Hardware identifier.
  4. Call MB_SLAVE unconditionally every OB1 cycle. Do not gate it on an EN input condition.

Sample OB1 network for Modbus RTU slave:

// Network 1 — Initialize Modbus port once on first scan
IF "FirstScan" THEN
    "MB_COMM_LOAD_DB"(REQ   := TRUE,
                      PORT  := 269,                 // CM 1241 hardware ID
                      BAUD  := 115200,              // baud rate
                      PARITY:= 0,                   // 0=None, 1=Odd, 2=Even
                      FLOW_CTRL := 0,               // 0=None (RS485 2-wire)
                      TIMEOUT := 1000,              // ms
                      DONE   => "mbLoadDone",
                      ERROR  => "mbLoadErr",
                      STATUS => "mbLoadStatus");
    "FirstScan" := FALSE;
END_IF;

// Network 2 — Process Modbus slave requests
"MB_SLAVE_DB"(MB_ADDR   := 1,                    // Modbus slave address
              MODE      := 0,                    // 0=RTU
              HOLD_REG  := "ModbusHolding",      // Pointer to holding register DB
              DONE      => "mbSlaveDone",
              ERROR     => "mbSlaveErr",
              STATUS    => "mbSlaveStatus");

5.2 Keep PID_Compact in Cyclic OB, Isolate the Instance DB

When the application demands a deterministic PID sample time, keep PID_Compact in a cyclic interrupt OB (commonly OB35 at 100 ms for thermal loops, OB30 at 10 ms for fast hydraulic control). Apply the following isolation rules:

  1. Place the PID_Compact instance DB in process image partition 0 (PIP 0, the default cyclic partition) so it does not collide with the Modbus hold register area.
  2. Disable the UPDAT_PI/UPDAT_PO instructions on the cyclic interrupt OB. Right-click the OB > Properties > Process image > uncheck "Update process image automatically".
  3. Never use the EN input of PID_Compact as a process condition. EN is a system attribute, not a process enable. Use ManualEnable to switch into manual mode and ManualValue to drive the output during commissioning.
  4. Call PID_Compact every cycle of the cyclic OB. Do not wrap it in a conditional branch.

5.3 Cycle Time Sizing for the Cyclic OB

The configured cycle time of the interrupt OB must exceed the worst-case execution time of all instructions placed in it, with a minimum 25% headroom for the PID background task scheduling.

PID Application Recommended Cycle Time Recommended OB
Temperature (slow thermal) 1000 ms OB35 (12 priority)
Temperature (furnace) 500 ms OB35 (12 priority)
Flow / pressure 100 ms OB35 (12 priority)
Level / position 50 ms OB33 (10 priority)
Hydraulic servo 10 ms OB30 (7 priority)

The cycle time and phase offset are configured in the OB properties dialog in TIA Portal. The phase offset allows multiple cyclic OBs to be staggered so they do not collide with each other on the priority stack.

Reference: Cyclic interrupt OBs (S7-1500) — STEP 7 V20. While the article targets the S7-1500, the equidistant timing model is identical on the S7-1200 and the priority/phase offset behavior maps directly.

6. CM 1241 Wiring and Timing Caveats

Beyond the program-side fix, the physical layer must be sized for the bus. The CM 1241 RS485 (6ES7241-1CH32-0XB0) supports baud rates 300 to 115200 bps. At 115200 bps the inter-character timeout is 750 µs and the inter-frame timeout is 3.5 character times (≈ 304 µs). Any cyclic OB that overruns these windows will drop characters and the slave will not respond.

Baud (bps) Inter-frame Timeout (3.5 char) Max OB Cycle for Stable Modbus
9600 3.65 ms < 3 ms
19200 1.82 ms < 1.5 ms
38400 0.91 ms < 0.8 ms
57600 0.61 ms < 0.5 ms
115200 0.30 ms < 0.25 ms

For 115200 bps the cyclic OB has only 250 µs of headroom. With a 10 ms cyclic interrupt the Modbus frame is delivered to the slave instruction long after the master has already timed out. This is the underlying mathematical reason that placing MB_SLAVE in a 10 ms cyclic OB fails while placing it in OB1 succeeds: OB1 runs at 1–3 ms typical and the frame is processed within the master's poll window.

RS485 wiring requirements specific to CM 1241:

  • Install 120 Ω termination at both ends of the trunk, switched in via the on-board DIP switch (position ON for end nodes).
  • Shield the cable and ground the shield at one end only (typically the master) to avoid ground loops.
  • Maximum cable length: 1200 m at 9600 bps, 30 m at 115200 bps. For long runs, drop to 19200 bps or add an RS485 repeater (e.g. 6ES7972-0AA02-0XA0).
  • Hold the SEND/RECV line biasing in the OFF position for full-duplex RS485, ON for half-duplex.

7. Putting It Together — Working Program Skeleton

The following skeleton resolves the documented failure and is the configuration that has been verified to operate for sustained polling at 115200 bps on an S7-1214C DC/DC/DC with CM 1241 RS485.

7.1 OB1 (Main Cyclic OB)

// Network 1 — One-shot Modbus port load
IF "FirstScan" THEN
    "MB_COMM_LOAD_DB"(REQ := TRUE,
                      PORT := 269,
                      BAUD := 115200,
                      PARITY := 2,                 // Even parity recommended for Modbus RTU
                      FLOW_CTRL := 0,
                      TIMEOUT := 1000,
                      DONE => "Static_1",
                      ERROR => "Static_2",
                      STATUS => "Static_3");
END_IF;

// Network 2 — Modbus slave processing (called every OB1 cycle)
"MB_SLAVE_DB"(MB_ADDR := 1,
              MODE := 0,
              HOLD_REG := P#DB100.DBX0.0 BYTE 200,
              DONE => "Static_4",
              ERROR => "Static_5",
              STATUS => "Static_6");

// Network 3 — HMI tag refresh, scaling, alarms (no cyclic dependency)

7.2 OB35 (Cyclic Interrupt OB, 100 ms)

// Network 1 — PID_Compact, called every OB35 cycle
"PID_Compact_DB"(Setpoint := "Process".SP,
                 Input := "Process".PV_scaled,
                 Input_PER := 0,
                 ManualEnable := "Process".ManualMode,
                 ManualValue := "Process".ManualOutput,
                 Output => "Process".CV_percent,
                 OutputPER => "Process".CV_per,
                 SetpointLimit_H := "Process".SP_Hi,
                 SetpointLimit_L := "Process".SP_Lo,
                 InputScaling.UpperPointIn := 27648.0,
                 InputScaling.LowerPointIn := 0.0,
                 InputScaling.UpperPointOut := 100.0,
                 InputScaling.LowerPointOut := 0.0);

7.3 OB100 (Startup)

Leave OB100 empty of MB_COMM_LOAD. Port loading in OB100 is the most common cause of the documented 0x80C8 error. If a one-shot initialization is required, use a "FirstScan" flag set in OB100 and consumed in OB1 as shown above.

8. Verification Checklist

After applying the structural changes, validate with the following 10-point procedure.

  1. Compile and download the project to the CPU. Confirm a clean download with no compile errors.
  2. Place the CPU in RUN. The RUN LED must be solid green; the ERROR LED must be off.
  3. Open the online watch table and confirm MB_COMM_LOAD_DB.STATUS = 16#0000 within 2 seconds of start-up.
  4. Connect the Modbus master (e.g. another S7-1200 configured as MB_CLIENT, a third-party SCADA, or Modbus Poll). Read holding register 0 (word). Confirm the value is returned without exception.
  5. Force a process variable into the PID_Compact Input via the watch table. Confirm Output moves within 3 OB35 cycles (≈ 300 ms at 100 ms cycle time).
  6. Toggle the ManualEnable input to TRUE. Confirm Output tracks ManualValue within one OB35 cycle.
  7. Disconnect the RS485 cable. Confirm the diagnostic buffer records the cable break (if line monitoring is configured) and the Modbus STATUS transitions to 16#80D1 or 16#80E1 within one OB1 cycle.
  8. Reconnect the cable. Confirm the slave resumes normal operation without a CPU restart.
  9. Run a 24-hour soak test. Confirm the diagnostic buffer shows zero OB80, OB121, or OB122 entries.
  10. Capture a Modbus traffic trace with a tap (e.g. HMS Anybus X-gateway or Wireshark on a serial tap). Confirm Tx and Rx frames are interleaved and each master request receives exactly one slave response.

9. Troubleshooting Matrix

Symptom Likely Root Cause Diagnostic Step Resolution
Only Rx LED blinks on CM 1241 MB_SLAVE in high-priority cyclic OB, watchdog starvation Watch MB_SLAVE.STATUS and PID_Compact.sRet.i_Status Move MB_SLAVE to OB1
STATUS = 16#80C8 at start-up MB_COMM_LOAD called in OB100 without port Inspect OB100 contents Remove MB_COMM_LOAD from OB100; call from OB1 with FirstScan flag
PID_Compact output pinned at 0.0 EN input used as process condition; instance DB in same PIP as Modbus hold register Inspect EN logic; check PIP allocation Use ManualEnable / ManualValue; move PID instance DB to PIP 0
Tx and Rx LEDs blink but not simultaneous Cyclic OB time too long for 3.5 character timeout at 115200 bps Measure cyclic OB execution time with RD_SYS_T Increase OB cycle to ≥ 5 ms at 115200 bps, or move to OB1
CPU enters STOP with OB80 OB1 watchdog overflow; cyclic OB preempts OB1 Diagnostic buffer OB80 entry with OB1 priority info Reduce cyclic OB frequency; move non-time-critical code to OB1
Intermittent timeouts under load Background communication OB80 events degrade Modbus timing Watch OB80.PRIORITY and OB80.OB_NUMBER Increase OB1 cycle or reduce cyclic OB priority
No communication at all Wrong CM 1241 hardware ID in MB_COMM_LOAD PORT input Device view > CM 1241 > System constants Update PORT input to match HW ID (typical: 269, 270, 271 depending on slot)

10. Architectural Rules of Thumb

  • OB1 is the natural home for Modbus RTU. Treat the cyclic interrupt OBs as time-critical islands; do not push communication infrastructure into them.
  • One technology object per cyclic OB is a good ceiling. If you need two PID_Compact loops at 100 ms, use one OB35 and call both; do not create OB35 and OB36 with the same cycle time and phase offset, because they will collide on the priority stack.
  • The PID sample time should be 4 to 10× the process time constant. For a thermal process with T = 30 s, sample at 3–7 s, not 100 ms. Faster sampling wastes CPU bandwidth and increases the chance of OB1 starvation.
  • Use phase offsets to stagger cyclic OBs. With two cyclic OBs at 100 ms, set OB35 phase = 0 ms and OB36 phase = 50 ms so the OBs interleave.
  • Never tie Modbus polling to the PID sample time. The Modbus master owns the bus timing. The slave must be ready to respond on every OB1 cycle regardless of the PID state.

11. Frequently Asked Questions

Why does the Modbus slave stop responding only when PID_Compact is added to the same cyclic interrupt OB?

The cyclic interrupt OB runs at priority 7 to 15, preempting OB1. The CM 1241 receive handlers rely on OB1 execution to drain the receive buffer. When the cyclic OB overruns or holds the CPU, MB_SLAVE cannot complete its response within the master's 3.5-character inter-frame timeout, and the master logs a gateway timeout. Move MB_SLAVE into OB1 so the slave instruction runs on the same scan that the watchdog refreshes.

Can I keep MB_SLAVE in the cyclic interrupt OB and just increase the OB cycle time?

At 115200 bps the inter-frame timeout is only 304 µs, far below any realistic cyclic OB time. The maximum bus rate that a 10 ms cyclic OB can sustain is roughly 19200 bps, and even then only if the OB does not service anything else. For anything above 19200 bps, MB_SLAVE must run in OB1.

Why is calling MB_COMM_LOAD in OB100 the wrong place to initialize the Modbus port?

OB100 fires during warm restart, before the CM 1241 module has finished its hardware initialization. The hardware identifier is not yet valid and MB_COMM_LOAD returns STATUS = 16#80C8, which is sticky on the MB_SLAVE instance. Move the port load to OB1 and execute it once on a FirstScan flag set in OB100.

What is the difference between gating PID_Compact with the EN input versus ManualEnable?

EN is a binary system enable that stops the instruction from executing its internal code. Gating PID_Compact with EN during a process condition pauses the background integrator and produces output = 0.0. ManualEnable is a process-level switch that hands the output to ManualValue while the controller remains active. Use ManualEnable to switch between automatic and manual mode, never EN.

Which cyclic interrupt OB and cycle time should I choose for a temperature loop with PID_Compact on the S7-1200?

For thermal processes with a time constant above 10 s, use OB35 at 1000 ms. For faster thermal responses (T = 2 to 5 s), use OB35 at 100 ms. The configured cycle time must exceed the worst-case execution time of the OB body by at least 25% to avoid OB80 time errors.

Does this conflict affect the S7-1500 as well?

Yes. The architectural cause is identical: high-priority OBs preempt OB1 and starve the Modbus RTU library. On the S7-1500 the cyclic OBs are OB30 to OB38, with priorities 7 to 17. The same fix applies — move MB_SLAVE to OB1, keep PID_Compact in the cyclic OB. The Modbus RTU library on the S7-1500 uses the same Modbus_Comm_Load and Modbus_Slave instructions under the names MB_COMM_LOAD and MB_SLAVE.

What is the maximum number of PID_Compact instances I can run in a single S7-1214C cyclic interrupt OB?

On an S7-1214C DC/DC/DC the cyclic OB budget is roughly 2 ms at 100 ms cycle. Each PID_Compact instance consumes 0.15 to 0.30 ms depending on firmware. In practice, 3 to 5 PID_Compact instances fit in a 100 ms OB35 on the S7-1214C before OB1 starts to starve. The S7-1215C doubles that headroom.

Back to blog