Overview: Why OB Execution Time Matters
On a SIMATIC S7-1500 CPU such as the 1516-3 PN/DP, the user program is not a single monolithic scan; it is partitioned into Organization Blocks (OBs) that the operating system schedules by priority. Background OBs (OB 90), the main cyclic OB (OB 1), cyclic interrupt OBs (OB 30 to OB 38), time-of-day OBs (OB 10 to OB 17), delay OBs (OB 20 to OB 23), hardware interrupt OBs (OB 40 to OB 47), synchronization OBs (OB 61 to OB 64), and event-driven OBs (OB 80, OB 82, OB 121, OB 122) all compete for the same CPU resource. Each OB has its own start time, its own execution duration, and its own contribution to total CPU load.
Knowing the per-OB execution time is essential for capacity planning, for detecting scan-time creep after a functional change, for sizing the OB 1 maximum cycle watchdog, and for determining whether communication, motion, or background tasks are starving the main program. The TIA Portal exposes some of this information through Online & Diagnostics > Cycle Time, but that view aggregates the entire scan. To isolate the contribution of an individual OB, the engineer needs the RT_INFO instruction and the PREV_CYCLE tag of OB 1.
This reference covers the priority model that drives OB scheduling on the S7-1500, the distinction between the OB 1 cycle and the overall scan, the parameter set of RT_INFO, the role of OB 80 in cycle-time monitoring, and a structured implementation pattern that drops directly into TIA Portal V18, V19, or V20 projects.
OB Architecture and Priority Model in S7-1500
OBs on the S7-1500 are executed exclusively on a priority basis. When multiple OB requests are pending, the operating system always services the OB with the highest priority first. The priority class is fixed by the OB type and cannot be changed by the user; only the OB number identifies the OB.
| OB Type | OB Numbers | Priority Class | Trigger Source |
|---|---|---|---|
| Main (cyclic) | OB 1 | 1 | Free cycle, restart |
| Time-of-day | OB 10 to OB 17 | 2 | Configurable time/date |
| Delay | OB 20 to OB 23 | 3 to 6 | Delay event after start |
| Cyclic interrupt | OB 30 to OB 38 | 7 to 15 | Fixed interval (e.g. 1 ms, 10 ms) |
| Hardware interrupt | OB 40 to OB 47 | 16 to 23 | Process event on channel |
| Synchronous (motion) | OB 61 to OB 64 | 25 | PROFIdrive/PROFINET cycle |
| Time error | OB 80 | 26 | Scan-time overrun, missing OB |
| Diagnostic interrupt | OB 82 | 26 | Module diagnostic event |
| Pull/plug | OB 83 | 26 | Module slot change |
| Background | OB 90 | 29 | Idle time of OB 1 |
| Startup | OB 100 / 101 / 102 | 27 | Cold/warm restart / re-init |
| Programming error | OB 121 | Priority of causing OB | Runtime fault in user code |
| I/O access error | OB 122 | Priority of causing OB | Failed direct I/O access |
Refer to the official description of Events and OBs (S7-1500) in the functional description manual for the definitive priority assignment per firmware generation. The single most important operational consequence of this model is that a cyclic interrupt OB running at 1 ms with priority 7 will preempt OB 1 on every cycle, so measuring OB 1 alone will not show the true workload.
Cycle Time vs. OB Execution Time: Clarifying the Distinction
The value reported by TIA Portal at Online & Diagnostics > Cycle Time is the total scan time, not the duration of OB 1. Total scan time includes:
- OB 1 user code execution
- Preemption time from cyclic interrupt OBs (OB 30 to OB 38)
- Preemption time from hardware interrupt OBs (OB 40 to OB 47)
- Preemption time from synchronous OBs (OB 61 to OB 64) when motion control is configured
- Communication processing (open communication, S7 communication, OPC UA, FETCH/WRITE, HMI tag service)
- Operating system housekeeping (task switching, I/O image update, diagnostics)
For a CPU 1516-3 PN/DP with three cyclic interrupt OBs and one synchronous OB, the displayed cycle time is the wall-clock period between two successive starts of OB 1, expanded by every higher-priority event that interrupted OB 1 during the scan. This is the value that OB 80 monitors against the configured maximum cycle time.
To get the execution time of a single OB, two data sources are available:
- OB 1 PREV_CYCLE tag (LREAL, milliseconds): previous OB 1 execution time, only valid for OB 1.
- RT_INFO instruction: per-OB runtime, call count, and CPU/communication load for any OB.
OB 1 PREV_CYCLE: Reading the Main Cycle Time
OB 1 carries two system-supplied LREAL tags that are visible in the block interface:
-
PREV_CYCLE(LREAL, in ms): duration of the previous OB 1 pass. -
CURR_CYCLEis not exposed on OB 1 directly; the cycle time is sampled at the next entry.
A typical capture pattern uses an FB with multi-instance DBs that records the value into a ring buffer on each pass:
// FB "CycleRecorder" interface
VAR
Samples : ARRAY[1..1000] OF LREAL; // ring buffer
Index : INT; // 1..1000
END_VAR
// On first call
IF Index = 0 THEN Index := 1; END_IF;
Samples[Index] := "Main".PREV_CYCLE; // OB 1 tag
Index := Index MOD 1000 + 1;
PREV_CYCLE only reflects the OB 1 segment. If a cyclic interrupt OB fires during the scan, that time is excluded from PREV_CYCLE but included in the total cycle time, so a comparison of PREV_CYCLE against the TIA Portal cycle-time display is a quick way to see how much OB 1 is being preempted.
RT_INFO Instruction: Granular Per-OB Measurement
The RT_INFO instruction is the primary tool for per-OB measurement on S7-1500. It is available in TIA Portal under Instructions > Extended instructions > Diagnostics. The block interface is:
| Parameter | Direction | Type | Meaning |
|---|---|---|---|
| OB | IN | INT | OB number to query |
| MODE | IN | BYTE | Selects the data returned |
| LADDR | IN | WORD | Sub-address (not used for mode 1 / 10 / 11 / 20 / 21) |
| RET_VAL | OUT | LREAL | Returned value |
Mode selection matrix:
| MODE | Returned Value (RET_VAL) | Unit | Use |
|---|---|---|---|
| 1 | Last execution time of OB identified by OB parameter | ms | Per-OB runtime |
| 2 | Last execution time of OB identified by LADDR parameter | ms | Per-OB runtime via instance DB address |
| 3 | Number of calls of OB identified by LADDR since last restart | count | Invocation count |
| 10 | Current CPU load (user program) | % | Live CPU load |
| 11 | Maximum CPU load since last restart | % | Peak CPU load |
| 20 | Current communication load | % | Live comm load |
| 21 | Maximum communication load since last restart | % | Peak comm load |
Calling RT_INFO for an OB that is not loaded on the CPU returns 0.0 without raising an error. Calling RT_INFO for an OB number that does not exist returns 0.0 and sets the ENO enable output to 0 with the diagnostic status 16#0000 in ENO-driven error evaluation.
Worked Example: Five Background OBs and Three Cyclic Interrupts
The user's CPU 1516-3 PN/DP has five OB 90 instances and three cyclic interrupt OBs (e.g., OB 30 at 10 ms, OB 31 at 20 ms, OB 35 at 100 ms) plus one synchronous OB (OB 61). To capture each runtime, build a single FB called once per OB 1 scan:
// FB "OB_Load_Monitor" body (SCL)
"Runtime".OB := 1;
"Runtime".MODE := 1;
"Runtime".LADDR := 0;
"Runtime".RET_VAL; // value in ms
OB1_ms := "Runtime".RET_VAL;
"Runtime".OB := 30; OB30_ms := "Runtime".RET_VAL;
"Runtime".OB := 31; OB31_ms := "Runtime".RET_VAL;
"Runtime".OB := 35; OB35_ms := "Runtime".RET_VAL;
"Runtime".OB := 61; OB61_ms := "Runtime".RET_VAL;
"Runtime".OB := 90; OB90_ms := "Runtime".RET_VAL;
"CPU".OB := 0; "CPU".MODE := 10; CPU_Load_Act := "CPU".RET_VAL;
"CPU".MODE := 11; CPU_Load_Max := "CPU".RET_VAL;
"Comm".OB := 0; "Comm".MODE := 20; Comm_Load_Act := "Comm".RET_VAL;
"Comm".MODE := 21; Comm_Load_Max := "Comm".RET_VAL;
The actual scan time is then reconstructed from:
// Estimated cycle time (ms)
EstimatedCycleTime := OB1_ms + OB30_ms + OB31_ms + OB35_ms + OB61_ms + OB90_ms;
This reconstruction will be close to, but slightly below, the TIA Portal cycle-time value because the OS housekeeping (I/O image update, task switching, PROFIBUS/PROFINET acyclic services) is not attributed to any user OB.
TIA Portal Online & Diagnostics: Cycle Time Display
The Cycle Time diagnostic panel is reached by selecting the PLC in the project tree, going online, and opening Online & Diagnostics > Cycle Time. The panel reports:
| Field | Meaning |
|---|---|
| Current cycle time | Latest OB 1 period, including all preemptions |
| Minimum cycle time | Lowest observed since last RUN-STOP-RUN transition |
| Maximum cycle time | Highest observed since last RUN-STOP-RUN transition |
| Configured maximum | Watchdog threshold (drives OB 80) |
This view also includes the OB 1 minimum and maximum values, which can be used to bound the OB 1 contribution inside the larger cycle time envelope. The Siemens KB article How do you measure the total cycle time of a program? (entry ID 87668055) covers the methodology on both S7-1200 and S7-1500 and is the canonical reference for the Online & Diagnostics panel.
OB 80 Time Error Interrupt: Detection and Response
The time error interrupt OB (OB 80) executes whenever the scan cycle exceeds the configured maximum cycle time, or when a time error event such as a referenced OB not being loaded occurs. See the official description at Time error interrupt OB.
OB 80 receives a temporary variable OB80_FLT_ID that identifies the event type:
| FLT_ID (hex) | Meaning | Typical Cause |
|---|---|---|
| 16#00xx | Cycle time exceeded | OB 1 over watchdog threshold |
| 16#01xx | OB call not possible | Referenced OB not loaded |
| 16#02xx | Time error during OB processing | Cyclic interrupt too close together |
| 16#05xx | Queue overflow | Event source firing faster than serviced |
| 16#07xx | Timeout | Operating system internal |
When OB 80 is configured, the CPU logs the event and continues; without OB 80, the same condition drives the CPU to STOP. The maximum cycle time is configured in TIA Portal under PLC properties > Cycle time monitoring. The default on the S7-1500 is 150 ms; values below 5 ms are not supported.
A robust OB 80 body should latch the fault, capture RT_INFO mode 11 (max CPU load) at the moment of the error, and either trigger an alarm or shed non-essential loads:
// OB 80 body (SCL)
IF "DLT".OB80_FLT_ID = 16#0001 OR "DLT".OB80_FLT_ID = 16#0002 THEN
// Cycle-time overrun
"HMI_Alarm".CycleTimeError := TRUE;
"HMI_Alarm".FLT_ID := "DLT".OB80_FLT_ID;
"HMI_Alarm".FLT_TIME := "DLT".OB80_TIME_STAMP;
"HMI_Alarm".CPU_Load_Max := "Load_Recorder".RT_INFO("CPU", 11, 0);
END_IF;
CPU Load Calculation and Formulas
The CPU load is defined as the share of the scan period consumed by user-program execution. For the OB 1 main cycle, the instantaneous load is:
CPU_Load_OB1 (%) = (PREV_CYCLE / Scan_Period) * 100
For the total CPU load including all OBs, the relationship between per-OB runtime, period, and load is:
OB_i_Load (%) = (OB_i_Runtime_ms / OB_i_Period_ms) * 100
Total_Load (%) = SUM_i (OB_i_Runtime_ms / OB_i_Period_ms) * 100 + Comm_Load_Act
Worked example with the user's CPU 1516-3 PN/DP:
| OB | Runtime (ms) | Period (ms) | Load (%) |
|---|---|---|---|
| OB 1 (main) | 8.0 | 20 | 40.0 |
| OB 30 (cyclic 1 ms) | 0.4 | 1 | 40.0 |
| OB 31 (cyclic 2 ms) | 0.3 | 2 | 15.0 |
| OB 35 (cyclic 100 ms) | 2.0 | 100 | 2.0 |
| OB 61 (synchronous) | 1.5 | 2 | 75.0 (on motion segment) |
| OB 90 (background) | 0.5 | 200 | 0.25 |
Aggregate load before OS overhead is approximately 172% of the configured segments, which cannot exceed 100% of CPU bandwidth; in practice these intervals do not all overlap every scan, and the OS load (comm + housekeeping) is what RT_INFO mode 10 reports directly. The formula above is useful for the S7-1500 sizing spreadsheet when designing a system before firmware deployment.
Implementation: Structured Code Example
A complete diagnostic FB in SCL for TIA Portal V18+:
FUNCTION_BLOCK "OB_Load_Monitor"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
ScanPeriod_ms : LREAL := 20.0; // configured OB 1 period
Enable : BOOL := TRUE;
END_VAR
VAR_OUTPUT
OB1_Runtime_ms : LREAL;
OB30_Runtime_ms : LREAL;
OB31_Runtime_ms : LREAL;
OB35_Runtime_ms : LREAL;
OB61_Runtime_ms : LREAL;
OB90_Runtime_ms : LREAL;
CPU_Load_Act_pct : LREAL;
CPU_Load_Max_pct : LREAL;
Comm_Load_Act_pct : LREAL;
Comm_Load_Max_pct : LREAL;
EstimatedCycleTime_ms : LREAL;
END_VAR
VAR
RT_OB : RT_INFO; // per-OB
RT_CPU : RT_INFO; // CPU load
RT_Comm : RT_INFO; // comm load
END_VAR
VAR_TEMP
iRet : LREAL;
END_VAR
BEGIN
IF NOT Enable THEN RETURN; END_IF;
// Per-OB runtime
RT_OB(OB := 1, MODE := 1, LADDR := 0, RET_VAL => OB1_Runtime_ms);
RT_OB(OB := 30, MODE := 1, LADDR := 0, RET_VAL => OB30_Runtime_ms);
RT_OB(OB := 31, MODE := 1, LADDR := 0, RET_VAL => OB31_Runtime_ms);
RT_OB(OB := 35, MODE := 1, LADDR := 0, RET_VAL => OB35_Runtime_ms);
RT_OB(OB := 61, MODE := 1, LADDR := 0, RET_VAL => OB61_Runtime_ms);
RT_OB(OB := 90, MODE := 1, LADDR := 0, RET_VAL => OB90_Runtime_ms);
// CPU and communication load
RT_CPU(OB := 0, MODE := 10, LADDR := 0, RET_VAL => CPU_Load_Act_pct);
RT_CPU(OB := 0, MODE := 11, LADDR := 0, RET_VAL => CPU_Load_Max_pct);
RT_Comm(OB := 0, MODE := 20, LADDR := 0, RET_VAL => Comm_Load_Act_pct);
RT_Comm(OB := 0, MODE := 21, LADDR := 0, RET_VAL => Comm_Load_Max_pct);
// Reconstructed cycle time
EstimatedCycleTime_ms := OB1_Runtime_ms + OB30_Runtime_ms
+ OB31_Runtime_ms + OB35_Runtime_ms
+ OB61_Runtime_ms + OB90_Runtime_ms;
END_FUNCTION_BLOCK
Call this FB unconditionally once per OB 1 scan from the main program. For a faster snapshot of the live CPU load, place a second instance inside a 100 ms cyclic interrupt OB so the HMI tag updates without waiting for OB 1 to complete.
Verification and Commissioning Checklist
- Compile and download the project to the CPU 1516-3 PN/DP.
- Go online and open Online & Diagnostics > Cycle Time. Confirm that the displayed cycle time matches the reconstructed value from RT_INFO mode 1 within ±5%. Discrepancy indicates OS overhead (PROFINET acyclic, etc.).
- Force the CPU into a high load by enabling a debug counter or a test loop in OB 1. Confirm that the maximum cycle time in TIA Portal tracks RT_INFO mode 11.
- Temporarily reduce the configured maximum cycle time to a value just above the OB 1 expected runtime and verify that OB 80 fires with
FLT_ID = 16#0001when the overrun occurs. - Check the diagnostic buffer for OB 80 events using Online & Diagnostics > Diagnostics Buffer. Each event should show the FLT_ID and the time stamp.
- Export the runtime tags to the HMI trend view; cycle for at least one hour of normal operation and verify that the OB runtime trends remain stable within ±10%.
- Confirm that the OB 90 background OB only runs when OB 1 has spare time; the OB90_Runtime_ms tag should remain near zero when CPU load exceeds 80%.
Troubleshooting Matrix
| Symptom | Likely Root Cause | Diagnostic Action | Resolution |
|---|---|---|---|
| OB 1 PREV_CYCLE jumps to 5–10 ms but TIA Portal shows 200 ms | Cyclic interrupt or synchronous OB is preempting OB 1 | Read RT_INFO mode 1 for OB 30/31/61 | Spread cyclic interrupt load or raise OB 1 priority |
| CPU goes to STOP with diagnostic buffer entry "Time error" | OB 80 not loaded; max cycle exceeded | Add OB 80, lower max cycle, examine buffer | Add OB 80 and raise max cycle to OB 1 measured peak + 25% |
| RT_INFO mode 10 returns 0% while OB is clearly executing | Mode 10 is sampled at start of OB 1, not within OB | Sample multiple times or use mode 11 | Use mode 11 to get maximum load |
| OB 90 runtime stays at zero even at low load | OB 90 not configured or scan is fully occupied | Check PLC properties > OBs > OB 90 | Add OB 90 and verify it executes in idle slots |
| Communication load (mode 20) exceeds 50% | Too many HMI tags polled, or OPC UA server heavy | Reduce tag count, increase update interval | Tune HMI polling or split communication load |
| OB 35 (100 ms cyclic) misses cycles | Previous OB 35 still running when next trigger fires | Compare mode 3 count vs expected count | Reduce OB 35 runtime or extend period |
| Cycle time creeps after firmware update | New firmware added OS background tasks | Compare OB 1 PREV_CYCLE pre/post update | Allow for new baseline; raise max cycle accordingly |
| RT_INFO RET_VAL = 0 for an OB that is in the program | OB has not yet executed since last restart | Force a RUN-STOP-RUN transition | After restart, allow OB to fire once; then read |
Field Notes and Best Practices
- Always configure OB 80 in production systems. Without it, a single cycle overrun halts the plant.
- Set the maximum cycle time to OB 1 measured peak + 25% to leave headroom for cyclic interrupts and OS overhead.
- Use RT_INFO mode 11 (maximum CPU load) for alarming rather than mode 10, since mode 10 is sampled at the OB 1 start and can miss transient peaks.
- Record the OB runtime trend over a full production shift, not just a single cycle; many scan-time spikes correlate with HMI tag bursts at shift change.
- When migrating from S7-300/400 to S7-1500, note that the S7-1500 RT_INFO returns milliseconds as LREAL; the legacy SFC 78 returned DWORD microseconds. Adjust scaling in any legacy code paths.
- When sizing a new CPU, use the CPU specification table for "Bit execution time" (e.g. 30 ns for CPU 1516) to convert instruction count into expected runtime, then verify with RT_INFO after commissioning.
- Disable RT_INFO polling when not needed; each call adds a small OS service overhead that shows up in OB 1 PREV_CYCLE.
Frequently Asked Questions
What does the "Cycle Time" in TIA Portal Online & Diagnostics show?
The Cycle Time panel reports the full OB 1 period, including OB 1 itself plus any preemption from cyclic interrupt OBs, hardware interrupt OBs, synchronous OBs, communication processing, and OS housekeeping. It is not the OB 1 execution time alone.
How do I measure the execution time of an individual OB on S7-1500?
Use the RT_INFO instruction with MODE = 1 and set the OB parameter to the target OB number. The RET_VAL returns the last execution time of that OB in milliseconds (LREAL). Modes 2 and 3 return the runtime and call count identified by LADDR.
What is the difference between RT_INFO mode 10 and mode 11?
Mode 10 returns the current CPU load (user program percentage) sampled at the moment of the call. Mode 11 returns the maximum CPU load observed since the last RUN-STOP-RUN transition. Use mode 11 for alarms and trending; use mode 10 only for live HMI display.
Why does my CPU go to STOP with a time error when OB 80 is missing?
OB 80 is the time error interrupt OB and executes when the scan cycle exceeds the configured maximum cycle time or when a referenced OB is not loaded. Without OB 80, the CPU cannot handle the error and enters STOP mode. Configure OB 80 and set the maximum cycle time to OB 1 measured peak plus 25%.
Can I read the previous OB 1 cycle time without using RT_INFO?
Yes. OB 1 carries a temporary LREAL tag called PREV_CYCLE in its block interface. Use it directly in the OB 1 static code. Note that PREV_CYCLE only reflects OB 1 itself and excludes preemptions from higher-priority OBs.