S7-1500 Connection Diagnostics with T_DIAG and TRCV Handshake

David Krause13 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

Problem Overview: Monitoring an S7-1500 OUC Link to a Customer PC

Engineers deploying SIMATIC S7-1500 CPUs (CPU 1511, 1513, 1515, 1516, 1518, and the software-PLC variants CPU 1515SP PC / CPU 1516HF PC) for open data exchange with a non-SIMATIC customer PC often rely on the Open User Communication (OUC) instruction set — TCON, TSEND, TRCV, and T_DIAG — to set up and supervise the TCP session. While TCON opens/closes the socket and TSEND/TRCV carry payload, link-health verification lives in T_DIAG. Field experience on customer PC integrations shows that T_DIAG alone has a latency gap that can leave the controller declaring the connection healthy after the physical medium has been lost. The pattern that closes that gap pairs T_DIAG with a TRCV-based application-layer heartbeat, with the heartbeat supplying sub-second fault detection and T_DIAG acting as a slow, secondary check for partner-PC crashes where no FIN ever arrives.

Open User Communication Architecture on S7-1500

The CPU 15x family exposes OUC instructions in TIA Portal V18 / V19 / V20 under Communication > Open User Communication. Each connection consumes an instance DB bound to TCON. The instance DB is parameterised in the inspector under Properties > Configuration > Connection parameters where the active/passive role, partner IP, port, and local TSAP/port are set. Where the partner is a non-SIMATIC PC, the role is almost always active connect with TCP protocol; the S7-1500 opens the socket to the configured remote IP and port.

For static-IP target partners, the configuration block contains:

  • Connection ID — a 16-bit handle unique project-wide.
  • Connection type — TCP (ISOonTCP is reserved for SIMATIC partners).
  • Active connection establishment — enabled (S7-1500 acts as client).
  • Remote address — dotted IPv4, e.g. 192.168.10.42.
  • Remote port — e.g. 2000, 5000, or 25000.
  • Local port — leave blank to let firmware assign, or pin when traversing VLAN/NAT boundaries.

Once loaded, the connection is established at runtime by TCON in OB1 or OB100 and remains held until TCON receives a disconnect request or the underlying TCP state machine times out. Diagnosing the actual runtime state, however, is the job of T_DIAG, not TCON.

TCON / TSEND / TRCV / T_DIAG Quick Reference

Instruction Purpose Trigger Block Key I/O
TCON Establish / tear down TCP connection OB1, OB100 req, ID, done, busy, error, status
TSEND Transmit buffer to remote OB1, cyclic req, ID, LEN, DATA, done, busy, error, status
TRCV Receive data from remote OB1 / OB3x (cyclic) en / req, ID, DATA, NDR, busy, error, status, RCVD_LEN
T_DIAG Inspect / supervise connection state OB1 (low priority) req, ID, MODE, done, busy, error, status, Result

The Result output of T_DIAG is a pointer to a structure of type TDiag_StatusExt (also referenced as TDiagExtStatus in some firmware versions). It contains, among other elements, the State field, the ConnTrialsSuccess / ConnTrialsFaults / ConnFaultsSinceLastSuccess counters, and the LastError field. These five elements are sufficient for health supervision when polled at a controlled rate.

Configuring TCON for a Static-IP PC Target

In TIA Portal V18 and newer, drag TCON onto an FB/OB block, create the Connection instance DB, and configure:

Connection ID            : W#16#0001
Connection type          : TCP
Active connection estab. : true
Partner                  : IPv4 / decimal
  Address                : 192.168.10.42
  Port                   : 2000
Local interface          : PROFINET interface [X1]
Local port               : (auto) — leave blank unless bridging VLANs

Save and download both the hardware configuration and the program blocks. Confirm the partner firewall is open on the remote port — connection attempts to a closed port surface in T_DIAG with State = 16#0006 (pending) and LastError = W#16#80C1 or W#16#80C5 depending on the firmware version. Refer to the Communication connections to PC stations (S7-300, S7-400, S7-1500) handbook and the TIA Portal V20 Open User Communication online help for the full error-code legend.

T_DIAG Instruction: Structure and Parameters

T_DIAG operates on a given connection ID and reads back the live state. The relevant inputs are:

  • req (BOOL) — rising edge triggers one diagnostic cycle.
  • ID (WORD) — the connection handle matching TCON's instance DB.
  • MODE (USINT) — 1 = read status / check connection; 2 = reset internal counters; additional values per firmware.
  • Result (VARIANT pointer or instance of TDiag_StatusExt) — destination for the status structure.

