Beckhoff#TwinCAT TF6310_Build a TCP Client

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.

https://www.beckhoff.com/en-en/products/automation/twincat/tfxxxx-twincat-3-functions/tf6xxx-tc3-connectivity/tf6310.html

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

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’
sRemoteHostT_IPv4Addr := ”;The IP Address of the Server
nRemotePortUDINTThe port number of the server
bExecuteBOOLActivated by a positive edge
tTimeoutTIME := T#45s;(*!!!*)Maximum for the execution of the Function Block

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FB is activated and remains unit acknowledgement from server
bErrorBOOL1=Error
nErrIdUDINTThe Error information if bError=1
hSocketT_HSOCKETThe TCP/IP Connection handle

FB_SocketClose

We can use this function block to close an TCP/IP or UDP socket connection.

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’
hSocketT_HSOCKETThe TCP/IP Connection handle
bExecuteBOOLActivated by a positive edge
tTimeoutTIME := T#5s;Maximum for the execution of the Function Block

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FB is activated and remains unit acknowledgement from server
bErrorBOOL1=Error
nErrIdUDINTThe Error information if bError=1

FB_SocketSend

We can use this function block to send the packages to a remote server.

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’
hSocketT_HSOCKETThe TCP/IP Connection handle
cbLenUDINTNumber of data to be send in bytes
pSrcPOINTER TO BYTEAddress (pointer) of the send buffer
bExecuteBOOLActivated by a positive edge
tTimeoutTIME := T#5s;Maximum for the execution of the Function Block


VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FB is activated and remains unit acknowledgement from server
bErrorBOOL1=Error
nErrIdUDINTThe 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

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’
hSocketT_HSOCKETThe TCP/IP Connection handle
cbLenUDINTNumber of data to be send in bytes
pSrcPOINTER TO BYTEAddress (pointer) of the send buffer
bExecuteBOOLActivated by a positive edge
tTimeoutTIME := T#5s;Maximum for the execution of the Function Block

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FB is activated and remains unit acknowledgement from server
bErrorBOOL1=Error
nErrIdUDINTThe Error information if bError=1
nReceBytesUDINTThe 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

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;String containing the network address of the TwinCAT TCP/IPConnection ServerEmpty=’Local’
nModeDWORD:= 0;Parameters Flag
sRemoteHostT_IPv4Addr := ”;The IP Address of the Server
nRemotePortUDINTThe port number of the server
bEnableBOOLAs long as True, TwinCAT will try to establish a connection until successfully.
tReconnectTIME := T#45s;(*!!!*)The Time for Connection establishment retry.

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FB is activated and remains unit acknowledgement from server
bErrorBOOL1=Error
nErrIdUDINTThe Error information if bError=1
hSocketT_HSOCKETThe TCP/IP Connection handle
eStateE_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

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする