Beckhoff TwinCAT TF6310 enables the implementation of one or more TCP/IP
server/clients in the TwinCAT PLC.There are two main parts in this function:
- PLC library: Tc2_TcpIp library (basic TCP/IP and UDP/IP function)
- Background program: TwinCAT TCP/IP Connection Server
And in this tutorial I will show you how to implement a TCP/IP Client in TwinCAT by using this TF6310 and communicate to a TCP/IP Server that is made by python.
Let’s start!
System Requirment
Installation
Access the below link to download the installation file.
Choose your langeuage.
Next>
Aggree the license.
Enter your information.
Complete>Next>.
Next>
Press install.
Please wait a minute..
Done!
You can find the TF6310-TCP-IP in this directory.
Adding Library
Reference>Add Library.
Search FB_Socket or Tc2_TcpIP to add the library to your project.
Function Block
FB_SocketConnect
We can use this Function Block to establish a new TCP/IP connection to a
remote server via the TwinCAT TCP/IP Connection Server.
The hSocket is outputted while Connection is established and this handle is used in the FB_SocketSend(),FB_SocketReceive(), FB_SocketClose().
IP Connection Server automatically assigns a new IP port number for each client.
VAR_INPUT
Name | Type | Description |
sSrvNetId | T_AmsNetId := ”; | String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’ |
sRemoteHost | T_IPv4Addr := ”; | The IP Address of the Server |
nRemotePort | UDINT | The port number of the server |
bExecute | BOOL | Activated by a positive edge |
tTimeout | TIME := T#45s;(*!!!*) | Maximum for the execution of the Function Block |
VAR_OUTPUT
Name | Type | Description |
bBusy | BOOL | 1=FB is activated and remains unit acknowledgement from server |
bError | BOOL | 1=Error |
nErrId | UDINT | The Error information if bError=1 |
hSocket | T_HSOCKET | The TCP/IP Connection handle |
FB_SocketClose
We can use this function block to close an TCP/IP or UDP socket connection.
VAR_INPUT
Name | Type | Description |
sSrvNetId | T_AmsNetId := ”; | String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’ |
hSocket | T_HSOCKET | The TCP/IP Connection handle |
bExecute | BOOL | Activated by a positive edge |
tTimeout | TIME := T#5s; | Maximum for the execution of the Function Block |
VAR_OUTPUT
Name | Type | Description |
bBusy | BOOL | 1=FB is activated and remains unit acknowledgement from server |
bError | BOOL | 1=Error |
nErrId | UDINT | The Error information if bError=1 |
FB_SocketSend
We can use this function block to send the packages to a remote server.
VAR_INPUT
Name | Type | Description |
sSrvNetId | T_AmsNetId := ”; | String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’ |
hSocket | T_HSOCKET | The TCP/IP Connection handle |
cbLen | UDINT | Number of data to be send in bytes |
pSrc | POINTER TO BYTE | Address (pointer) of the send buffer |
bExecute | BOOL | Activated by a positive edge |
tTimeout | TIME := T#5s; | Maximum for the execution of the Function Block |
VAR_OUTPUT
Name | Type | Description |
bBusy | BOOL | 1=FB is activated and remains unit acknowledgement from server |
bError | BOOL | 1=Error |
nErrId | UDINT | The Error information if bError=1 |
FB_SocketReceive
We can use this Function block to receive the data from the server.Because the bExecute is detected as a rise edge, It should be better to call this block every 100ms and util all your data are received. The Bytes that are received ,output as nRecBytes.
VAR_INPUT
Name | Type | Description |
sSrvNetId | T_AmsNetId := ”; | String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’ |
hSocket | T_HSOCKET | The TCP/IP Connection handle |
cbLen | UDINT | Number of data to be send in bytes |
pSrc | POINTER TO BYTE | Address (pointer) of the send buffer |
bExecute | BOOL | Activated by a positive edge |
tTimeout | TIME := T#5s; | Maximum for the execution of the Function Block |
VAR_OUTPUT
Name | Type | Description |
bBusy | BOOL | 1=FB is activated and remains unit acknowledgement from server |
bError | BOOL | 1=Error |
nErrId | UDINT | The Error information if bError=1 |
nReceBytes | UDINT | The Bytes that received from server |
FB_ClientServerConnection
We can use this function block to manage the client to server connection by TwinCAT.
FB_SocketOpen and FB_SocketClose are included inside and you do not need to call these by yourself.
The integrated debugging output of the connection status facilitates troubleshooting in the event of configuration or communication errors – eState is variable to output the current connection status and nErrorID will output the current error.
After the Connection is established, we only need to care about the FB_SocketSenda and FB_SocketReceive.
It is a very covenant communication block.
VAR_INPUT
Name | Type | Description |
sSrvNetId | T_AmsNetId := ”; | String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’ |
nMode | DWORD:= 0; | Parameters Flag |
sRemoteHost | T_IPv4Addr := ”; | The IP Address of the Server |
nRemotePort | UDINT | The port number of the server |
bEnable | BOOL | As long as True, TwinCAT will try to establish a connection until successfully. |
tReconnect | TIME := T#45s;(*!!!*) | The Time for Connection establishment retry. |
VAR_OUTPUT
Name | Type | Description |
bBusy | BOOL | 1=FB is activated and remains unit acknowledgement from server |
bError | BOOL | 1=Error |
nErrId | UDINT | The Error information if bError=1 |
hSocket | T_HSOCKET | The TCP/IP Connection handle |
eState | E_SocketConnectionState := eSOCKET_DISCONNECTED; | Return the current connection status. |
Error: 1828
There is a missing license problem if Error of 1828 is displayed.
Go to SYSTEM>License.
Open the Manage License Tab> choose T6310>Add License.
Trial License is added.
Cick the 7 Daus Trial Licnese.
Enter the magic Code.
License file is generated!
Now you can download the configuration to your runtime again!
Data type
T_HSOCKET
It is the variable for representing a connection handle or a handle of an open socket. We can use this socket handle to open/close/send/receive operations.
E_SocketConnectionState
A data type to show the current status of the TCP/IP Connection.
TYPE E_SocketConnectionState: ( eSOCKET_DISCONNECTED, eSOCKET_CONNECTED, eSOCKET_SUSPENDED ); END_TYPE |
Server with Python
I build a Simple server and client by using python first, and make sure my python server is working.
Server Side
Server will wait for the connection from any client and return the message that was sent from the client.
import socket HOST = “127.0.0.1” PORT = 65432 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f”Connected by {addr}”) while True: data = conn.recv(1024) if not data: break conn.sendall(data) |
Client Side
connect to a local server and send a “Hello world” text.
import socket HOST = “127.0.0.1” PORT = 65432 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((HOST, PORT)) s.sendall(b”Hello, world”) data = s.recv(1024) print(f”Received {data!r}”) |
Result-Server
Connected by (‘127.0.0.1’, 51649) |
Result-Client
Received b’Hello, world’ |
Play with TwinCAT
The python server is working and we can connect it with TwinCAT TF6310 TCP/IP.
SocketConnect/Close
Program1 – Let’s check if the TwinCAT TCP/IP Client can connect to the server or not.
Program
pou001_Connect2PythonServer
VAR
PROGRAM pou001_Connect2PythonServerVAR SocketConnect :FB_SocketConnect; SocketClose :FB_SocketClose; hSocket :T_HSOCKET; bConnect :BOOL; bClose :BOOL;END_VAR |
Code
SocketConnect( sRemoteHost:=’127.0.0.1′ ,nRemotePort:=65432 ,bExecute:=bConnect ,hSocket=>hSocket ); IF bConnect AND (NOT SocketConnect.bBusy OR SocketConnect.bError)THEN bConnect:=FALSE; END_IF SocketClose( hSocket:=hSocket ); IF bClose THEN bClose:=FALSE; END_IF |
Result-TwinCAT Side
The socket handle from hsocket – we can see the client address and the pot number are assigned.
Result-Python Server Side
And Also server side is received the connection from the client.
Connected by (‘127.0.0.1’, 51665) |
Send/Receive the Data
Good, Now we can try to send/receive the data.
Modify the Python server
Let’s try to modify the python TCP/IP Server to be more easy to know if the message is received or not.
import socket HOST = “127.0.0.1” PORT = 65432 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print(f”Connected by {addr}”) while True: data = conn.recv(1024) if not data: break print(“data from client:”.encode()+data) conn.sendall(data+”,Data back from Server”.encode()) |
Porgram
pou002_SendReceiveData2PythonServer
VAR
PROGRAM pou002_SendReceiveData2PythonServer VAR SocketConnect :FB_SocketConnect; SocketClose :FB_SocketClose; SocketSend :FB_SocketSend; SocketReceive :FB_SocketReceive; hSocket :T_HSOCKET; bConnect :BOOL; bClose :BOOL; bSend :BOOL; bReceive :BOOL; TON :TON; tRefleshTime :TIME:=T#100MS; SendBytes :ARRAY[0..1023]OF BYTE; ReceiveByte :ARRAY[0..1023]OF BYTE; stSendString :STRING; SendLen :UDINT; stReceiveString :STRING; R_TRIG_ByteReceived :R_TRIG; END_VAR |
Code
//Establish the connection to Python Server SocketConnect( sRemoteHost:=’127.0.0.1′ ,nRemotePort:=65432 ,bExecute:=bConnect ,hSocket=>hSocket ); IF bConnect AND (NOT SocketConnect.bBusy OR SocketConnect.bError)THEN bConnect:=FALSE; END_IF //Send message to Python Server //Configure the Sending message stSendString:=’Hello world from TwinCAT!’; SendLen:=LEN(stSendString); //Copy MEMCPY( destAddr:=ADR(SendBytes) ,srcAddr:=ADR(stSendString) ,n:=SendLen ); //Function Block SocketSend( hSocket:=hSocket ,cbLen:=SendLen ,pSrc:=ADR(SendBytes) ,bExecute:=bSend ); IF bSend AND (NOT SocketSend.bBusy OR SocketSend.bError) THEN bSend:=FALSE; END_IF //Receive message from Python Server //Reflesh Timer TON( IN:=NOT TON.Q ,PT:=tRefleshTime ); //Function Block SocketReceive( hSocket:=hSocket ,cbLen:=SIZEOF(ReceiveByte) ,pDest:=ADR(ReceiveByte) ,bExecute:=NOT TON.Q ); //If bytes are received R_TRIG_ByteReceived( CLK:=SocketReceive.nRecBytes > 0 ); IF R_TRIG_ByteReceived.Q THEN MEMCPY( destAddr:=ADR(stReceiveString) ,srcAddr:=ADR(ReceiveByte) ,n:=SocketReceive.nRecBytes ); END_IF //Close the Connection //Function Block SocketClose( hSocket:=hSocket ); IF bClose OR SocketSend.bError OR SocketReceive.bError THEN bClose:=FALSE; END_IF |
Result-TwinCAT Side
Data sent and received the correct response from the server!
Result-Python Server Side
Connected by (‘127.0.0.1’, 63751) b’data from client:Hello world from TwinCAT!’ b’data from client:Hello world from TwinCAT!’ |
Bonus-Use Connection Helper
Finally, here is the Bonus to implement the same logic, but uses the FB_ClientServerConnection Helper function block.
Program
pou003_UsingConnectionHelper
VAR
PROGRAM pou003_UsingConnectionHelper VAR RemoteServer :FB_ClientServerConnection; SocketSend :FB_SocketSend; SocketReceive :FB_SocketReceive; hSocket :T_HSOCKET; bConnect :BOOL; bClose :BOOL; bSend :BOOL; bReceive :BOOL; TON :TON; tRefleshTime :TIME:=T#100MS; SendBytes :ARRAY[0..1023]OF BYTE; ReceiveByte :ARRAY[0..1023]OF BYTE; stSendString :STRING; SendLen :UDINT; stReceiveString :STRING(255); R_TRIG_ByteReceived :R_TRIG; R_TRIG_SendFlag :R_TRIG; CopiedBytes:UDINT; counter:INT; i:INT; END_VAR |
Code
//Establish the connection to Python Server RemoteServer( sRemoteHost:=’127.0.0.1′ ,nRemotePort:=61000 ,bEnable:=bConnect ,hSocket=>hSocket ); R_TRIG_SendFlag( CLK:=RemoteServer.eState = eSOCKET_CONNECTED ); IF R_TRIG_SendFlag.Q THEN bSend:=TRUE; END_IF //Send message to Python Server //Configure the Sending message stSendString:=’Hello world from TwinCAT TF6310!’; SendLen:=LEN(stSendString); //Copy MEMCPY( destAddr:=ADR(SendBytes) ,srcAddr:=ADR(stSendString) ,n:=SendLen ); //Function Block SocketSend( hSocket:=hSocket ,cbLen:=SendLen ,pSrc:=ADR(SendBytes) ,bExecute:=bSend ); IF bSend AND (NOT SocketSend.bBusy OR SocketSend.bError) THEN FOR i:=0 TO 1023 DO ReceiveByte[i]:=16#00; END_FOR stReceiveString:=’ ‘; bSend:=FALSE; IF NOT SocketSend.bError THEN bReceive:=TRUE; END_IF END_IF //Receive message from Python Server //Reflesh Timer TON( IN:=NOT TON.Q ,PT:=tRefleshTime ); //Function Block SocketReceive( hSocket:=hSocket ,cbLen:=SIZEOF(ReceiveByte) ,pDest:=ADR(ReceiveByte) ,bExecute:=NOT TON.Q AND bReceive ); //If bytes are received R_TRIG_ByteReceived( CLK:=SocketReceive.nRecBytes > 0 ); IF R_TRIG_ByteReceived.Q THEN CopiedBytes:=MEMCPY( destAddr:=ADR(stReceiveString) ,srcAddr:=ADR(ReceiveByte) ,n:=SocketReceive.nRecBytes ); counter:=counter+1; bReceive:=FALSE; bSend:=TRUE; END_IF IF SocketReceive.bError THEN bReceive:=FALSE; END_IF |
Result-TwinCAT Side
we can get the same result!
Result-Python Server Side
Connected by (‘127.0.0.1’, 64176) b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ b’data from client:Hello world from TwinCAT TF6310!’ |
Source Code
https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project_TF6310_Sample_PythonServer.zip