When the Result parameter is dragged into a global DB or the static section of an FB, TIA Portal lists the type as TDiag_StatusExt in the data-type picker. In some installations the helper type is hidden because of a partial library import; in those cases the engineer must enter the type name string verbatim into the Data type column of the DB — the exact symptom called out in the field case ("the type can't be found"). The fix is to import or browse to the type:

DATA_BLOCK "DB_Diag"
  STRUCT
    Sts : TDiag_StatusExt;   // if unresolved, type the name manually
  END_STRUCT;
END_DATA_BLOCK

If the manual type name does not compile, reinstall the Open User Communication global library under Options > Global Libraries > Open User Communication; this deposits TDiag_StatusExt into the project's type catalogue so subsequent DBs can use the picker.

TDiag_StatusExt Field Definitions and State Codes

The structure is read into a DB and parsed by user code. Its typical fields are:

Field Type Meaning (HEX hint)
State WORD 16#0004 = connection established (CONNECTED); 16#0006 = pending; 16#0002 = disconnected; other codes indicate transient states.
ConnTrialsSuccess DINT Successful connections since last reset (counter).
ConnTrialsFaults DINT Failed connect attempts since last reset.
ConnFaultsSinceLastSuccess DINT Faults observed after the last successful connect.
LastError WORD Last reported firmware status, e.g. W#16#0000 none, W#16#80C1 aborted.

The exact field naming follows the firmware-version-dependent documentation; consult the TIA Portal V20 Open User Communication online help for version-specific names. In practice, the supervisor watches State == 16#0004 and ConnTrialsSuccess > 0 as the healthy-condition gate.

State Code Reference Table

State (HEX) Interpretation Engineering Meaning
16#0000 DISCONNECTED TCON never executed or was torn down; no partner.
16#0002 LISTENING Passive side awaiting partner.
16#0004 CONNECTED TCP socket established and ready for TSEND/TRCV.
16#0006 CONNECTION_PENDING Connect attempt in progress (ARP resolution, SYN sent).
16#0007 DISCONNECT_PENDING Tearing down, TCP FIN_WAIT.
16#0008 REMOTE_DISCONNECT Partner closed the socket; controller must re-establish.
16#000A ABORTED Connection aborted locally (timeout, OS reset).

Treat the values as firmware-version-dependent and always cross-check the installed CPU firmware release notes before relying on a specific code. S7-1500 firmware V2.9 and V3.x enumerate the states in the same logical order but may add additional transient codes.

The Cable-Disconnect Detection Gap

A common field symptom is that T_DIAG invoked immediately after the Ethernet cable is unplugged continues to report State = 16#0004 for several seconds, often 30 s or more, because the TCP socket remains in ESTABLISHED state until the operating system's TCP retransmit timer expires. S7-1500 CPUs implement TCP with optional keep-alive timers, but their default values (several minutes) make them inadequate for process supervision where the cycle time must detect a failure within a few scan cycles.

Implications for the supervisor:

  • A single-shot T_DIAG right after a fault can mis-classify the link as healthy.
  • Polling faster than the OS retransmit window still yields stale State = 16#0004.
  • Applications requiring hard real-time detection (≤ 5 s) cannot rely on the TCP layer signals alone.

The remediation is a higher-layer heartbeat: the PC partner transmits a counter or random token at a fixed interval; the controller receives it via TRCV. As long as a fresh token arrives every T seconds, the link is provably live. The TCP keep-alive layer is relegated to a secondary, slow check that handles partner crashed cases where no FIN ever arrives.

Handshake-Based Connection Verification with TRCV

The robust pattern is:

  1. The customer PC's terminal software (Python sockets, Node.js, Excel VBA MSCOMM, Hercules, netcat) sends a small frame at 100–250 ms intervals — for example ASCII HB;0012;XYZ\r\n or a 4-byte big-endian counter.
  2. The S7-1500 cyclically triggers TRCV with the same Connection ID. TRCV delivers the frame into a receive buffer; NDR toggles when new bytes are present.
  3. The application parses the frame, increments a rolling counter, and increments a heartbeats received since last scan counter.
  4. A timer (e.g. an IEC timer in OB3x with 500 ms cadence) clears the rolling counter if no frame arrives; if the counter drops below a threshold — say three consecutive misses at 250 ms each (≈ 750 ms) — the application declares the link down and triggers TCON to re-establish.

Sample SCL fragment that lives in OB1:

