Resolving Maximum Cycle Time Exceeded on S7-1500 CPUs

David Krause11 min read
SiemensTIA PortalTroubleshooting
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

1. Problem Overview

The "Maximum program cycle time exceeded" diagnostic event on a Siemens S7-1500 CPU (in this case, a 6ES7516-3AN02-0AB0 CPU 1516-3 PN/DP programmed with TIA Portal V15) is generated when the OB1 cycle plus the runtime of any nested cyclic interrupt, time-of-day, or hardware interrupt OBs exceeds the configured maximum cycle monitoring time. The diagnostic buffer entry reads:

Diagnostic buffer excerpt:
- Event: Temporary CPU error - Maximum program cycle time exceeded
- Parameter value: 150 milliseconds (configured WatchDog)
- Response: Time error, OB80 start requested
- Help text: The current cycle's runtime has exceeded the maximum cycle monitoring time. Possible causes: an endless loop has been programmed, or the runtime of the cyclic program has been extended due to nested alarm OBs.

If OB80 is loaded in the project, the CPU starts it as a recovery routine and remains in RUN. If OB80 is missing, the CPU transitions to STOP with SF LED active. The supplied user program contained OB1, OB30, OB80, OB82, OB86, OB100, OB121, and OB122 - OB80 was present, but the cause of the time error still needed to be isolated.

2. CPU 1516-3 PN/DP Relevant Specifications

The cycle-time behavior of the affected CPU constrains the diagnostic strategy:

Parameter CPU 1516-3 PN/DP (6ES7516-3AN02-0AB0)
Bit / data word / retentive memory 500 KB / 5 MB / 4 MB
Bit-instruction execution time 10 ns
Word-instruction execution time 12 ns
Fixed-point / floating-point arithmetic 16 ns / 64 ns
Min. OB1 cycle time (default) 1 ms
Default max. cycle monitoring time 150 ms
Min. cyclic interrupt OB (OB30) period 500 µs
Number of OBs (total) 100+ (cyclic, interrupt, error)
PROFINET interfaces 2 (X1 PN/IE; X2 PN), 1 PROFIBUS DP
Number of PROFINET IO devices 256

Even though the CPU is fast, a 150 ms watchdog is conservative for safety-relevant automation. PROFINET IO data exchange with six S7-1200 slaves (PUT/GET, I-device, or PN controller-DP device coupling) can absorb 10-30 ms per scan depending on watchdog and update times configured for each slave.

3. Cycle Time and Maximum Cycle Monitoring Time

The S7-1500 operating system measures the OB1 scan time continuously. Per the official Siemens functional description (Cycle time and maximum cycle time - S7-1500):

  • Cycle time = OB1 execution time + sum of all interrupted higher-priority OB processing (OB30, OB40-47, OB82, OB121, OB122) + system overhead.
  • Cycle monitoring time (WatchDog) is the upper limit. Default = 150 ms. Configurable in Device Properties > PLC > Cycle time.
  • If the cycle time exceeds the watchdog, OB80 is requested. If OB80 is present and finishes within its own watchdog, the CPU remains in RUN and the cycle-time counter resets.
  • If OB80 is missing, or if OB80 itself exceeds its watchdog, the CPU transitions to STOP with diagnostic buffer entry "STOP due to time error".

The relationship is:

T_cycle_measured = T_OB1 + Σ T_interrupt_OB_i
T_cycle_measured < T_watchdog   ⇒ normal operation
T_cycle_measured ≥ T_watchdog   ⇒ OB80 triggered

4. Interpreting the Diagnostic Buffer

The diagnostic buffer is the primary fault-isolation tool. Open it from Online > Diagnostics > Diagnostic buffer after going online to the CPU. For each entry, double-click the row to follow paging links:

Diagnostic buffer field What it tells you
Event ID (hex) 0x3501 = Maximum cycle time exceeded
0x3502 = OB80 start requested
0x39xx = OB80 execution
Parameter value Configured watchdog in ms (here 150)
OB being executed Identifies which OB triggered the error (OB1 or interrupt)
Block stack Stack of FBs/FCs currently executing (path to offender)
Help link Causes and remediation steps from Siemens KB

Tip: When the diagnostic buffer shows "OB1 in execution state," the block stack at the moment of the error reveals exactly which FC/FB instance was active. This bypasses hours of manual disable-and-test.

5. Time-Error OB (OB80) Behavior

OB80 is the time-error interrupt OB. Its temporary variables reveal what the firmware knew at the moment of the fault:

OB80 input (Temp) Type Meaning
LADDR HW_IO_ANY Hardware identifier (0 if no HW trigger)
OB_PRIORITY BYTE Priority of the OB that was interrupted
OB_NUMBER BYTE OB number that was running (1 = OB1)
OB_RESERVED_1 BYTE Reserved (0)
OB_RESERVED_2 BYTE Reserved (0)
FAULT_TIME DATE_AND_TIME Timestamp of the error
CUR_CYC DINT Currently configured cycle monitoring time (ms)
CUR_T DINT Currently elapsed cycle time (ms) at the moment of error
LAST_CYC DINT Cycle time of the previous scan (ms)
LAST_T DINT Previous elapsed cycle time (ms)

