Keyence Barcode Scanner S7-1200 TCP/IP Communication via OUC

David Krause17 min read
S7-1200SiemensTutorial / How-to
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

Configuring Keyence Barcode Scanner TCP/IP Communication with Siemens S7-1200 via Open User Communication (OUC)

The Siemens SIMATIC S7-1200 (CPU 1214C, firmware V4.x) communicates with Keyence barcode scanners that expose a generic TCP/IP socket interface but do not support PROFINET. Communication is implemented using Open User Communication (OUC), a set of native TCP/UDP instructions in the S7-1200 instruction set. This article provides a full engineering procedure from hardware wiring through TIA Portal configuration, sample code for both instruction variants (TSEND_C/TRCV_C and the modular TCON/TSEND/TRCV/TDISCON family), scanner-side settings, bench testing with a PC utility, and a troubleshooting matrix keyed to the OUC STATUS error codes returned by the blocks.

Field note: Before wiring the PLC to the scanner, replicate the scanner's TCP behavior on a laptop with a free utility such as Hercules SETUP utility. Send and receive the actual scanner frames first; that quickly exposes the byte order, framing, terminator, and whether the scanner expects a poll request or spontaneously transmits on trigger.

1. Overview of Open User Communication on the S7-1200

Open User Communication is the term Siemens uses for connection-oriented (TCP) and connectionless (UDP) socket programming on S7-1200 and S7-1500 CPUs. The instructions live in the Communication palette of the TIA Portal program editor:

Instruction Function Typical Use
TCON Establishes a TCP/UDP connection Handled implicitly by TSEND_C/TRCV_C; explicit for advanced lifecycle control
TDISCON Terminates an active connection Releases connection resources on shutdown/error
TSEND Sends a defined data area Free-form telegram, no auto-receive
TRCV Receives data into a defined area Free-form telegram, requires TCON to be active
TSEND_C Combined connect + send Compact transmit with implicit TCON
TRCV_C Combined connect + receive Compact receive with implicit TCON
TUSEND/TURCV UDP send/receive Connectionless transport (not used here)

Two implementation paths are available:

  • Compact path: TSEND_C and TRCV_C blocks handle the connection lifecycle automatically. Recommended for simple poll/response or unsolicited scan-and-send scenarios.
  • Modular path: TCON, TDISCON, TSEND, TRCV individually controlled. Required when you need asymmetric logic (e.g., only listen, or send only when data is received, or run multiple scanners over separate connection IDs).

2. Prerequisites

2.1 Hardware

Item Minimum / Recommended
CPU S7-1214C DC/DC/DC or DC/DC/RLY (6ES7214-1AE40-0XB0 or later). Any S7-1200 with firmware V4.0 or higher is supported.
Ethernet port Onboard PROFINET interface of the S7-1200 (X1)
Keyence scanner SR-1000 series, SR-2000 series, SR-D100 series, BL-1300 series, or any model exposing TCP/IP socket mode (verify catalog no. in scanner manual)
Cabling Cat 5e or better, RJ45, crossover not required for modern auto-MDIX scanners
Network Same subnet (e.g., PLC 192.168.0.1 / scanner 192.168.0.10, mask 255.255.255.0). Direct cross-over or a small switch both work.
Engineering station PC with TIA Portal V15.1 or later; recommended V17/V18 for the most recent CPU firmware

2.2 Firmware & Software

  • TIA Portal V15.1 or higher (V16, V17, V18 all supported). CPU firmware V4.2 to V4.6 (current production) all support the full TSEND_C/TRCV_C instruction set.
  • For legacy CPU firmware V4.0 or V4.1, ensure the latest HSP (Hardware Support Package) is installed; some STATUS word layouts differ.
Always cross-check the CPU's article number and firmware against the Siemens Industry Online Support portal before commissioning. The instruction TSEND_C was extended (added BUSY semantics for V4.0); older manuals describe a different STATUS mapping.

3. S7-1200 Communication Resources and Limits

Every active OUC connection consumes one entry from the CPU's connection resource table. The S7-1214C supports a fixed number of Open User Communication connections. Consult SIMATIC S7-1200 Programmable Controller - System Manual, chapter "Communication" for exact figures per CPU article number. Typical values:

