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.
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_CandTRCV_Cblocks handle the connection lifecycle automatically. Recommended for simple poll/response or unsolicited scan-and-send scenarios. -
Modular path:
TCON,TDISCON,TSEND,TRCVindividually 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_Cinstruction set. - For legacy CPU firmware V4.0 or V4.1, ensure the latest HSP (Hardware Support Package) is installed; some
STATUSword layouts differ.
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_Ccan act as active partner. -
Passive partner - the scanner opens the socket to the PLC's listening port.
TRCV_CwithActiveEstablished = FALSEon the connection DB makes the PLC passive.
4. Hardware Configuration in TIA Portal
- Add the S7-1214C to the project. If your exact article number isn't visible, use the HSP.
- 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.
- 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.
- 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.
- Compile and download hardware configuration.
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
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
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.
- Connect a PC directly to the scanner with an Ethernet cable (or via a small switch).
- Configure the PC's NIC to a static address in the same subnet, e.g., 192.168.0.100 / 255.255.255.0.
- Open Hercules > TCP Client tab. Set Host IP = 192.168.0.10, Port = 9004. Click Connect.
- Click Send with the ASCII string
LON(or the equivalent trigger command from the scanner manual). - The scanner returns the barcode (or a NAK if no code is in view). Verify character set, terminator, and length.
- 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.
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
DONEflag 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
BUSYpersists across OB invocations and the call must remain in the same priority class. -
Firmware mismatch: S7-1200 firmware V4.0 introduced new
STATUScodes (e.g., 16#80C3 for resource exhaustion). V4.2 addedTUSEND/TURCV. OlderSTATUSreference 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_SERVICEandOB1_PI_STARTin 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
DONEtransitions.
13. Complete Commissioning Checklist
- Verify scanner IP and subnet with a laptop ping.
- Verify scanner port with Hercules (open a TCP socket and read reply).
- Compile hardware config in TIA Portal; download to PLC.
- Insert
TSEND_C/TRCV_Cwith connection ID = 1, partner IP, partner port. - Set
CONT := TRUEon both blocks. - Trigger a send from a watch table forcing
i_SendReq; observew_TSendStatus= 16#0000 afterDONE. - Trigger a scan physically; observe
w_RcvLen= expected length ands_RcvBufcontents in the watch table. - Convert
s_RcvBufto a STRING tag and display on HMI. - Add reconnection logic if production cannot tolerate manual intervention.
- Run the line for 30 minutes; verify no
STATUScodes other than 16#0000/16#7000/16#7001 appear in the diagnostic buffer.
14. References and Further Reading
- SIMATIC S7-1200 Programmable Controller - System Manual (chapter "Communication / Open User Communication")
- SIMATIC S7-1200 / S7-1500 - Open User Communication - Function Manual
- Communication with S7-1200 / S7-1500 - Programming and Operating Manual
- Keyence SR-1000 / SR-2000 Series Barcode Reader Communication Manual (catalog no. SR-1000 / SR-2000) - search the vendor site for the specific model's "Communication (Ethernet) Manual"
- Keyence BL-1300 Series Barcode Reader - Communication Manual
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.