Resolving S7-400 OB86 Power-Up Diagnostic Miss in ET200M Systems

David Krause16 min read
S7-400SiemensTroubleshooting
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 Definition

On SIMATIC S7-400 / S7-400H controllers, the diagnostic organization block OB86 (Rack Failure / DP Slave Failure) is invoked only when a rack failure or a distributed I/O station loss is detected as a live transition during RUN. If a PROFIBUS DP slave (for example, an ET200M station with a redundant IM 153-2 link module) is removed while the CPU is de-energized and remains missing at the moment the controller returns to RUN, OB86 is not called at power-up. The user program therefore sees the system as healthy even though physical modules are absent, leaving the diagnostic database silent until the next live event.

This behavior creates a diagnostic gap for any plant whose control cabinet may be powered down for transport, maintenance, or customer-driven shutdown. OB82, OB83, OB85, OB86, and OB87 are all event-driven — they fire on transitions, not on static conditions. Without an explicit status scan during startup, the program cannot distinguish "everything is OK" from "the rack was already missing when we woke up."

Observable symptom signatures:

  • No OB86 call at the OB100 (warm restart) or OB102 (cold restart) boundary
  • No OB82 diagnostic interrupt at startup for faults already present
  • Fault-tracking DB shows "all stations OK" even though a link module or ET200M is physically absent
  • OB86 fires correctly for live events once the CPU is fully RUN
  • Removing and reinserting the link during RUN triggers OB86 as expected
  • Slot-level I/O faults appear in the diagnostic buffer but no station-level alarm is raised
Critical: OB82-OB87 are edge-triggered. They report the occurrence and removal of errors. A fault that exists at the very first scan of the CPU cannot be reported through these OBs because no edge ever occurred from the CPU's perspective.

2. System Architecture Context

The fault pattern described above most commonly appears on S7-400H redundant systems with distributed I/O connected over PROFIBUS DP using redundant IM 153-2 link modules. Typical hardware in scope:

Component Typical Siemens Part Number Role in Diagnostic Chain
SIMATIC S7-417-5H 6ES7 417-5HT06-0AB0 (or later H-CPU) Master, runs OB100 / OB102 / OB86
ET200M station 6ES7 153-2BA10-0XB0 / 6ES7 153-2BA70 (redundant link) DP slave, reports diagnostics upstream
PROFIBUS DP cable 6XV1 830-0EH10 / 6XV1 830-3EH10 Physical link for cyclic I/O exchange
PS 405 / PS 407 6ES7 405-0KA02-0AA0 / 6ES7 407-0KA02-0AA0 Power supply for rack and DP interface
Sync module / fiber 6ES7 960-1AA04-0XA0 / 6ES7 960-1AB04-0XA0 H-specific — not directly involved, but supports H diagnostics

For S7-400H systems, additional redundant-aware OBs exist and may also need to be considered:

  • OB70 — I/O redundancy error (loss of redundancy on a redundant I/O)
  • OB72 — CPU redundancy error (loss of master / standby or sync failure)
  • OB73 — Communication redundancy error

The same edge-triggered limitation applies to OB70-OB73 — they too will not fire for faults already present at startup. See the SIMATIC S7-400H System Manual for the complete list of redundant-specific OBs and their startup information templates.

3. Diagnostic OB Execution Model in S7-400

Understanding why OB86 is silent at startup requires a precise view of the S7-400 event model. The following table summarizes the diagnostic OBs and their triggering conditions:

OB Name Trigger Startup Behavior
OB82 Diagnostic interrupt Module reports diagnostic event (incoming/outgoing) Only fires on edge after RUN
OB83 Insert/remove module Module insertion or removal during RUN Only fires on edge after RUN
OB85 Priority class error I/O access error during process image update Only fires on edge after RUN
OB86 Rack failure / DP slave failure DP station present → absent or absent → present Only fires on edge after RUN
OB87 Communication failure Communication error (e.g., GD packet failure) Only fires on edge after RUN
OB100 Warm restart CPU completes restart Called once at startup — does not call OB82-87
OB101 Hot restart CPU completes hot restart (S7-400 only) Called once at startup
OB102 Cold restart CPU completes cold restart Called once at startup