IF "rcv".NDR = TRUE THEN
    "i_HbCount" := "i_HbCount" + 1;
    "dbDiag".HeartbeatAge_ms := 0;
    "b_LinkOK" := TRUE;
END_IF;

Cyclic timer in OB3x (e.g. 250 ms):

// Heartbeat age watchdog
"dbDiag".HeartbeatAge_ms := "dbDiag".HeartbeatAge_ms + 250;
IF "dbDiag".HeartbeatAge_ms > 1500 THEN
    "b_LinkOK" := FALSE;
END_IF;

This is the handshake approach the original deployment ultimately adopted: TRCV-driven count from the PC partner side, with T_DIAG demoted to a periodic backup check.

Periodic T_DIAG Polling Paired with TRCV Handshake

A practical compromise uses T_DIAG on a slow cadence (every 5–30 s) to catch cases where the partner PC is dead but the socket has not yet been torn down, while the TRCV handshake detects cable-unplug or partner-PC power-loss in real time. The two indicators are combined in a logical OR — the channel that flags the fault wins.

// OB1 / cyclic task — combined health gate
IF "b_LinkOK" = TRUE                         // TRCV handshake healthy
   AND "dbDiag".Sts.State = 16#0004          // T_DIAG also healthy
   AND "dbDiag".Sts.ConnTrialsSuccess > 0
THEN
    "b_DualPathHealthy" := TRUE;
ELSE
    "b_DualPathHealthy" := FALSE;
END_IF;

Wrap T_DIAG's req edge with a 30 s clock derived from a TP / clock-bit / IEC timer so the diagnostic does not fire every scan:

IF "clk_TDiag".Q THEN
    "t_diag".req := TRUE;
END_IF;

"t_diag"(req  := "t_diag".req,
         ID   := W#16#1,
         MODE := 1,
         done   => "t_diag".done,
         busy   => "t_diag".busy,
         error  => "t_diag".error,
         status => "t_diag".status,
         Result := "dbDiag".Sts);

Periodic counters kept inside T_DIAG (ConnTrialsFaults rising, ConnFaultsSinceLastSuccess rising) generate alarms even when the connection re-establishes itself, allowing the engineer to count flaky-link events over a shift.

PC-Side TCP/IP Terminal / Excel Socket Configuration

When the partner is a customer-provided general PC, the typical software used to terminate the OUC TCP socket falls into these classes:

  • Linux: netcat nc -l -p 2000, or a Python 3 socket server using socket.recv_into() in a non-blocking loop.
  • Windows: Hercules SETUP Utility, Wireshark (diagnosis only), or a small Python / PowerShell socket listener.
  • Excel: VBA macro referencing MSWinSck.OCX / MSComm32.OCX for raw TCP, or using Application.OnTime to schedule a periodic send in a workbook module.

The PC must (a) open the server socket on the configured remote port, (b) accept the S7-1500's connect SYN, and (c) drive the heartbeat send loop at a deterministic interval. If MSComm is used, ensure the OCX is registered and the buffer size ≥ 4096 bytes. For Excel-VBA sockets, the latency of Application.OnTime varies from 50–500 ms depending on macro security settings, so use a Windows service or Python when the heartbeat must be steady at 100–250 ms.

For firewall rules, allow inbound TCP on the configured port. Corporate Windows firewalls frequently default-deny inbound server sockets and produce silent connection refusals that read as State = 16#0006 (pending) on T_DIAG.

Verification, Commissioning, and Field-Tested Procedure

Use the following five-step roll-out for every S7-1500 OUC link to a non-SIMATIC PC:

  1. Layer-1 check — ping the PC from the CPU's Online > Accessible nodes view; confirm a MAC entry appears in the controller's ARP table.
  2. TCP open — once the PC's socket server is running, trigger TCON and verify State = 16#0004 within three cycles.
  3. Bidirectional payload — execute TSEND; verify NDR on TRCV; compare a known byte pattern in Wireshark to confirm there are no fragmentation issues.
  4. Handshake health — start the heartbeat from the PC; observe i_HbCount climb in real time on the controller; unplug the cable and confirm b_LinkOK = FALSE within one heartbeat window.
  5. T_DIAG polling — wait 30 s, fire T_DIAG, confirm ConnFaultsSinceLastSuccess ≥ 1 after the cable event.

If step 2 returns State = 16#0006 persistently, check (a) the PC firewall, (b) the IP subnet / gateway mismatch, (c) any L2 managed switch port blocking the MAC, (d) the partner port being already bound by another process.