Resource S7-1214C Effect
Max OUC connections (total) Up to 8 active + 8 passive, depending on firmware Each scanner consumes 1 active connection (PLC side initiates) or 1 passive (scanner initiates)
Max connections per instruction type Connection IDs 1..4095 (with TSAP for ISO-on-TCP, port for TCP) Pick a unique connection ID per scanner
TCP send buffer (default) 8192 bytes per call (max 8192) Keyence telegrams are well under 1 KB; default is fine
Receive length (TRCV) 1..8192 bytes Limit to expected payload + terminator length

Two common connection roles exist:

  • Active partner - the PLC opens the socket to the scanner's listening port (typical). TSEND_C/TRCV_C can act as active partner.
  • Passive partner - the scanner opens the socket to the PLC's listening port. TRCV_C with ActiveEstablished = FALSE on the connection DB makes the PLC passive.

4. Hardware Configuration in TIA Portal

  1. Add the S7-1214C to the project. If your exact article number isn't visible, use the HSP.
  2. Open Device View > CPU > PROFINET interface [X1]. Set the PLC IP address (e.g., 192.168.0.1) and subnet mask (255.255.255.0). Disable the PROFINET device name since OUC uses IP only.
  3. Add the Keyence scanner as a Unspecified Device or as a vendor-specific IO module is not required. You only need its IP address and TCP port.
  4. Open CPU Properties > Communication and verify that no IP access list rule is blocking the scanner IP. For LAN-only setups, leave the access list empty or allow the scanner's IP.
  5. Compile and download hardware configuration.
Profinet vs. Ethernet: The X1 port serves both PROFINET (RT/IRT) and standard TCP/IP simultaneously. OUC does not conflict with PROFINET IO traffic; both can run on the same physical port.

5. PLC Tag Declaration

Create a global data block "DB_OUC_Keyence" with the following tags. Names are illustrative; match your site's naming convention.

Tag Type Initial value Purpose
i_SendReq Bool FALSE Rising edge triggers a TSEND_C send
i_RcvReq Bool FALSE Rising edge triggers TRCV_C to enable receive
o_TSendDone Bool - Mirror of TSEND_C.DONE
o_TRcvDone Bool - Mirror of TRCV_C.DONE
o_TRcvError Bool - Mirror of TRCV_C.ERROR
w_TSendStatus Word 16#0000 Mirror of TSEND_C.STATUS
w_TRcvStatus Word 16#0000 Mirror of TRCV_C.STATUS
w_TRcvLen Word 16#0000 Mirror of TRCV_C.RCVD_LEN (length actually received)
s_SendBuf Array[0..255] of Byte - Outgoing telegram buffer (poll command)
s_RcvBuf Array[0..511] of Byte - Incoming telegram buffer
s_Barcode String[80] '' Decoded barcode string
w_ConnID Word 16#0001 Connection ID 1

6. Compact Path - TSEND_C and TRCV_C Implementation

6.1 Adding the Blocks

From Instructions > Communication > Open User Communication, drag TSEND_C and TRCV_C into OB1 (or a cyclic OB). TIA Portal will auto-create a connection description DB (e.g., TCON_1_DB) for each instance.

6.2 Connection Configuration (TSEND_C)

Click on the TSEND_C instance and open the Properties > Configuration > Connection tab. Specify:

Parameter Value (example) Note
Connection type TCP ISO-on-TCP is also valid but adds a 4-byte TPDU header; use raw TCP for scanner
Connection ID 1 Must match the receiving block or use the same DB for both
Local port 2000 (or 0 = any) If 0, system assigns a free port
Partner IP 192.168.0.10 Keyence scanner IP
Partner port 9004 Confirm with scanner manual (SR-1000 default = 9004, SR-2000 default = 9004, BL-1300 default = 9100)
Active connection establishment TRUE PLC initiates the socket

6.3 Ladder Example - Trigger + Send

Network 1: Build poll command and request send
      i_SendReq     o_TSendDone
    --|P|--[CALL TSEND_C, DB_TSEND_C]--( )
                       REQ := i_SendReq
                       CONT := TRUE          // keep connection up between calls
                       LEN  := 6             // length of poll command (see scanner doc)
                       DATA := s_SendBuf     // pointer to send buffer
                       DONE => o_TSendDone
                       BUSY => o_TSendBusy
                       ERROR => o_TSendError
                       STATUS => w_TSendStatus
                       CONNECT => o_ConnEstablished

