Troubleshooting OB86 FLT_ID 16#CD on ET200S-ET200SP PROFINET

David Krause17 min read
S7-300SiemensTroubleshooting
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

Troubleshooting OB86 FLT_ID 16#CD on ET200S-ET200SP PROFINET

1. Problem Overview: OB86 Stuck on 16#CD Instead of 16#CB

When an ET200S CPU (IM151-8 PN/DP family) is connected to a remote ET200SP station over PROFINET IO, the application expects OB86 to fire with FLT_ID = B#16#CB the moment the IO device disappears from the network. In normal operation this is the case: pulling the PROFINET cable while both controller and device remain powered triggers an incoming event (EV_CLASS = B#16#38) with FLT_ID = B#16#CB (station failure). When the cable is plugged back in, OB86 fires the outgoing event (EV_CLASS = B#16#39) with the same FLT_ID, indicating the failure has cleared.

A specific scenario breaks this pattern and is the source of the field symptom reported on a TIA Portal V11 project:

  1. ET200S CPU remains powered on (RUN or STOP).
  2. ET200SP station is switched OFF (24 V removed from the interface module).
  3. The PROFINET cable is disconnected and reconnected at the ET200SP side.
  4. OB86 fires with EV_CLASS = B#16#38 and FLT_ID = B#16#CD (configuration difference), not the expected B#16#CB (station failure).
  5. The CPU never reports the B#16#CB (failure) or B#16#39 (outgoing) events until the cable is unplugged and plugged a second time after the device has been powered up.

The PLC cannot be used to monitor the ET200SP station reliably with OB86 alone in this configuration. This article documents why this happens, what each FLT_ID actually means on PROFINET, and the available mitigations - from event buffering in OB86 to PROFINET diagnostic reads via SFB52 RDREC and SFC51 RDSYSST.

Tooling note: All examples below assume TIA Portal V11 / STEP 7 V11 SP2 or later. The OB86 local-data layout shown matches the S7-300/400 reference manual and is documented in the Rack failure organization block (OB 86) reference for S7-300/S7-400.

2. OB86 Local Data Layout and Event Codes

OB86 is the rack-failure / distributed-I/O-failure OB. According to the Siemens reference, the start information of OB86 contains the following temporary variables that the firmware pre-fills before the OB is entered:

Variable Type Description
OB86_EV_CLASS BYTE Event class: B#16#38 (incoming, OB entered) or B#16#39 (outgoing, OB completed / fault cleared)
OB86_FLT_ID BYTE Fault identifier (see Section 3)
OB86_PRIORITY BYTE Priority class - default 2 in RUN, may be 26 in STARTUP
OB86_OB_NUMBR BYTE OB number (always 86)
OB86_RESERVED_1 BYTE Reserved
OB86_IO_FLAG BYTE I/O flag: B#16#54 = input, B#16#55 = output
OB86_MDL_ADDR WORD Logical base address of the master / affected PROFINET IO system
OB86_ZINFO WORD Additional information - on PROFINET: device number 1-255
OB86_ZINFO_1 DWORD Slot / module identifier
OB86_ZINFO_2 DWORD Module status / vendor ID
OB86_ZINFO_3 DWORD Device identification (vendor ID + device ID)

For PROFINET IO, OB86_MDL_ADDR returns the HW identifier of the affected PROFINET IO system or station, and OB86_ZINFO returns the device number (1-255). OB86_ZINFO_1 carries the slot number. The combination of these three values uniquely identifies a station/slot pair and is the only reliable way to distinguish a missing device from a configuration mismatch.

3. EV_CLASS and FLT_ID Code Reference

The two bytes most engineers key on are EV_CLASS and FLT_ID. The complete set of FLT_ID values that can appear in OB86 on a PROFINET IO system is shown below. Codes are taken from the SIMATIC S7-300/400 CPU reference manual; verify against the manual that ships with your specific CPU firmware version.

EV_CLASS FLT_ID Meaning Typical trigger
B#16#38 B#16#C1 PROFINET IO system failure PN controller side network down
B#16#38 B#16#C3 PROFINET station failure (legacy) PROFIBUS DP or older PROFINET device drop
B#16#38 B#16#C5 PROFINET slot / submodule failure Module pulled from a powered station
B#16#38 B#16#CB PROFINET interface module failure ET200SP head station lost from an established AR
B#16#38 B#16#CD Configuration difference (expected != actual) Configured device missing at scan time, topology mismatch
B#16#39 B#16#C2 PROFINET IO system return Controller-side network restored
B#16#39 B#16#C4 PROFINET station return (legacy) Older PROFINET device reappears
B#16#39 B#16#C6 PROFINET slot / submodule return Submodule reinserted
B#16#39 B#16#CC PROFINET interface module return ET200SP head station powered back up
B#16#39 B#16#CE Configuration difference cleared Topology now matches the project