The Startup Information of OB86 (and OB82) contains two flags:

  • OB86_FLT_ID — fault identifier (e.g., B#16#C3 / B#16#C4 / B#16#C7)
  • For OB86, the OB86_EV_CLASS byte distinguishes incoming (B#16#38 / B#16#39) from outgoing (B#16#3A / B#16#3B) events

Refer to the Siemens TIA documentation for the diagnostic interrupt OB to confirm startup information layout for OB82: Diagnostic interrupt OB (OB 82) — STEP 7 / TIA Portal V21. The same structure applies on the S7-400, where OB82 startup info contains module start address, channel, and event-in / event-out flags.

4. Root Cause Analysis

The diagnostic gap is not a bug — it is a deliberate consequence of the S7-400 event model:

  1. The CPU boots and enters OB100 (warm restart) or OB102 (cold restart).
  2. During the restart phase, the CPU performs PROFIBUS DP initialization: it calls each slave, parametrizes it, and configures it.
  3. After parametrization, the DP master takes each missing slave into its "not available" state.
  4. Because the CPU never observed the slave as present, no OB86 "incoming failure" event can be generated — there is no edge from "present" to "absent."
  5. OB82, OB83, OB85, OB86, and OB87 remain silent until the next runtime transition.

The only place where the current physical state is authoritatively known is the System State List (SSL). The SSL is a snapshot maintained by the operating system that reflects the actual current condition of every configured module, DP slave, and slot.

Reading the SSL requires the standard function SFC51 "RDSYSST" (Read System State). SFC51 is the only sanctioned interface for the user program to query the SSL. The relevant SSL partial lists for distributed I/O diagnosis are:

SZL_ID Description Index Meaning Typical Use
W#16#0A91 DP slave diagnostic status 0 = extract (all slaves), or DP address Identify which slaves are faulty
W#16#0094 Status of all DP slaves DP master / DP slave system ID Per-system station list
W#16#00B4 Module diagnostic data of a DP slave DP station address Get detailed diagnostic buffer
W#16#00B1 Diagnostic data of a module Logical base address Central / expansion rack slots
W#16#00B3 Module diagnostic data records DS0/DS1 Logical base address Detailed diagnostic record
W#16#0118 H system diagnostic information 1 S7-400H redundant-specific
W#16#0131 Diagnostic buffer of the CPU 1 Recent fault history

For the use case described in this article, the most useful SSL is W#16#0A91 — the DP slave diagnostic status list. Each entry is a two-word record:

Byte Field Meaning
0 Status byte (SZL.STATUS) B#16#00 = OK, B#16#11 = faulty, B#16#33 = not configured
1 Reserved
2-3 DP station address PROFIBUS address of slave

5. Solution Strategy: Active Status Polling in OB100 / OB102

The robust solution is a hybrid architecture:

  1. Mark the fault-tracking DB as non-retentive. This clears any stale flags from before power-down.
  2. In OB100 (warm restart) and OB102 (cold restart), call SFC51 with SZL_ID = W#16#0A91 to read the actual DP slave diagnostic status of every configured station.
  3. Populate the fault-tracking DB based on the SFC51 result. A status byte <> B#16#00 means the station is currently faulty.
  4. After startup, rely on OB86 events for real-time updates.

This hybrid model restores correctness without sacrificing the runtime efficiency of event-driven OB handling. The startup scan adds a few milliseconds to OB100 — negligible on S7-400 — and ensures the diagnostic DB is fully synchronized with the actual physical state before OB1 begins cyclic execution.

Engineering note: For S7-400H, also call SFC51 with SZL_ID = W#16#0118 in OB100 to verify the H-system redundancy state (master / standby / solo). Use OB72 and OB70 for runtime updates.

6. Prerequisites for Implementation

  • STEP 7 V5.5 / V5.6 (or TIA Portal V16+ for S7-400 with compatibility mode)
  • SFC51 from the standard library (CEIL / IEC library)
  • Pre-allocated DB (e.g., DB2000 "Diag_DB") with at least N+2 words, where N is the number of configured DP slaves
  • Configured OB100 and OB102 (download empty OBs if not yet present, otherwise the CPU will remain in STOP if the default startup routine is rejected)
  • Access to the hardware configuration (HW Config) to confirm DP station addresses

7. Implementation in STL

The following STL block can be inserted at the top of OB100 (and duplicated into OB102). It reads SSL W#16#0A91 with INDEX = 0 (extract of all DP slaves) and writes the result into a pre-allocated data area. After the call, the application scans the returned list and marks the fault DB accordingly.

// OB100 — initial SSL scan to populate fault DB
// Scratch flags: M 100.0 = busy, MW102 = retval
// Target data area: P#DB2000.DBX 0.0 BYTE 256 (32 stations max)

      CALL SFC 51
           REQ     := TRUE
           SZL_ID  := W#16#0A91       // DP slave diagnostic status
           INDEX   := W#16#0000       // 0 = full extract
           RET_VAL := MW 102          // 0 = OK, Fxxx = error
           BUSY    := M 100.0
           SZL_HEADER := DB2000.SSL_HEADER   // STRUCT (length, n_records)
           DR      := P#DB2000.DBX 16.0 BYTE 240

      A     M 100.0
      JC    end                // SFC51 still running

      // Evaluate SZL_HEADER: DBW0 = record length, DBW2 = number of records
      L     DBW 0              // record length (bytes per record)
      L     4
      ==I
      JC    eval_4             // each record = 4 bytes (status + addr)

end:  BE

eval_4:
      L     DBW 2              // number of records returned
      T     MW 104             // loop counter
      L     0
      T     MW 106             // pointer offset

next:
      L     MW 104
      L     0
      ==I
      JC    finished

      // Each record: byte 0 = status, byte 1 = reserved, bytes 2-3 = DP address
      L     DBB [MW 106 + 16]  // status byte
      L     B#16#00
      ==I
      JC    ok_station

      // Faulty station: write address + status into fault DB
      L     DBW [MW 106 + 18]  // DP address
      T     DBW [MW 110]       // fault_db[i].addr
      L     DBB [MW 106 + 16]  // status
      T     DBB [MW 112]       // fault_db[i].status
      SET
      S     DBX [MW 114]       // fault_db[i].fault_flag
      JU    cont

ok_station:
      L     DBW [MW 106 + 18]  // DP address
      T     DBW [MW 110]
      L     0
      T     DBB [MW 112]
      CLR
      S     DBX [MW 114]       // fault_db[i].fault_flag = 0
      R     DBX [MW 115]       // fault_db[i].new_fault = 0

cont: L     MW 106
      L     4
      +I
      T     MW 106
      L     MW 110
      L     8
      +I
      T     MW 110
      L     MW 104
      DEC 1
      T     MW 104
      JU    next

finished:
      BE
Programming note: The scratch flags (MW102, MW104, MW106, MW110, MW112, MW114) must be located in a non-retentive area (e.g., M 0.0-M 255.7 with default mapping, or an instance DB). Do not reuse these addresses in OB1 — they will be overwritten by the cyclic scan.

8. Implementation in SCL

For engineers using SCL (Structured Control Language) the same logic is more compact:

// SCL — call inside OB100 / OB102

FUNCTION_BLOCK FB_DiagScan
VAR
    busy       : BOOL;
    ret_val    : INT;
    header     : STRUCT
        length_w  : WORD;
        n_records : WORD;
    END_STRUCT;
    record     : ARRAY[1..32] OF STRUCT
        status : BYTE;
        rsvd   : BYTE;
        addr   : WORD;
    END_STRUCT;
    i : INT;
END_VAR
BEGIN
    RDSYSST(REQ := TRUE,
            SZL_ID := W#16#0A91,
            INDEX  := W#16#0000,
            RET_VAL := ret_val,
            BUSY := busy,
            SZL_HEADER := header,
            DR := record);

    // Wait until SFC51 completes
    WHILE busy DO
        RDSYSST(REQ := FALSE,
                SZL_ID := W#16#0A91,
                INDEX  := W#16#0000,
                RET_VAL := ret_val,
                BUSY := busy,
                SZL_HEADER := header,
                DR := record);
    END_WHILE;

    // Iterate over returned records
    IF ret_val = 0 THEN
        FOR i := 1 TO WORD_TO_INT(header.n_records) DO
            // fault_db[i].fault_flag := record[i].status <> B#16#00;
            "Diag_DB".fault[i]    := record[i].status <> B#16#00;
            "Diag_DB".addr[i]     := record[i].addr;
            "Diag_DB".status[i]   := record[i].status;
            "Diag_DB".new_fault[i] := 0;       // suppress new-fault latching on startup
        END_FOR;
    END_IF;
END_FUNCTION_BLOCK
H-System extension: For S7-400H, also call RDSYSST with SZL_ID = W#16#0118 to read H-system redundancy status. Slot 0 indicates master / standby; if neither bit is set, the system is in solo mode — capture this in OB100 so HMI alarms accurately reflect the H state from the first cycle of OB1.

9. OB86 Runtime Logic — Do Not Remove

The startup scan complements but does not replace the runtime OB86. Once the CPU is in RUN, OB86 remains the authoritative source for live transitions. The combined fault DB write logic should look like this:

  • OB100 / OB102: populate fault DB from SSL (handles pre-existing faults)
  • OB86 (incoming event): set fault flag for the affected station; optionally raise an HMI alarm
  • OB86 (outgoing event): clear fault flag when station returns
  • OB82: handle module-level diagnostic interrupts; update channel-level diagnostic bits
  • OB70 (H only): handle I/O redundancy loss; do not flag the station as failed, only as "no longer redundant"
  • OB72 (H only): handle CPU redundancy error (master/standby swap, sync loss)

The SSL partial-list extractions and their semantics are documented in the STEP 7 Online Help for SFC51 and in the S7-300/400 System Software System and Standard Functions reference manual.

10. Retentive Strategy Combined with SSL Scan

There are three viable retention strategies. Pick one based on the diagnostic semantics required:

Strategy DB Property Startup Action Risk
A — Pure non-retentive Non-retentive OB100 SSL scan populates DB None if SSL scan is implemented
B — Pure retentive Retentive None Stale flags reflect pre-power-down state
C — Retentive with reset bit Retentive OB100 clears DB then SSL scan repopulates Slightly more code; safe

Strategy A is the most elegant and is recommended for new projects. Strategy C is recommended when an existing fault DB has retentive dependencies that cannot easily be removed. In both cases, the OB100 / OB102 SSL scan is mandatory.

11. Verification and Commissioning

Validate the implementation with the following test sequence:

  1. Healthy power-up: With all DP stations connected, power down the cabinet and power back up. Confirm that the fault DB contains no fault flags after OB100 completes (verify in online watch table).
  2. Faulted power-up: Power down, remove one IM 153-2 from the redundant pair on a configured ET200M station, then power back up. Confirm that the fault DB contains a fault flag for that station's address within the first OB1 cycle.
  3. Live transition: With the CPU in RUN and healthy, remove the IM 153-2. Confirm OB86 fires (event class B#16#39 / B#16#3A). Confirm the fault DB flag transitions correctly.
  4. Recovery transition: Reinsert the IM 153-2. Confirm OB86 fires with event class B#16#38 (incoming / station recovered) or B#16#3B (outgoing). Confirm the fault DB flag clears.
  5. Diagnostic buffer cross-check: Read SSL W#16#0131 (diagnostic buffer) after each step and confirm consistent timestamps.
  6. Watchdog on OB100: Confirm OB100 completes in < 100 ms (typical) — add a temporary "OB100 done" timestamp if needed.

Place a breakpoint or status indicator on the OB100 / OB102 block to verify it executes during restart. In STEP 7 / TIA Portal, use the online "Monitor / Modify" function on the fault DB after power-up to confirm the SSL result was applied correctly.

12. Troubleshooting Matrix

Observed Symptom Likely Cause Fix
OB100 SSL scan returns RET_VAL = W#16#80A1 SZL_ID / INDEX combination invalid Verify SZL_ID = W#16#0A91 and INDEX in valid range
RET_VAL = W#16#8080 SFC51 already active Use single instance, wait for BUSY = FALSE
Header.n_records = 0 No DP master / no configured slaves Verify HW Config and DP master system ID
All status bytes = B#16#33 Slaves not configured in HW Config Re-import GSD / re-run HW Config
OB100 never called CPU is in run-mode only (not restarted) Force restart via PG or mode selector
Fault DB cleared on power-up but never repopulates OB100 not downloaded, OB102 not downloaded Download empty OB100 / OB102; place call inside
Fault flag set but not on HMI HMI polling period longer than transient Use event-driven HMI tags or shorter poll period
OB86 fires twice for same station Two DP master systems / H system addressing duplicate Check DP master system IDs in HW Config
OB70 not firing on H redundancy loss OB70 not present in program Download OB70 with at least BE at the end
S7-400H reports "solo" after restart unexpectedly Sync-up not yet completed at OB100 execution Delay SSL scan until after first link-up check (e.g., 1 s)

For deeper information on diagnostic error interrupt semantics across S7-300/400, see Diagnostic interrupt OB (OB 82) (S7-300, S7-400) — TIA Portal V21 and the S7-1200 equivalent for context on the diagnostic event model in TIA Portal S7-1200 Manual Collection — Diagnostic error interrupt OB. Although the S7-1200 differs in detail, the underlying "edge-triggered vs. status-based" distinction is identical and explains the philosophy behind OB82's startup information. For CPU-specific manuals, consult SIMATIC S7 S7-1200 Programmable controller — ID 91696622, which contains the same diagnostic-event model description applicable to the S7-1200 family.

13. Edge Cases and Field-Proven Caveats

  • OB100 timing on H systems: On S7-400H, OB100 may execute before the sync link is fully established. Avoid making sync-dependent decisions inside OB100. Instead, set a "first scan" flag and act on it from OB1.
  • SSL extract limits: SZL_ID W#16#0A91 with INDEX = 0 returns an extract. The maximum number of records depends on the CPU; S7-417 supports 64 DP slaves per master system, multiple master systems. Plan the data area accordingly (4 bytes × max stations + 4-byte header).
  • DP/PA couplers: For PROFIBUS-PA segments behind a coupler, use SZL_ID W#16#0A92 in addition to W#16#0A91 — PA devices are not visible in the DP slave list.
  • Subsequent re-parameterization: If a slave was disconnected at power-up, the CPU still parametrizes it after a configurable timeout. The SSL status byte then transitions from B#16#11 to B#16#00 if the slave returns. To avoid false "station OK" flags, do not read the SSL too early in OB100.
  • Faults cleared during OB100: OB100 must complete before OB1 starts. If the diagnostic DB is non-retentive and OB100 fails to populate it, OB1 will read zeros. Wrap the SFC51 call in a status check and refuse to leave OB100 if the read failed (BU/Be for monitoring only — do not block startup unless absolutely required).
  • CPU 410 (newer H family): The same pattern applies. Use SZL_ID W#16#0A91 with INDEX = 0 in OB100. S7-400H-specific SSL W#16#0118 is unchanged.
  • Time stamping: When logging fault timestamps, use SFC1 (READ_CLK) inside OB86 — not SFC51. The SSL itself does not carry timestamps; it carries current status only.

14. Frequently Asked Questions

Why does OB86 not fire at power-up when a DP slave is missing?

OB86 is edge-triggered. The CPU only generates OB86 when a station transitions between present and absent during RUN. If the slave is already absent when the CPU first scans it during restart, no edge occurs and OB86 is never called. Use SFC51 with SZL_ID W#16#0A91 in OB100 or OB102 to query the current SSL status directly.

Which SZL_ID should I use to read the DP slave diagnostic status?

Use W#16#0A91 (DP slave diagnostic status). Call SFC51 with INDEX = 0 to get a full extract of all configured DP slaves. Each record is 4 bytes: status byte, reserved byte, and the 2-byte DP station address. A status byte of B#16#00 indicates the slave is OK; B#16#11 indicates a faulty slave; B#16#33 indicates an unconfigured address.

Should the diagnostic DB be retentive or non-retentive?

For a clean implementation, mark the diagnostic DB as non-retentive and use the OB100 / OB102 SSL scan to repopulate it at every restart. This prevents stale flags from before power-down. If retention is required, use OB100 to clear the DB and then repopulate from the SSL — never rely on OB86 alone for the initial state.

Does the same issue affect OB82 diagnostic interrupts?

Yes. OB82 (module diagnostic interrupt) is also edge-triggered. Diagnostic events that exist at the moment of power-up will not trigger OB82. The SZL_IDs W#16#00B1 (diagnostic data of a module) and W#16#00B3 (DS0/DS1 diagnostic records) can be polled in OB100 to detect existing module faults. Index with the logical base address of the slot.

How does this change for S7-400H redundant systems?

The principle is identical, but additional SSLs apply. Use SZL_ID W#16#0118 in OB100 to read H-system redundancy status, and populate H-specific fault tracking for OB70 (I/O redundancy loss) and OB72 (CPU redundancy error) the same way. On H systems, ensure the OB100 SSL scan runs after the sync link is established, or delay the H-state evaluation to the first OB1 cycle.

What is the maximum number of DP slaves supported by SZL_ID W#16#0A91?

The partial list extract length depends on the CPU. S7-416 and S7-417 support up to 64 DP slaves per master system and multiple master systems. Allocate the destination area generously (e.g., 32 × 4 bytes for one DP master system, 64 × 4 bytes for two) and check the SZL_HEADER.n_records field to determine the actual count returned.

Back to blog