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_DIAGright 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:
- 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\nor a 4-byte big-endian counter. - The S7-1500 cyclically triggers
TRCVwith the same Connection ID.TRCVdelivers the frame into a receive buffer;NDRtoggles when new bytes are present. - The application parses the frame, increments a rolling counter, and increments a heartbeats received since last scan counter.
- 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
TCONto 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 usingsocket.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.OCXfor raw TCP, or usingApplication.OnTimeto 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:
- 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.
-
TCP open — once the PC's socket server is running, trigger
TCONand verifyState = 16#0004within three cycles. -
Bidirectional payload — execute
TSEND; verifyNDRonTRCV; compare a known byte pattern in Wireshark to confirm there are no fragmentation issues. -
Handshake health — start the heartbeat from the PC; observe
i_HbCountclimb in real time on the controller; unplug the cable and confirmb_LinkOK = FALSEwithin one heartbeat window. -
T_DIAG polling — wait 30 s, fire
T_DIAG, confirmConnFaultsSinceLastSuccess ≥ 1after 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.
Edge Cases, Library Variants, and Known Limitations
-
GDS / OUC library version drift. TIA Portal V17 versus V20 ships slightly different OUC libraries; the
Resultpointer's underlying type (TDiag_StatusExtvsTDiag_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#0002LISTENING. 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:
Statepermanently sits at16#0006withConnTrialsFaultsincrementing. 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.