Implementing an OB80 with logging of CUR_T, CUR_CYC, and the block stack gives an immediate fingerprint of the runaway path. In the project under diagnosis, OB80 was loaded but contained no error-recording logic, so it absorbed the trap and re-entered OB1 - hiding the cause.

6. Root Cause Analysis: Nested Loops in SCL

Disabling every FC/FB in OB1 and re-enabling them one at a time revealed that three deeply nested FCs containing FOR loops pushed the cycle time past 150 ms:

(* ----------- FC1 ----------- *)
FOR i := 1 TO 12 DO
    FC2();         // 12 calls
END_FOR;

(* ----------- FC2 ----------- *)
FOR j := 1 TO 72 DO
    FC3();         // 72 calls per FC1 iteration
END_FOR;

(* ----------- FC3 ----------- *)
FOR k := 1 TO 72 DO
    DoWork();      // 72 calls per FC2 iteration
END_FOR;

The total number of DoWork() invocations per OB1 scan is:

N = 12 × 72 × 72 = 62 208 calls per cycle

If DoWork() averages 5 µs of bit/word execution, the inner loop alone costs roughly 5 µs × 62 208 = ~311 ms - more than 2× the watchdog. Any slight overhead from FC boundary calls pushes this further. The "Maximum program cycle time exceeded" event is therefore deterministic, not stochastic.

Compounding factors that increased cycle time in this project:

  • OB30 cyclic interrupt at 5 ms period ran in parallel with OB1, pre-empting it.
  • PROFINET IO update with six S7-1200 slaves at 1 ms update time absorbed 3-6 ms per OB1 cycle.
  • RE_TRIGR was not used - the watchdog never reset.

7. Step-by-Step Diagnostic Procedure

Apply this sequence when the same diagnostic event appears in a future project:

  1. Capture the diagnostic buffer online. Note event IDs, timestamps, and the block stack at the moment of the time error.
  2. Inspect the time-error OB (OB80). Add code to copy CUR_T, LAST_T, and the current block number into a global data block so the values survive the trap and can be read after OB1 resumes.
  3. Use the diagnostic buffer "Open in editor" link. In TIA Portal V15 the link is occasionally broken; fall back on the block stack text in the buffer.
  4. Disable the cyclic interrupt OBs (OB30) and the PROFINET IO update temporarily by calling Device Properties > PLC > Cycle > Disable cyclic interrupt OBs on the online CPU to see whether OB1 alone overruns.
  5. Use the Block Stack from the S7-1500 web server or HMI tags (e.g., read OB1.STACK via RD_SINFO from a connected HMI).
  6. Isolate by binary-chop. Disable half of the FC/FB calls in OB1, observe cycle time, then narrow the search.
  7. Inspect each suspect FC for nested loops. A nested FOR structure where the inner block also iterates is the most common cause.
  8. Add a temporary tag named OB1_StartTime using RUNTIME (SCL: tStart := RUNTIME;) at the first network of OB1 and the second at the last network. Subtract to get the current OB1 scan time in microseconds.
  9. Add RE_TRIGR strategically only after confirming there is no infinite loop - it will mask the symptom, not cure it.

8. Solution 1 - Flatten or Refactor the Nested Loops

The canonical fix is to remove the nested FC calls from inside loops. Convert the triple nested loop into a single loop with a flat index, or replace the FCs with re-entrant logic that operates on array slices:

(* Refactored: a single FOR that walks a precomputed index set *)
FOR idx := 1 TO 62208 DO
    DoWork(arrA[idx], arrB[idx], arrC[idx]);
END_FOR;

Or, when the inner logic truly needs 72 × 72 work units, schedule only the work that fits within one OB1 scan and persist progress in an instance DB:

(* Iterative scheduler inside FC1 *)
iRunState := iRunState + 1;
IF iRunState > 12 THEN
    iRunState := 0;
    bComplete := TRUE;
END_IF;
FOR j := 1 TO 72 DO
    FOR k := 1 TO 72 DO
        DoWork(iRunState, j, k);
    END_FOR;
END_FOR;

This executes one "row" of the outer iteration per cycle, capping the cycle time at the inner-loop workload only.

9. Solution 2 - RE_TRIGR Instruction

The RE_TRIGR instruction resets the cycle-time watchdog to zero so the next scan starts with a fresh budget. It is found in the Extended instructions > Watchdog palette in TIA Portal:

(* Reset watchdog partway through OB1 to gain headroom *)
IF bMidScanReset THEN
    RE_TRIGR();              // SCL form
END_IF;