The poll command for many Keyence scanners is a short ASCII string, for example <CR>LON<CR> (6 bytes) or LON\r depending on firmware. Verify the exact byte sequence and terminating characters against the scanner's communication manual before testing.

6.4 Receive Side (TRCV_C)

Network 2: Continuous receive
      i_RcvReq      o_ConnEstablished
    --|P|--[CALL TRCV_C, DB_TRCV_C]--( )
                       EN_R   := TRUE       // receive enable
                       CONT   := TRUE
                       LEN    := 0          // 0 = use ADHOC length mode (any length)
                       DATA   := s_RcvBuf
                       DONE   => o_TRcvDone
                       BUSY   => o_TRcvBusy
                       ERROR  => o_TRcvError
                       STATUS => w_TRcvStatus
                       RCVD_LEN => w_TRcvLen
ADHOC mode (LEN=0): When LEN=0, TRCV_C returns as soon as the partner closes the half-duplex or sends a single TCP segment. For scan-and-send scanners that transmit a fixed-length ASCII telegram (e.g., "ABCD1234\r\n"), set LEN explicitly to 10 and call TRCV_C after each scan. For trigger-style scanners, leave EN_R=TRUE continuously and read DONE to detect new data.

6.5 Sample Code - SCL Variant

// Block: FC_OUC_Scan
// Purpose: Send LON poll, wait for barcode reply, copy to string