If step 4 reports a false negative (i.e. T_DIAG still shows State = 16#0004 after the cable pull), confirm the heartbeat cadence is faster than the TCP keep-alive on both sides, and add a hard timeout in the application such that four missed heartbeats force TCON to re-establish.

CPU 1515SP PC / 1516HF PC note: For software-PLC controllers used as Windows-based controllers, the connection supervision has additional constraints documented under Communication connections to PC stations (S7-300, S7-400, S7-1500) — an existing S7 connection routed by the CPU becomes invalid if the assignment of the interface is changed from SIMATIC PC Station to PC Station. Always commit interface changes as a single download item to avoid stranding live connections.

Edge Cases, Library Variants, and Known Limitations

  • GDS / OUC library version drift. TIA Portal V17 versus V20 ships slightly different OUC libraries; the Result pointer's underlying type (TDiag_StatusExt vs TDiag_Status) changes between releases. Cross-version import can produce type not found errors that are resolved by re-importing the matching library version.
  • Firmware pinning. The connection-fault detection timer in the S7-1500 OS is firmware-dependent; a CPU at firmware V2.9 behaves differently from V3.0. Read the firmware release notes that ship with the controller and check the Communication or Open User Communication sections.
  • Multiple CPUs behind one PC. If a single PC terminates multiple S7-1500 connections, assign distinct remote ports per connection; do not rely on IP-only demultiplexing when the PC is multi-homed.
  • Symmetric vs asymmetric keep-alive. TCP keep-alive, when enabled in the firmware, can be set per connection. Match values between the controllers and the PC side to avoid asymmetry in fault-detection latency.
  • OPC UA alternative. For new projects where the PC supervisor can speak OPC UA, replacing the raw TCP+OUC model with the S7-1500's built-in OPC UA server simplifies monitoring (the OPC UA Server interface exposes connection state as items) and reduces error-handling code. See the SIMATIC S7-1500 OPC UA Server manual for the published interface.
  • S7-1500R/H redundant pair. In a redundant pair, both CPUs maintain the connection; only the active one terminates the socket; the standby reports State = 16#0002 LISTENING. The supervisor must distinguish standby healthy from fault using role-status tags.
  • VPN / routed paths. Across routed paths the TCP keep-alive response can take > 30 s, exacerbating the cable-disconnect detection gap. Application-layer heartbeat is the only practical means of low-latency link supervision over routed or VPN paths.
  • Layer 3 ACLs. Some plant networks run inbound packet inspectors that intercept unsolicited SYNs and silently drop them. Symptom: State permanently sits at 16#0006 with ConnTrialsFaults incrementing. The fix is to ACL-bypass the controller's IP on the inspector or move to TCP allowed only between the partner pair.

Frequently Asked Questions

Why does T_DIAG still return State = 16#0004 after I unplug the Ethernet cable?

The TCP socket remains in ESTABLISHED state until the OS retransmit timer expires; the S7-1500's keep-alive default is several minutes. Add an application-layer handshake at 100–250 ms cadence to detect the fault faster than the TCP layer.

How do I type TDiag_StatusExt manually when TIA Portal cannot find it?

Open Options > Global Libraries and import the Open User Communication library shipped with your TIA Portal version; the type is registered in the project. If the import still fails, enter TDiag_StatusExt verbatim into the DB field's data-type column.

What is the minimum heartbeat interval recommended for an S7-1500 OUC link to a PC?

100 ms at the PLC cycle is a safe minimum. Below 50 ms, TRCV busy handling can saturate OB1; above 250 ms the heartbeat window opens long enough to miss an unplug event before the next cycle ends.

Can I poll T_DIAG every scan to get fast fault detection?

Yes, but the State field still lags physical faults by the TCP retransmit window (typically 30 s). Polling faster than the OS retransmit window wastes CPU cycles without improving detection. Use T_DIAG on a 5–30 s cadence and the application handshake for sub-second fault detection.

Is there a TIA Portal setting to lower the TCP keep-alive time on the S7-1500?

CPU firmware V3.0 and newer expose TCP keep-alive parameters under the connection's advanced properties. For firmware V2.x or older, application-layer heartbeat is the only practical means of low-latency link supervision.

My T_DIAG Result pointer compiles only when I type the type name; is that permanent?

No. After the type is recognised once by manual entry, recompile and re-import the Open User Communication global library; subsequent DBs will find TDiag_StatusExt in the picker and the manual workaround can be removed.

Back to blog