Observe that B#16#CD is paired with an outgoing event of B#16#CE, not B#16#CB/B#16#CC. This is the source of the symptom reported in the field: a station that was simply not powered cannot report "failure" because the PROFINET stack has never seen it answer. The controller reports a configuration mismatch instead.

Symptom summary: When the ET200SP is off and the cable is unplugged, no OB86 is triggered (the controller sees a "ghost" of a device that was never there). When the cable is plugged in, OB86 fires with FLT_ID = B#16#CD because the configured device is unreachable. Only when the ET200SP head module is powered on does the second cable pull generate the expected B#16#CB / B#16#CC sequence.

4. Root Cause: Why OB86 Reports 16#CD Instead of 16#CB

The PROFINET IO controller inside the ET200S CPU maintains an Application Relationship (AR) state machine for every configured device. The relevant states are:

  1. Expected - device configured in TIA Portal, not yet seen on the wire.
  2. Discovering - DCP identify frames answered, AR being negotiated.
  3. Established - cyclic data exchange running.
  4. Failure - watchdog timeout on the established AR.
  5. Return - AR re-established.

When the ET200SP is unpowered, the controller sits in the Expected state (or a passive "wait for identify" substate) and never builds an AR. Pulling the cable at this point is invisible to the controller at the AR layer - the link LED on the CPU port may indicate link loss, but the AR was never active, so OB86_FLT_ID does not move to B#16#CB. Re-plugging the cable prompts a re-scan that finds no device with the configured name, which the stack reports as a configuration difference (B#16#CD) rather than a station failure (B#16#CB).

Powering the ET200SP head module up causes the device to respond to DCP, the AR to be built, and from that moment onward the controller is in a state where it can distinguish failure from configuration. At that point, removing the cable triggers B#16#CB, restoring it triggers B#16#CC.

ET200SP OFFCable pull: no OB86 Cable reinsertedOB86: EV=38 / FLT=CD ET200SP POWEREDAR established Cable pullOB86: CB / CC Restart with ET200SP still OFF Expected: CB on cable pull, CC on re-plug

5. Verifying PROFINET Configuration in TIA Portal

Before modifying the OB86 program, validate the engineering view of the project:

  1. Open the PROFINET topology view in TIA Portal. Confirm the ET200SP station has the correct PROFINET device name assigned (Online > Accessible nodes > Assign PROFINET device name).
  2. Compare the configured device number to the actual ring/line position. PROFINET device numbers 1-255 must be unique on the subnet.
  3. Verify that the ET200SP head module is configured with the right catalog version. ET200SP IM 155-6 PN ST, HF and HS variants differ in supported diagnostics. Mismatch with the configured module version triggers B#16#CD at every restart.
  4. In the device properties, set "Startup behavior > Comparison preset to actual configuration" to "From compatible partner module" or "From configured module" - never to "From slot 0" if the slot is empty.
  5. Compile and download the hardware configuration. A stale PLC that still uses an old HW identifier will not match the renamed device and will keep producing B#16#CD events.
TIA Portal V11 caveat: V11 has limited support for ET200SP catalog updates. If the ET200SP module is not in the V11 hardware catalog, install HSP 0180 (or the latest ET200SP Support Package) and update the catalog before chasing OB86 errors. Many "stuck 16#CD" symptoms in V11 are caused by missing GSDML support.

6. Implementing a Robust OB86 with Event Buffering

OB86 may be entered multiple times within a single second (e.g., a flapping station). To avoid losing events, buffer every entry into a ring DB keyed on a timestamp and MDL_ADDR. The pattern below uses a single FB and is written in Structured Text (SCL), which TIA Portal V11 supports natively for new function blocks.

FUNCTION_BLOCK "FB_OB86_Logger"
VAR
  sidx : INT  := 0;          // ring slot index
  cnt  : DINT := 0;          // total events seen