Rules for safe use:

  • Never place RE_TRIGR inside an unbounded loop - it will never let the loop complete and the CPU will hang in OB1.
  • Use it only as a tactical workaround after the runaway branch has been confirmed to be finite.
  • Add a counter and compare against a watchdog-fail DB to detect repeated usage - if RE_TRIGR fires every scan the cycle is consistently close to the limit and the project will fail in production.

10. Solution 3 - Raise the Maximum Cycle Monitoring Time

Navigate to Device Properties > PLC > Cycle time on the S7-1500 CPU and adjust:

Property Default Recommended range for this project
Cycle monitoring time (ms) 150 200 - 500 ms (after code fix)
Min. cycle time (ms) 1 1 - 10 ms

Raising the value alone is acceptable as a stop-gap - the official Siemens KB explicitly allows it - but only after the offending code has been fixed. Doubling the watchdog to 300 ms without fixing the nested loop merely delays the fault and may obscure other intermittent issues.

11. Solution 4 - Split OB1 Across Multiple Cyclic OBs

The S7-1500 supports multiple cyclic OBs (OB1, OB123-OB32767). Group the program into priority classes:

  • OB1 (priority 1): Fast I/O update, alarms.
  • OB123 (priority 2): PROFINET IO data exchange.
  • OB124 (priority 3): Bulk computation, batch loops.

Each OB has its own watchdog setting, isolating the failure surface. The diagnostic buffer then reports which cyclic OB tripped, accelerating isolation.

12. Verification Procedure

After applying a fix, verify the result with this checklist:

  1. Force a full scan with the Online > Operating mode > Cold restart or power cycle to ensure the diagnostic buffer is cleared.
  2. Run for at least 60 minutes under representative PROFINET load (all six S7-1200 slaves cycling). Confirm no time-error events.
  3. Read the S7-1500 web server > Diagnostics > Cycle time. Confirm Min/Avg/Max cycle times stay below 70 % of the configured watchdog (≤105 ms in the original 150 ms setting).
  4. Force worst-case conditions: disable one PROFINET slave, increase OB30 frequency to 1 ms, run again for 10 minutes. The watchdog must not be approached.
  5. Capture RUNTIME and RE_TRIGR count in a dedicated DB for permanent monitoring via HMI or OPC UA.
  6. Document the new watchdog setting, loop restructuring, and OB partitioning in the project release notes.

13. Preventive Best Practices

  • Avoid calling FC/FBs inside FOR loops. Move the loop into the called block or iterate over pre-computed arrays.
  • Keep OB1 lean. OB1 should orchestrate - heavy data manipulation belongs in cyclic interrupt OBs or background tasks (OB90).
  • Always load OB80 in every S7-1500 project. Add a 5-line SCL snippet that logs the offending OB number and cycle time into a global DB. This is the cheapest possible insurance.
  • Set the cycle monitoring time relative to the expected workload. For projects with six PROFINET slaves and OB30 running, 200-300 ms is a defensible starting point.
  • Use RUNTIME as the first and last network of OB1 during commissioning to record the true scan time and surface creeping cycle-time growth before it trips the watchdog.
  • Avoid RE_TRIGR unless absolutely required. Treat each call as a code-review red flag.
  • Refactor cross-block nested loops into single flat loops with explicit indexing; profile the new variant in PLCSIM before commissioning.

14. FAQ

What is the default maximum cycle monitoring time on a Siemens S7-1500 CPU?

The default is 150 ms. It is configurable in Device Properties > PLC > Cycle time. The CPU triggers OB80 once the measured OB1 plus interrupt OB execution time exceeds this value, and the diagnostic buffer records event 0x3501 with the configured watchdog as parameter value.

How does RE_TRIGR affect the cycle watchdog on an S7-1500?

RE_TRIGR resets the cycle-time watchdog to zero so the current scan starts a fresh budget. Place it only at well-defined points in OB1 after confirming the code between RE_TRIGRs is bounded. Inside an unbounded loop it masks the fault and lets the CPU hang in OB1.

Why does my S7-1500 go to STOP with OB80 loaded?

If OB80 itself exceeds the cycle monitoring time (e.g., it contains another runaway loop), the CPU transitions to STOP. OB80 must be lean - typically 5-20 lines that log state and return.

Can nested FOR loops in SCL cause Maximum cycle time exceeded?

Yes. A loop with N outer × M inner iterations calls the inner block N·M times. With three levels at 12 × 72 × 72 = 62 208 calls, a routine that takes even 5 µs per call overruns the 150 ms watchdog. Restructure with flat indexing or split across multiple OB1 scans using a scheduler DB.

Which OB can I read to find which OB caused the time error?

OB80 temporary variables supply OB_NUMBER, OB_PRIORITY, CUR_T, and LAST_T. Log these into a global data block on the first network of OB80 so they survive OB1 restart and can be inspected via HMI or the diagnostic buffer.

Back to blog