Problem Statement
When a Siemens SIMATIC S7-1500 CPU configured as a PROFINET I-Device is forced into STOP mode — by an operator, a programming device, an error, or a firmware restart — the higher-level IO Controller must detect the loss of valid process data. Engineers monitoring the controller's error OBs (OB82, OB83, OB86) frequently see no call even though the diagnostic buffer records a station failure or rack fault. The PROFINET documentation bundled with STEP 7 V13+ (TIA Portal) states that OB 86 fires for a station coming or going, but in practice the I-Device-to-STOP transition behaves differently from a pulled cable or a powered-down PROFINET slave. The link stays up, the Application Relationship (AR) remains active, and the failure surfaces only at the application layer. This article consolidates the exact OB behavior, identifies why OB 86 may not appear, and presents four engineering-grade detection methods that work on S7-1500 firmware V2.5 through V20. The reference documentation is the Siemens function manual PROFINET with STEP 7 V13 SP1 / V14 and the application note I-Device Function in Standard PN Communication.
PROFINET I-Device STOP Semantics
An I-Device is a PROFINET IO Device that is itself a PROFINET controller of a lower-level IO system, exchanging a defined set of process data with a higher-level IO Controller through configured transfer areas. Each transfer area is a contiguous block of bytes with a defined start address on both sides. The IO Controller owns the AR, schedules the cyclic data exchange, and consumes/provides the data. When the I-Device CPU transitions from RUN to STOP, the PROFINET stack on the I-Device continues to send frames to the IO Controller, but the application data is held at the last valid value or zero, depending on the "Behavior in STOP" property configured on the transfer area. From the IO Controller's perspective, the I-Device remains physically present on the network — the link is up, the device is exchanging watchdog and parameter frames, but the user data producer has stopped servicing the output area and is no longer updating the input area.
This distinction is critical. PROFINET differentiates three failure classes at the IO Controller:
- Station failure (cable pull, power loss): OB 86 fires in the IO Controller with EVT_CLASS = W#16##3931 (station failure incoming) and W#16##3961 (station return). The diagnostic buffer records a rack fault.
- Diagnostic interrupt (module-level error): OB 82 fires for each diagnostic event from a slot. The I-Device CPU itself may publish a "CPU in STOP" diagnostic record from its PROFINET interface, depending on firmware.
- I/O access error (peripheral fault during data access): OB 122 fires when user code reads or writes a transfer area while the I-Device is unreachable or in STOP and the slot's data validity flag is FALSE.
For an I-Device that goes into STOP while the PROFINET link remains active, the IO Controller's PROFINET stack does not always raise a station failure. Instead, the controller marks the slots as "data invalid" (provider stopped) and surfaces the condition only when user code attempts an I/O access. Engineers expecting OB 86 to fire for "any I-Device problem" are surprised when the IO Controller happily continues to read the last valid value from the PII.
OB Firing Matrix for I-Device STOP
| OB | Name | Fires on I-Device STOP? | Trigger Condition | Engineering Notes |
|---|---|---|---|---|
| OB 82 | Diagnostic Interrupt | Sometimes (firmware-dependent) | Module-level diagnostic change. The I-Device CPU publishes a "CPU in STOP" diagnostic record from its own PROFINET interface. | Not reliable as a sole detection mechanism on S7-1500. S7-300/400 behavior differs. |
| OB 83 | Insert/Remove Interrupt | No | Triggered by physical module insert/remove events on the local rack or on a remote station. An I-Device going to STOP does not generate a plug/pull event. | Do not rely on OB 83. Load it only to prevent CPU STOP on the IO Controller. |
| OB 85 | Program Execution Error | Sometimes | Fires on update of the process image when a slot is faulted and the corresponding OB is not loaded, or when an I/O access error occurs during PII update. | Often appears as a background to OB 122 in I/O access scenarios. |
| OB 86 | Rack / Station Failure | Variable | Fires for station failure (W#16##3931) and station return (W#16##3961). The I-Device STOP transition may or may not be classified as a station failure depending on firmware and configuration. | Load OB 86 even if you cannot guarantee it fires — it remains the primary indicator of physical-level PROFINET failures. |
| OB 122 | I/O Access Error | Yes (when accessing transfer area) | Fires when user code performs a direct peripheral read/write (PEW / PAW) on a transfer-area slot whose data is invalid because the I-Device is in STOP. | Reliable detection method, but requires peripheral access — not the process image. Optional on S7-1500. |
Why OB 122 Does Not Fire on Optimized Block Access
The S7-1500 default data block model uses "optimized" access, where the compiler hides physical memory and the symbolic tag is resolved by the runtime system without a peripheral read. When the user code reads a transfer area symbolically (e.g., iDevice.InputWord0), the CPU copies the value from the input process image (PII) at the start of the cycle. If the I-Device is in STOP and the PII contains the last valid value, the read succeeds and OB 122 does not fire. The condition is not surfaced until either:
- User code calls
UPDAT_PIorUPDAT_POexplicitly, which returns an error code in RET_VAL, or - User code performs a direct peripheral access using the
PEW/PAW/PED/PADsyntax on the I-Device slot's I/O address.
Optimized blocks do not prevent peripheral addressing — the misconception is that "optimized" and "symbolic peripheral" are mutually exclusive. Configure the I-Device's transfer area with the "Peripheral access" attribute visible (default in TIA Portal V16+), and use the peripheral address in the access expression. The block can remain optimized. The key is the access path, not the block attribute.
Prerequisites for Reliable Detection
Before implementing any detection method, confirm the following configuration items in TIA Portal:
- IO Controller project compiled and downloaded. The device configuration must include the I-Device with its transfer areas and slot assignment.
- Transfer area properties set correctly. In Devices & Networks > I-Device > Transfer areas, the "Update of process image" must be assigned to a process image partition (PIP) or to OB 1, depending on the chosen method.
-
Process image partition assigned to a cyclic OB. If you intend to call
UPDAT_PIfor a specific transfer area, the PIP must be assigned to the calling OB (e.g., OB 35). - All error OBs loaded. OB 82, OB 83, OB 85, OB 86, and OB 122 must each have a body in the IO Controller project, even if the body is empty.
- I-Device CPU online and reachable. Verify the AR is established by inspecting the I-Device's online diagnostics > PROFINET diagnostics > Connection.
Detection Method 1: Peripheral Access to Force OB 122
The most direct way to guarantee OB 122 fires on I-Device STOP is to read the transfer area with a peripheral instruction. This forces the runtime to attempt a read from the I/O subsystem, which fails when the provider is in STOP and the data-validity flag is FALSE.
Structured Text (SCL) Example
// Force a peripheral read on the I-Device transfer area.
// If the I-Device is in STOP, the data is invalid and OB 122 fires.
#rawInputWord := "I-Device_InputArea".%IW0;
The .%IW0 syntax is a fully qualified access (FQA) in TIA Portal that compiles to a PEW read at runtime, regardless of whether the enclosing block is optimized. In the SCL editor, type the I/O variable name followed by .%IW0 for a 16-bit peripheral input read. For 32-bit, use .%ID0; for 8-bit, use .%IB0. For outputs, use .%QW0 / .%QD0 / .%QB0.
Inside OB 122, set a flag indicating the I-Device is unreachable. OB 122 provides the following start information in its temporary local data:
| Local Variable | Data Type | Meaning |
|---|---|---|
| OB122_EV_CLASS | BYTE | Event class (W#16#39 = I/O access error) |
| OB122_SW_FLT | BYTE | Fault code (W#16#42 = area length error, W#16#43 = area error, W#16#44 = area missing) |
| OB122_PRIORITY | BYTE | Priority class of the OB that triggered the error |
| OB122_OB_NUMBER | BYTE | OB number (122) |
| OB122_BLK_TYPE | BYTE | Block type that caused the error (FB, FC, OB, DB) |
| OB122_MEM_AREA | BYTE | Memory area (1 = I-input, 2 = Q-output) |
| OB122_MEM_ADDR | WORD | Relative address of the failed access within the I/O area |
// OB 122 - I/O Access Error
// Latch a user flag and capture the address that failed.
"iDevice_FaultLatched" := TRUE;
"iDevice_LastFaultTime" := RD_SYS_T;
IF OB122_MEM_AREA = 1 THEN
"iDevice_LastFaultIsInput" := TRUE;
ELSE
"iDevice_LastFaultIsInput" := FALSE;
END_IF;
"iDevice_LastFaultAddress" := OB122_MEM_ADDR;
Performance Consideration
Reading the transfer area every cycle in the main OB 1 may add a few microseconds per access on an S7-1516 and can mask the failure window if the I-Device briefly toggles in and out of STOP. For a 1 ms cyclic task, place the peripheral access in a slower watchdog OB (e.g., OB 35 at 100 ms) and compare against the previous value to detect a stuck or zeroed input. The PERIPHERAL_READ instruction can be wrapped in a conditional execute on a cycle counter to reduce the call rate:
IF ("watchdog_cycleCounter" MOD 10) = 0 THEN
"watchdog_rawInput" := "I-Device_InputArea".%IW0;
END_IF;
Detection Method 2: UPDAT_PI / UPDAT_PO with RET_VAL
The instructions UPDAT_PI (update process image of inputs) and UPDAT_PO (update process image of outputs) accept a mode parameter that targets a specific I/O region. They return a RET_VAL (WORD) of W#16#0000 on success or one of the standard PROFINET error codes on failure. The error codes 80A0, 80A1, 80B0, and 80B1 are the strong indicators of an I-Device-in-STOP condition.
| RET_VAL (W#16#) | Meaning | Likely Cause for I-Device STOP |
|---|---|---|
| 0000 | No error | — |
| 8090 | Address not configured or wrong length | I-Device transfer area deleted from project |
| 8092 | Specified I/O area not available in process image | I-Device slot dropped or partition not assigned |
| 8093 | I/O data fault for the specified area | Provider in STOP, link lost, or data invalid |
| 80A0 | Negative acknowledgment when reading from the I/O | Provider in STOP, AR aborted |
| 80A1 | Negative acknowledgment when writing to the I/O | Provider in STOP, AR aborted |
| 80B0 | PI/PO cannot be updated: module not present | I-Device offline |
| 80B1 | PI/PO cannot be updated: module not ready (data invalid) | Provider in STOP, diagnostic pending |
Call these instructions in a slow cyclic OB (e.g., OB 35) to avoid burdening the main cycle. The high byte of RET_VAL is non-zero for any error. Save the LADDR of the failing area in a marker so an operator can identify which I-Device has stopped.
Ladder Logic Example (FBD equivalent shown)
NETWORK 1: Update I-Device input process image, evaluate RET_VAL
CALL "UPDAT_PI"
LADDR := 100 // Logical I/O start address of I-Device transfer area
RET_VAL := "iDev_UpdateRetVal"
NOP 0
NETWORK 2: Evaluate error
L "iDev_UpdateRetVal"
SRW 8 // Shift right by 8 (high byte to low byte)
L 0
<>I // If high byte <> 0, error present
= "iDevice_FaultLatched"
NETWORK 3: Capture specific error code for HMI display
L "iDev_UpdateRetVal"
T "iDevice_LastErrorCode" // Word for HMI tag
Detection Method 3: DeviceStates Instruction
The DeviceStates instruction (available in S7-1500 firmware V2.0+) returns the operational state of a configured PROFINET device. Unlike the methods above, it does not require a peripheral access and works even with optimized symbolic reads. The instruction is part of the standard PLC program library and appears in the "PROFINET IO" folder in the TIA Portal instructions catalog.
// DeviceStates call - MODE 0 returns state of all configured IO devices
#iStatesRet := "DeviceStates_0"(
MODE := 0,
LADDR := 0,
RESULT := "iDev_StateArray"
);
When the I-Device transitions to STOP, the device remains in the configured list and is reported as TRUE in some firmware versions, or FALSE in others. Cross-reference with a heartbeat to disambiguate. For per-device state, use MODE 1 (LADDR = logical address of the I-Device).
| MODE | Behavior | Use Case |
|---|---|---|
| 0 | Returns state of all IO devices | Bulk health check on IO Controller startup or watchdog |
| 1 | Returns state of a single device at LADDR | Targeted I-Device status check |
| 2 | Returns state of all IO devices in a station group | Per-rack / per-IO system health |
Note that DeviceStates reports the PROFINET AR (Application Relationship) state, not the application-level provider status. An I-Device with an active AR but a stopped CPU may be reported as OK by PROFINET and as stopped by your heartbeat. Use DeviceStates as a supplement, not a primary detector.
Detection Method 4: Heartbeat / Watchdog Bit
The most portable and platform-independent method is a heartbeat bit toggled by the I-Device's application code in a fast cyclic OB (e.g., OB 30 at 10 ms with a 50% duty cycle so the master sees a transition at least every 100 ms). The IO Controller monitors the bit and latches a fault if it does not see a transition within a defined window.
I-Device Side (SCL, cyclic in OB 30)
IF "heartbeat_toggle" THEN
"iDevice_Heartbeat" := TRUE;
"heartbeat_toggle" := FALSE;
ELSE
"iDevice_Heartbeat" := FALSE;
"heartbeat_toggle" := TRUE;
END_IF;
IO Controller Side (SCL, cyclic in OB 35 at 100 ms)
IF "iDevice_Heartbeat" = "heartbeat_lastValue" THEN
"heartbeat_stuckCounter" := "heartbeat_stuckCounter" + 1;
ELSE
"heartbeat_stuckCounter" := 0;
"heartbeat_lastValue" := "iDevice_Heartbeat";
END_IF;
IF "heartbeat_stuckCounter" >= 3 THEN
"iDevice_FaultLatched" := TRUE; // Three consecutive 100 ms cycles with no toggle
"iDevice_FaultTimestamp" := RD_SYS_T;
END_IF;
This method is preferred for the following reasons:
- It detects both the I-Device STOP and the I-Device CPU hang (no OB 30 execution).
- It is unaffected by PROFINET diagnostic quirks or OB firing behavior.
- It works identically across S7-300, S7-400, S7-1200, S7-1500, and third-party controllers.
- The time-to-detect is bounded by the toggle period × 3, which is a tunable engineering parameter.
- It survives firmware updates that change the OB firing semantics.
Timing Diagram: Heartbeat Detection
Implementation Comparison
| Method | Detects STOP? | Detects hang? | Detects link loss? | Pollution-free? | Implementation Cost |
|---|---|---|---|---|---|
| OB 82 / 86 monitoring | Variable | No | Yes | Yes | Low (load OBs, set flag) |
| OB 122 via peripheral access | Yes | No | Yes | No (extra access) | Medium (must manage PEW/PAW) |
| UPDAT_PI / UPDAT_PO | Yes | No | Yes | No (cyclic update) | Low (single call per cycle) |
| DeviceStates | Firmware-dependent | No | Yes | Yes | Low |
| Heartbeat bit | Yes | Yes | No (but link loss is detected by other means) | Yes | Low (1 bit + 1 toggle OB) |
Process Image Partition (PIP) Configuration
For UPDAT_PI and peripheral access methods, the I-Device transfer area must be assigned to a PIP that is updated by the calling OB. The default PIP 1 (OB 1) updates every cycle. To use OB 35 (100 ms) as the watchdog OB, create a new PIP in TIA Portal:
- Open Devices & Networks > select the IO Controller CPU.
- Navigate to Properties > Process image partitions.
- Click "Add new partition" and name it (e.g., PIP_iDevice_Watchdog).
- Assign PIP_iDevice_Watchdog to OB 35 with an update rate of 100 ms.
- Open the I-Device > Transfer areas > select the input area > Properties > Process image > assign to PIP_iDevice_Watchdog.
- Compile and download. The transfer area is now updated only when OB 35 runs.
This separation allows the main OB 1 to read the I-Device at full speed for normal operation, while OB 35 handles the slower watchdog checks without impacting cycle time.
Safety and Process Implications
In safety-related applications (PROFIsafe over PROFINET), the I-Device STOP transition is handled by the PROFIsafe layer independently of the standard PROFINET I/O mechanism. The PROFIsafe driver on the IO Controller monitors the safety AR and raises a fail-safe state (substitute values = 0) within the PROFIsafe watchdog time (typically 100 ms to 500 ms). The methods described in this article do not replace PROFIsafe diagnostics; they are supplementary to it.
For non-safety process control, the recommended response to an I-Device fault is:
- Latch the fault flag and timestamp.
- Switch the process to a defined safe state (e.g., hold last value, drive outputs to 0, or transfer to a backup controller).
- Annunciate the fault on the HMI with the I-Device's PROFINET device name, slot number, and the specific error code from RET_VAL or OB 122.
- Require operator acknowledgment before resuming normal control.
Disabling the I-Device Function Programmatically
From TIA Portal V18 onward, the I-Device function can be disabled in the I-Device CPU's user program. This is documented in the TIA Portal V20 I-Device Programming Manual. The disable takes effect on the next STOP→RUN transition of the I-Device CPU. Once disabled, the higher-level IO Controller sees the I-Device as fully removed (station failure), OB 86 fires with W#16##3931, and the controller can respond with a defined fallback rather than the ambiguous "data invalid" state. This is the preferred method for orderly shutdown of an I-Device in a process where the I-Device is taken offline for maintenance.
Verification & Commissioning Steps
- Load all error OBs. In TIA Portal, add OB 82, OB 83, OB 85, OB 86, OB 122 to the IO Controller project. Each must have a body, even if the body is empty. Compile and download.
- Configure the I-Device transfer area with "Peripheral access" visible. In Devices & Networks > I-Device > Transfer areas, ensure the area is enabled for read/write and that the "Update of process image" is set per your detection method.
- Force the I-Device into STOP. Use Online & Diagnostics > Stop CPU on the I-Device. Trigger the transition from the IO Controller side to verify OB behavior.
- Inspect the IO Controller's diagnostic buffer. Look for rack fault (OB 86) and I/O fault (OB 122) entries. The event IDs and timestamps confirm which OBs fired.
- Verify the UPDAT_PI RET_VAL. Monitor the RET_VAL in a watch table. A non-zero high byte (e.g., W#16#80B1) confirms the data-invalid state.
-
Test the heartbeat. With the I-Device in RUN, observe the IO Controller's
heartbeat_stuckCountercycling between 0 and 1. Force the I-Device to STOP and verify the counter increments to 3 within 300 ms. - Test the recovery path. Issue a RUN command to the I-Device. Verify all flags clear and the OB 86 station-return event (W#16##3961) appears in the IO Controller's diagnostic buffer.
- Document the response time. Record the time between the I-Device STOP command and the fault flag latch on the IO Controller. For a 100 ms heartbeat window, expect 300 ms. For OB 122 on peripheral access in OB 1, expect 1–2 ms.
Troubleshooting Matrix
| Symptom | Probable Cause | Fix |
|---|---|---|
| OB 86 fires, OB 122 does not | Station failure detected at PROFINET level (e.g., link loss). User code reads the process image, not the peripheral address. | Switch to peripheral access if you need sub-cycle detection. Otherwise, OB 86 is sufficient. |
| OB 86 does not fire, OB 122 does not fire | I-Device STOP does not propagate as station failure. User code uses optimized symbolic access on the PII. | Implement heartbeat, UPDAT_PI, or peripheral access. None of the standard OBs will fire reliably in this configuration. |
| OB 122 fires continuously after I-Device STOP | Peripheral access in OB 1 reads the failed area every cycle. This is expected but can stall OB 1 if the I-Device stays in STOP and the OB is heavily nested. | Move the peripheral access to a slow OB (OB 35) and gate it on a cycle counter. |
| DeviceStates reports OK while I-Device is in STOP | PROFINET AR is still active. PROFINET does not see a station failure. | Trust the heartbeat, not DeviceStates. Combine with OB 86 for link-loss coverage. |
| Heartbeat never toggles even when I-Device is in RUN | Transfer area is configured as input-only on the IO Controller, or the I-Device's output area is not mapped to the IO Controller's input area. | Verify the transfer area direction. The I-Device's output (provider) must map to the IO Controller's input (consumer). |
| UPDAT_PI returns W#16#8092 | Process image partition for the I-Device is not assigned to OB 35 or the calling OB. | Assign the I/O to a PIP in Devices & Networks > I-Device > Properties > Process image partition. |
| IO Controller also goes to STOP when I-Device stops | An error OB (typically OB 85 or OB 86) is not loaded. The default action is to STOP the CPU. | Load OB 82, OB 83, OB 85, OB 86, and OB 122 with at least an empty body. |
| Diagnostic buffer shows rack fault but no OB fires | The OB is loaded but the event ID does not match the OB type. Verify the OB is OB 86 (rack failure), not OB 82 (diagnostic) or OB 122 (I/O access). | Add all relevant OBs and check each temporary variable on entry. |
Cross-Platform Notes
The OB behavior described here is specific to the S7-1500 / S7-1200 generation running TIA Portal projects. On S7-300/400 with STEP 7 V5.x, the behavior is similar but the symbolic/peripheral distinction is less pronounced because classic STEP 7 uses absolute addressing by default. On ET 200SP CPUs, the same OB matrix applies because the runtime system is shared with the S7-1500 family.
Third-party IO Controllers (e.g., Allen-Bradley ControlLogix with PROFINET scanner, Beckhoff CX with PROFINET device) implement their own diagnostic mechanisms and do not use Siemens OBs. For mixed-vendor architectures, the heartbeat method is the only fully portable detection mechanism and is the recommended engineering practice.
HMI / Web Server Display
For operator visibility, expose the following tags on the HMI or via the CPU's integrated web server:
-
iDevice_FaultLatched(BOOL): Master fault indicator. -
iDevice_LastErrorCode(WORD): Hex code from UPDAT_PI RET_VAL or OB 122 fault code. -
iDevice_LastFaultTimestamp(DTL): Time of the most recent fault. -
heartbeat_stuckCounter(INT): Current stuck count for diagnostics. -
DeviceStates_Result(ARRAY of BOOL): Per-device health from DeviceStates.
The S7-1500 web server can be configured under CPU Properties > Web server > User-defined pages to display these tags without an external HMI. This is useful for remote diagnostics in cabinet installations.
FAQ
Which OB is called on the IO Controller when a Siemens S7-1500 I-Device is put into STOP?
For an S7-1500, OB 86 (rack/station failure) may fire for a station-loss event but is not guaranteed for an I-Device STOP with the PROFINET link intact. OB 122 (I/O access error) fires reliably only when user code performs a peripheral read/write (PEW/PAW syntax) on the I-Device transfer area. For most applications, a heartbeat bit or a UPDAT_PI/UPDAT_PO call with RET_VAL evaluation is the most reliable detection method.
Why does OB 122 not fire when I read the I-Device input via the process image?
OB 122 is only triggered by direct peripheral I/O access (PEW/PAW). When you read the process image (PII) — which is the default for optimized block access on S7-1500 — the CPU copies the last valid value into the PII during the I-Device's cyclic update. As long as the I-Device remains reachable at the PROFINET level, the PII continues to be updated with the last value the I-Device published, even if the I-Device CPU is in STOP. Force a peripheral access using the .%IW0 fully qualified access syntax in SCL to trigger OB 122.
Can I disable the I-Device function programmatically to avoid STOP propagation?
Yes. In STEP 7 / TIA Portal V18+, the I-Device can be disabled in the I-Device CPU's user program. The disable takes effect on the next STOP→RUN transition of the I-Device CPU. Once disabled, the higher-level IO Controller sees the I-Device as fully removed (station failure), OB 86 fires with W#16#3931, and the controller can respond with a defined fallback. The I-Device function is re-enabled on the next RUN transition automatically, or it can be re-enabled programmatically via the same instruction.
What is the difference between the I-Device STOP and pulling the PROFINET cable?
Cable pull or power loss on the I-Device terminates the PROFINET AR at the link layer, so OB 86 fires with W#16#3931 (station failure) on the IO Controller within one watchdog time (typically 3 ms × 12 = 36 ms at 3 ms WatchDog). I-Device STOP leaves the link intact and the AR active; the IO Controller sees the I-Device as reachable, the data becomes "provider stopped / data invalid," and the failure surfaces only on peripheral access or a UPDAT_PI call. This is why a heartbeat bit is the most reliable indicator of I-Device STOP, while OB 86 is the most reliable indicator of physical loss.
Does OB 122 fire on S7-1500 in the same way as on S7-300/400?
No. On S7-300 and S7-400, OB 122 is mandatory — if it is not loaded, the CPU goes to STOP. On S7-1500 (firmware V1.0+), OB 122 is optional. If the IO Controller CPU does not have OB 122 loaded, the I/O access error is handled internally and the read returns the last valid value or zero. The fault is still logged in the diagnostic buffer. To replicate the S7-300/400 behavior on S7-1500, load OB 122 with a body that handles the error and explicitly latches a user-defined flag.
How fast can the IO Controller detect the I-Device STOP?
Detection latency depends on the method. OB 122 on a peripheral access in OB 1 fires within 1–2 ms of the next cycle after the data becomes invalid. UPDAT_PI in a 10 ms cyclic OB adds 10 ms. DeviceStates in a 100 ms cyclic OB adds 100 ms. A heartbeat toggled at 50 ms in OB 30 with a stuck counter threshold of 3 (300 ms) adds 300 ms. The fastest reliable method is the peripheral-access OB 122 approach; the most robust and portable is the heartbeat method.