#iBusy := FALSE;
IF #iSendReq AND NOT #oTsendDone THEN
    "TSEND_C_DB"(REQ := #iSendReq,
                CONT := TRUE,
                LEN  := #iSendLen,
                DATA := #sSendBuf,
                DONE => #oTsendDone,
                BUSY => #oTsendBusy,
                ERROR => #oTsendError,
                STATUS => #wTsendStatus);
END_IF;

IF #oTsendDone OR #oConnEstablished THEN
    "TRCV_C_DB"(EN_R := TRUE,
                CONT := TRUE,
                LEN  := 0,
                DATA := #sRcvBuf,
                DONE => #oRcvDone,
                BUSY => #oRcvBusy,
                ERROR => #oRcvError,
                STATUS => #wRcvStatus,
                RCVD_LEN => #wRcvLen);
END_IF;

// On rising edge of oRcvDone, copy received bytes into barcode string
IF #oRcvDone THEN
    // s_Barcode := CHAR_ARRAY_TO_STRING(LEFT(s_RcvBuf, w_RcvLen));
    // Use Siemens BLKMOV or CHAR_CONV per your code style
END_IF;

7. Modular Path - TCON, TSEND, TRCV, TDISCON

When you need precise control (e.g., separate polling cycle, multiple scanners, dynamic reconnection after fault), use the modular instructions. Each block is a separate instance DB.

7.1 Network Diagram

S7-1214C (PLC) OB1 cyclic TCON (ID=1) TSEND TRCV TDISCON (on error) Keyence Scanner TCP Server Port 9004 IP 192.168.0.10 Telegram: STX..ETX TCP/IP socket

7.2 Connection Description DB (parameter record)

You can either let TIA Portal create the connection description (right-click the TCON instance) or create one manually with the following structure. The connection description is the TCON_Param area of the TCON instance DB.

// Structure: TCON_Param (16 bytes header + parameter data)
// TIA Portal auto-generates this from the Configuration tab of TCON.

// Manual specification for TCON_PARAM (compact form):
{
  BlockLength    := 64;
  Id             := 1;                 // Connection ID
  ConnectionType := 16#0B;            // 0x0B = TCP (16#0C = ISO-on-TCP, 0x0D = UDP)
  ActiveEstablished := TRUE;          // PLC is active partner
  RemoteAddress   := 192.168.0.10;     // Scanner IP
  RemotePort      := 9004;             // Scanner TCP port
  LocalPort       := 0;                // 0 = let system assign
}

7.3 Call Sequence

// Network 1 - TCON on startup or after error
IF i_ConnectReq AND NOT o_ConnEstablished THEN
    "TCON_DB"(REQ   := TRUE,
              ID    := 1,
              DONE  => o_TconDone,
              BUSY  => o_TconBusy,
              ERROR => o_TconError,
              STATUS=> w_TconStatus);
END_IF;

// Network 2 - TSEND after a successful connect
IF o_ConnEstablished AND i_SendReq AND NOT o_TsendBusy THEN
    "TSEND_DB"(REQ   := i_SendReq,
               ID    := 1,
               LEN   := i_SendLen,
               DATA  := s_SendBuf,
               DONE  => o_TsendDone,
               BUSY  => o_TsendBusy,
               ERROR => o_TsendError,
               STATUS=> w_TsendStatus);
END_IF;

// Network 3 - TRCV always enabled when connected
IF o_ConnEstablished THEN
    "TRCV_DB"(EN_R  := TRUE,
              ID    := 1,
              LEN   := 0,
              DATA  := s_RcvBuf,
              DONE  => o_RcvDone,
              BUSY  => o_RcvBusy,
              ERROR => o_RcvError,
              STATUS=> w_RcvStatus,
              RCVD_LEN=> w_RcvLen);
END_IF;

// Network 4 - TDISCON on fatal error
IF o_TconError OR o_RcvError OR i_DisconnectReq THEN
    "TDISCON_DB"(REQ := TRUE,
                 ID  := 1,
                 DONE=> o_DisconDone,
                 BUSY=> o_DisconBusy,
                 ERROR=> o_DisconError,
                 STATUS=> w_DisconStatus);
END_IF;

8. Keyence Scanner-Side TCP/IP Configuration

Use the scanner's web interface or Keyence's AutoID Network Navigator tool to set the following. Defaults vary by model; verify against the scanner manual:

Parameter Typical default Action
IP address 192.168.0.10 (SR series), 192.168.100.101 (some BL) Set to a static IP reachable from the PLC
Subnet mask 255.255.255.0 Match PLC subnet
Default gateway 0.0.0.0 Leave 0 unless routing required
Communication mode TCP Server / TCP Client For PLC-active topology: set scanner to TCP Server, PLC opens the socket
Port 9004 (SR-1000/2000), 9100 (BL-1300), 8004 (SR-D100) Record the actual port in the connection description DB
Trigger source Serial / Ethernet / Discrete For Ethernet trigger, send an LON command from the PLC
Data terminator CR / CRLF / None Match the PLC's TRCV expected length or use ADHOC mode
Header / footer bytes STX..ETX (some models) If present, include them in length or strip in PLC code

9. Bench Testing with Hercules SETUP Utility

Before touching the PLC, prove the scanner's protocol with a PC. Hercules SETUP utility is a free TCP/UDP test client widely used in industrial commissioning.

  1. Connect a PC directly to the scanner with an Ethernet cable (or via a small switch).
  2. Configure the PC's NIC to a static address in the same subnet, e.g., 192.168.0.100 / 255.255.255.0.
  3. Open Hercules > TCP Client tab. Set Host IP = 192.168.0.10, Port = 9004. Click Connect.
  4. Click Send with the ASCII string LON (or the equivalent trigger command from the scanner manual).
  5. The scanner returns the barcode (or a NAK if no code is in view). Verify character set, terminator, and length.
  6. Repeat with the scanner's native configuration tool (AutoID Network Navigator or similar) to confirm framing before adapting to the PLC.

Once you have a known-good ASCII (or binary) frame, mirror it exactly in the PLC's s_SendBuf and validate s_RcvBuf against the same length.

Watch for byte order: Some Keyence models return data in little-endian binary if configured for binary protocol. With TCP/IP ASCII mode (default), bytes are sent as-is and CHAR interpretation in TIA Portal is straightforward.

10. Verification and Diagnostics

10.1 Online STATUS Word Decoding

Watch the following tags in the watch table:

Tag Healthy state
w_TSendStatus 16#0000 when idle, 16#7000 briefly during run
w_TRcvStatus 16#0000 when idle, 16#7000 while waiting
o_TSendDone Pulses TRUE for one cycle on successful send
o_TRcvDone Pulses TRUE for one cycle when new data received
o_TRcvError Should remain FALSE
w_RcvLen Length of the last successful receive

10.2 Common OUC STATUS Codes (hex)

STATUS Meaning Action
16#0000 Idle / no error No action
16#7000 No job active, instruction idle Normal
16#7001 Job in progress (BUSY) Wait for DONE / ERROR
16#7002 Job queued (will start when current finishes) Normal for back-to-back calls
16#8085 LEN parameter out of range, or connection not established Check LEN and connection ID; verify TCON succeeded
16#8086 Pointer invalid (e.g., DATA points to wrong area) Re-check pointer syntax in DB; ensure symbol is "absolute" access
16#80A1 Connection or port already in use Verify connection ID uniqueness; check partner is not in TIME_WAIT
16#80A3 Connection being terminated Wait; this is transient
16#80A4 IP address of partner invalid or unreachable Ping scanner from a laptop in the same subnet; verify static IP
16#80A7 TCP connection lost (timeout, RST) Check cable, scanner power, firewall; add reconnection logic
16#80B4 Connection terminated locally (TDISCON) Expected if you intentionally disconnect
16#80C3 All connection resources exhausted Reduce number of simultaneous connections or upgrade CPU
16#80C4 Temporary resource error (out of memory) Reduce call rate or upgrade CPU firmware

10.3 Reconnection Logic

A robust pattern wraps every OUC block with auto-reconnect:

// After a TSEND_C or TRCV_C ERROR, drop and re-establish connection
IF o_TsendError OR o_RcvError THEN
    "TDISCON_DB"(REQ := TRUE, ID := 1);
    i_ConnectReq := TRUE;          // retry TCON on next OB1 scan
END_IF;

// Re-arm with a small delay to avoid hot-looping if the partner is offline
IF i_ConnectReq AND NOT o_ConnEstablished THEN
    IF t_RetryTimer.Q = FALSE THEN
        t_RetryTimer(IN := TRUE, PT := T#2S);
    END_IF;
    IF t_RetryTimer.Q THEN
        "TCON_DB"(REQ := TRUE, ID := 1);
    END_IF;
END_IF;

11. Troubleshooting Matrix

Symptom Likely cause Diagnostic step Fix
STATUS = 16#80A4 on first TCON Scanner IP unreachable Ping 192.168.0.10 from PC in same subnet Fix scanner IP, subnet, or cabling
STATUS = 16#80A1 on every cycle Connection ID already in use or wrong DB reused Inspect online block consistency Use unique connection IDs per scanner; recompile all OUC blocks
Send executes (DONE=TRUE) but no data appears at scanner Wrong port or wrong framing Run Hercules from a PC and verify the same command opens the socket Match port; verify ASCII terminator (CR vs CRLF)
Scanner responds, RCVD_LEN = 0 Partner not transmitting Trigger scanner manually; check BUSY on TRCV_C Send correct LON trigger command; check scanner mode is "Ethernet trigger"
Receive is "junk" characters Binary vs ASCII protocol mismatch Capture in Hercules with hex view Switch scanner to ASCII output mode or reinterpret buffer as bytes
Connection drops every few minutes Scanner idle timeout Check scanner's TCP keepalive setting Lower scanner's idle-timeout; send periodic poll or use TCP keepalive
Only first scan after download succeeds CONT = FALSE on the second send Inspect CONT input Set CONT := TRUE to keep connection persistent
Multiple scanners on same PLC - only one works Duplicate connection ID Open each instance DB online Use unique IDs (e.g., 1, 2, 3)
Online status stays at 16#8086 Pointer access wrong (e.g., ARRAY slice not supported) Use variant or P# pointer per Siemens help Restructure buffer as separate Array[*] of Byte DB and pass as P#DB...BYTE...
Slow response (multi-second latency) Scanner in power-save or low-power mode Check scanner LED state Disable power save; verify Ethernet link speed (10/100 Mbps full duplex)

12. Field-Proven Caveats and Performance Notes

  • Trigger latency: A round-trip poll/response between PLC and scanner typically completes in 30-80 ms on a clean 100 Mbps link. The PLC's OB1 cycle must be faster than the scanner's response time or the DONE flag can be missed. OB1 at 10 ms is safe.
  • OB1 vs OB35/OB36: Place OUC blocks in OB1 only. Cyclic interrupt OBs (OB30-OB38) can call OUC, but be aware that BUSY persists across OB invocations and the call must remain in the same priority class.
  • Firmware mismatch: S7-1200 firmware V4.0 introduced new STATUS codes (e.g., 16#80C3 for resource exhaustion). V4.2 added TUSEND/TURCV. Older STATUS reference tables (pre-V4.0) will be missing codes that you will encounter in newer CPUs.
  • Switch selection: Avoid unmanaged industrial switches with embedded IGMP/PTP filtering - they sometimes drop TCP keepalives. Use a managed switch (e.g., Siemens SCALANCE XC-100) when in doubt.
  • Watchdog / cycle time: Receiving many telegrams can briefly extend OB1 cycle time when the receive buffer is large. Monitor OB1_PI_SERVICE and OB1_PI_START in diagnostics.
  • HMI touch points: HMI tags polled at 250 ms for the barcode are typical. Add a "new scan" pulse tag so the HMI can blink a banner when DONE transitions.
Safety note: OUC runs on the same physical port as PROFINET safety (PROFIsafe). Mixing PROFIsafe and OUC traffic on the same port is supported but ensure that the OUC traffic does not saturate the link. Keyence barcode traffic is in the low kbps range and will not interfere with PROFIsafe.

13. Complete Commissioning Checklist

  1. Verify scanner IP and subnet with a laptop ping.
  2. Verify scanner port with Hercules (open a TCP socket and read reply).
  3. Compile hardware config in TIA Portal; download to PLC.
  4. Insert TSEND_C/TRCV_C with connection ID = 1, partner IP, partner port.
  5. Set CONT := TRUE on both blocks.
  6. Trigger a send from a watch table forcing i_SendReq; observe w_TSendStatus = 16#0000 after DONE.
  7. Trigger a scan physically; observe w_RcvLen = expected length and s_RcvBuf contents in the watch table.
  8. Convert s_RcvBuf to a STRING tag and display on HMI.
  9. Add reconnection logic if production cannot tolerate manual intervention.
  10. Run the line for 30 minutes; verify no STATUS codes other than 16#0000/16#7000/16#7001 appear in the diagnostic buffer.

14. References and Further Reading

FAQ

Which instruction set should I start with: TSEND_C/TRCV_C or the modular TCON family?

Start with TSEND_C and TRCV_C for a single-scanner, single-connection setup. The compact blocks hide the connection lifecycle and are easier to debug. Switch to TCON/TSEND/TRCV/TDISCON when you need multiple scanners on the same PLC, custom reconnection logic, or asymmetric send/receive flows.

What is the default TCP port for a Keyence barcode scanner?

Common defaults are port 9004 for SR-1000 / SR-2000 series, 8004 for SR-D100, and 9100 for BL-1300 series. The actual port can be changed via the scanner's web interface or AutoID Network Navigator tool. Always confirm against the model's communication manual before commissioning.

My TRCV never returns DONE even though the scanner is sending data. What is wrong?

Check three things in order: (1) EN_R on TRCV_C must be TRUE continuously in trigger-on-data mode; (2) the connection must be established (CONT := TRUE on the prior TSEND_C); (3) the scanner's terminator (e.g., CR/LF) must match what TRCV_C expects in ADHOC mode. If STATUS stays at 16#7001 (BUSY), the partner is open but not transmitting. Run Hercules on a PC to confirm the scanner actually sends after the LON trigger.

STATUS 16#80A4 appears after a few hours of operation. How do I make the connection auto-recover?

Wrap the OUC blocks with a reconnection routine: on ERROR, call TDISCON then TCON again after a 2-second delay. Place the retry logic in OB1. Use a timer (e.g., IEC_TON) to prevent hot-looping when the partner is offline. This pattern handles cable disconnects and scanner restarts transparently.

Can the S7-1200 connect to more than one barcode scanner over TCP/IP?

Yes. Each scanner needs a unique connection ID (1 through 4095) and a separate pair of instruction instances (or compact pair). The CPU's total OUC connection budget depends on the article number; the S7-1214C typically supports up to 8 active connections. Watch for STATUS 16#80C3 (resources exhausted) if you approach the limit.

Back to blog