END_VAR
BEGIN
  // 1. Always save the event first - never overwrite blindly
  "DB_OB86_Log".Event[cnt MOD 16].EV_CLASS  := OB86_EV_CLASS;
  "DB_OB86_Log".Event[cnt MOD 16].FLT_ID    := OB86_FLT_ID;
  "DB_OB86_Log".Event[cnt MOD 16].MDL_ADDR  := OB86_MDL_ADDR;
  "DB_OB86_Log".Event[cnt MOD 16].ZINFO     := OB86_ZINFO;
  "DB_OB86_Log".Event[cnt MOD 16].TIMESTAMP := RD_SYS_T(LO_TOD#0s);
  cnt := cnt + 1;

  // 2. Trigger application logic only on the (EV_CLASS, FLT_ID) pair you care about
  IF OB86_EV_CLASS = B#16#38 AND OB86_FLT_ID = B#16#CB THEN
    "DB_OB86_Log".Station[OB86_MDL_ADDR].Lost := TRUE;
  ELSIF OB86_EV_CLASS = B#16#39 AND OB86_FLT_ID = B#16#CC THEN
    "DB_OB86_Log".Station[OB86_MDL_ADDR].Lost := FALSE;
  END_IF;

  // 3. Treat B#16#CD / B#16#CE as a soft "configuration drift" alarm
  IF OB86_FLT_ID = B#16#CD THEN
    "DB_OB86_Log".LastConfigMismatch := OB86_MDL_ADDR;
  END_IF;
END_FUNCTION_BLOCK

Notes on the snippet:

  • Use the standard OB86 temporary variables that the firmware pre-fills; do not redeclare them by hand.
  • The ring has 16 slots. With 1 s resolution from RD_SYS_T, this gives 16 s of history, which is enough to catch cable flaps that the human eye misses.
  • The logger is the only call inside OB86. OB86 is non-preemptive: nothing else will run until OB86 returns, so keep the body short.
OB86 priority pitfall: If you place a blocking call inside OB86 (e.g., WR_PARM with the wrong record), the firmware will skip the OB at startup priority 26. In TIA Portal V11 this can be diagnosed by opening the CPU diagnostic buffer and looking for the entry "OB86 priority error".

7. Reading ET200SP Slot Diagnostics with SFB52 RDREC

When OB86 only gives you B#16#CD/B#16#CE, read the diagnostic record of the affected station to know which slot is misbehaving. SFB52 RDREC is the only standard tool to do this from PLC code without going through the CPU display. The block signature in S7-300/400 is:

CALL "RDREC" , DB52
  REQ    := TRUE                       // edge-triggered; keep TRUE until BUSY goes low
  ID     := W#16#10C                   // HW identifier of the ET200SP head module
  INDEX  := 0                          // standard diagnostic record 0
  MLEN   := 64                         // up to 64 bytes of record
  VALID  := "DB52".RDREC_VALID
  BUSY   := "DB52".RDREC_BUSY
  ERROR  := "DB52".RDREC_ERROR
  STATUS := "DB52".RDREC_STATUS
  LEN    := "DB52".RDREC_LEN
  RECORD := P#DB 52 DBX 0.0 BYTE 64
END_CALL;
Parameter Value for ET200SP Notes
ID HW identifier of the station Read from the ET200SP device properties in TIA Portal (Project tree > Device properties > System constants). For an ET200SP PN on PROFINET IO system 1 with device number 3, the ID is typically 268 dec. Verify in the system constants table.
INDEX 0 = standard diagnostic; 0x8000 = identifier-related; 0x800A = diagnostic interrupt; 0x802B = port data For ET200SP modules, INDEX 0 returns the standard record 0 (vendor-specific length up to 64 bytes). Records 0x8000-0x800C are defined by the PROFINET profile.
MLEN 4-234 bytes Use 4 first to read the standard header (first 4 bytes include the length), then read the full record in a second call.
RECORD DB / area of MLEN bytes Must be exactly MLEN bytes or longer. TIA Portal V11 warns but still allows shorter areas; V13+ is stricter.
STATUS Standard SFB52 return codes W#16#0000 = OK; W#16#80A0 = negative acknowledgement; W#16#80A1 = slot does not exist; W#16#80C0 / 80C3 = record not available

After the read, bytes 0-3 of the record always contain the standard PROFINET header:

  • Byte 0 - block type (0x01 = record 0, 0x02 = record 1, 0x03 = record 2, 0xF0 = vendor-specific)
  • Byte 1 - reserved / length high
  • Bytes 2-3 - length low 16 bits
  • Byte 4+ - vendor-specific payload (channel number, error type, LED status)
Read before you write: Reading INDEX 0x800A (diagnostic interrupt) on an ET200SP IM 155-6 PN ST returns up to 234 bytes. Always size the RECORD area to 234 bytes; the LEN output tells you how many bytes were actually written.

8. Polling System Status Lists via SFC51 RDSYSST

For station-level status without driving a single slot, use SFC51 RDSYSST to read the partial system status lists (SZL). The SZL is the in-CPU database that the diagnostic buffer, the web server, and the HMI all use. The SZL entries that matter for PROFINET are:

SSL_ID (hex) Name What it tells you
W#16#0131 Diagnostic status of a station Aggregate status, single word per device number
W#16#0174 Status of the modules of a PROFINET IO station One entry per slot: OK / faulty / not present
W#16#0424 Status of the PN interfaces Up/down for every PN port - used to triangulate cable issues
W#16#0F31 Module diagnostic information (raw) First 4 bytes mirror the standard PROFINET record 0
W#16#0A91 PN IO interface parameters Port link state, speed, autonegotiation

Example - reading the link status of port 1 of the PROFINET IO system:

CALL "RDSYSST" , DB51
  REQ        := TRUE
  SSL_ID     := W#16#0424            // PN interface status
  INDEX      := 1                    // port number
  SZL_HEADER := "DB51".HDR
  DR         := P#DB 51 DBX 0.0 BYTE 32
  RET_VAL    := "DB51".RV
  BUSY       := "DB51".BSY
END_CALL;

If RET_VAL returns W#16#7000 (busy) or W#16#0000 (done), the entry was read. A return of W#16#0085 means the entry is dynamic and may not be available during STOP. Combine the link state with OB86 to distinguish "cable yanked" from "device powered off":

  • OB86 fires B#16#CB and SZL 0x0424 = "down" -> cable removed on a running device.
  • OB86 fires B#16#CD and SZL 0x0424 = "down" -> device unpowered from boot.
  • OB86 fires B#16#CC and SZL 0x0424 = "up" -> device returned and link is alive.

9. CPU Diagnostic Buffer and Online Diagnostics

When OB86 does not fire at all (e.g., during STOP->RUN transition), the diagnostic buffer is the only place the events are recorded. In TIA Portal:

  1. Online > Online & diagnostics > Diagnostics buffer.
  2. Filter on "IO controller" and "IO device".
  3. Look for entries with text "Station failure", "Station return", "Configuration error".

Each entry carries a timestamp accurate to 10 ms, plus the event ID in the format "0xE0xx" or "0xE1xx" (mapped to OB86 FLT_ID). Sample entries the engineer will see in this scenario:

  • "Station failure - PROFINET IO device" - corresponds to B#16#C3 / CB.
  • "Configuration error - expected configuration does not match actual configuration" - corresponds to B#16#CD.
  • "No fault" - OB86 was not entered, so nothing fired at the application level. The buffer will still show the firmware event.
STOP->RUN quirk: OB86 is not entered when the CPU transitions from STOP to RUN with no faults present. This is by design - the rack-failure OB exists to report faults during RUN, not at restart. A device that is unpowered when the CPU is started will simply be marked "not available" in the IO system status, and the application must query this on its own via the process image quality bits or SZL 0x0174.

10. ET200SP Power-Up and Station-Return Sequencing

PROFINET follows a strict startup sequence. For an ET200SP IM 155-6 PN HF (or HS) head module, the controller expects:

  1. DCP identify (NameOfStation assignment).
  2. AR establishment (Connect request -> Connect response).
  3. Cyclic I/O data exchange.
  4. Alarm handshake (Diagnostic alarms if OB82 is loaded).

If step 1 or 2 fails (e.g., the head module is still in POST), the controller aborts the AR and reports B#16#CD. The AR is then re-attempted at the next device-scan cycle (default 1 s for ET200SP HF, configurable down to 250 ms). The engineer can therefore expect:

  • t = 0 ms - power ON 24 V at the ET200SP.
  • t approx 1.5-3 s - IM 155-6 PN is ready, DCP responds.
  • t approx 3.0-4.0 s - AR established, cyclic data exchange starts.
  • t approx 4.0-4.5 s - OB86 fires with EV_CLASS = B#16#39, FLT_ID = B#16#CE (configuration difference cleared) or B#16#CC (interface module return), depending on whether the head module matched the configured version exactly.

The window where the engineer can see B#16#CD is therefore at most 1 s to 4 s. Anything longer usually means a name mismatch, wrong GSDML, or a defective port on the switch. If the time exceeds 10 s, swap the patch cable and check the switch port LED state via SZL 0x0424.

11. Verification and Commissioning Checklist

Before the system can be handed over, run and log the following checks:

  1. Power ON test: Power on PLC and ET200SP simultaneously. Within 5 s, OB86 must report B#16#CE or B#16#CC. The diagnostic buffer must show a "station return" event.
  2. Cable pull test: With both devices powered, pull the PROFINET cable. OB86 must report B#16#CB within 1 s. Re-plug and verify OB86 reports B#16#CC within 1 s. Repeat 10 times to catch flapping.
  3. Powered-off device test: Power off the ET200SP. Wait 30 s. OB86 must report either B#16#CD (configuration difference) or, in newer firmware, B#16#CB with a delay. Pulling the cable at this point must not produce an additional B#16#CB event.
  4. Stop->Run test: Stop the CPU, leave ET200SP off, restart CPU. OB86 must NOT fire. Verify that the application sees the station as "missing" through the IO system status bits (e.g., quality flag in the process image or SZL 0x0174).
  5. SFB52 RDREC sanity test: With the device present, call RDREC with INDEX = 0. STATUS must be 0 and LEN must be greater than 4. With the device powered off, the call must return STATUS = W#16#80A0 or W#16#80A1 within 1 s.
  6. SFC51 RDSYSST link test: With the device powered, SZL 0x0424 INDEX 1 must return LINK = up. With the device powered off, it must return LINK = down. The application uses this to disambiguate a powered-off station from a cable break.
  7. Diagnostic buffer dump: Save the buffer as a .bin file and attach it to the commissioning report.
  8. Web server: If the CPU has a web server, enable it and verify the diagnostic page mirrors the buffer.
Acceptance criterion: A healthy PROFINET link must not produce B#16#CD during normal operation. If B#16#CD is observed, treat it as a configuration or firmware mismatch and resolve it before commissioning the IO. Acceptance is only granted when OB86 logs zero B#16#CD events across a full power-cycle test.

12. Frequently Asked Questions

Why does OB86 show FLT_ID 16#CD instead of 16#CB when my ET200SP is off?

The PROFINET IO controller in the CPU distinguishes between a station that was present and has gone away (B#16#CB) and a station that was never reachable because the head module is unpowered (B#16#CD - configuration difference). The AR was never established, so there is nothing to report as a failure. Power up the ET200SP and wait for the AR to come up; only then will B#16#CB / B#16#CC appear on subsequent cable events.

How can I tell the difference between a powered-off station and a cable break on a live station?

Check the port link state via SZL 0x0424 with SFC51 RDSYSST. A powered-off device reports the link as "up" (cable is good) and OB86 shows B#16#CD. A cable break reports the link as "down" and OB86 shows B#16#CB. Combining the OB86 event and the link state uniquely identifies both cases.

Which SFB52 RDREC parameters do I use for an ET200SP station?

Set ID to the HW identifier of the ET200SP head module (visible in the system constants of the TIA Portal project), INDEX to 0 for the standard diagnostic record, and MLEN to 64 bytes to cover the largest standard record. For channel diagnostics, set INDEX to 0x800A and MLEN to 234 bytes. STATUS returns W#16#0000 on success, W#16#80A0 / 80A1 / 80C0 / 80C3 on common errors.

Is SFC51 RDSYSST still usable on an S7-300 CPU running TIA Portal V11?

Yes. SFC51 is a standard CPU function and is available in every S7-300 CPU from firmware V2.x onward. TIA Portal V11 places it in the standard library; drag it from "Program elements > Libraries > Standard Library > System Function Blocks" onto a call block. Inputs are REQ, SSL_ID, INDEX, SZL_HEADER, DR, RET_VAL, BUSY.

Why is OB86 not called at all when the CPU transitions from STOP to RUN?

OB86 reports faults detected during RUN. A device that was already missing when the CPU entered RUN is reflected in the IO system status table (process image quality bits) but does not fire OB86 because the controller has no AR to report against. Use the SZL 0x0174 via SFC51 RDSYSST, or RDREC on the head module, to detect the missing device on application startup.

Can I use DIS_IRT to mask the 16#CD event and rely on a different mechanism?

Yes, but only on OB8x family interrupts. DIS_IRT disables a specific interrupt (OB40-OB47, OB82, OB83, OB86) for a given logical address. For an OB86 station-failure event on a powered-off device, calling DIS_IRT(MODE := 0, OB_NR := 86, ...) suppresses the event entirely. This is acceptable when the application does not need to react to a non-running head module. The drawback is that ENA_IRT must be called to re-enable OB86, and any genuine failure will be masked until the application remembers to re-enable the interrupt. Reserve this for HMI/scada paths that consume SZL 0x0174 instead of OB86.

Back to blog