Beckhoff#TwinCAT TF6310_Build a TCP Client

Beckhoff TwinCAT TF6310 では複数のTCP/IP Server/Client の実装をSupportできます。

  • PLC library: Tc2_TcpIp library (basic TCP/IP and UDP/IP function)
  • Background program: TwinCAT TCP/IP Connection Server

この記事ではまずTCP/IP ClientをTwinCAT上でどう実装するかを説明し、PythonのServerとやりとりを書きたいと思います。

よろしくお願いします。

System Requirment

Installation

以下のLinkにアクセスしInstallation fileをダウンロードします。

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

言語を選びます。

Next>

ライセンスに同意し>Next>します。

情報を入力し、Next>します。

Complete>Next>.

Next>

Installします。

しばらくお待ちください。

Done!

インストールされたらTF6310-TCP-IPのDirectory が出てきます。

Adding Library

次はLibraryを追加します。Reference>Add Library.

FB_Socket か Tc2_TcpIP を検索しProjectをLibarayに入れてください。

Function Block

FB_SocketConnect

こちらのFunction Blockを使用しTCP/IP Connectionを確立できます。

hSocketという変数が、Server接続に成功するときに出力します。そのhSocketはFB_SocketSend()、FB_SocketReceive()、 FB_SocketClose()のFunction BlockでInputパラメタとして必要です。

Serverは各Connectionに自動的にPort番号を振り分けます。

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;TwinCAT TCP/IP ServerのNetIdです。空文字ならLocal Serverになります。
sRemoteHostT_IPv4Addr := ”;ServerのIP
nRemotePortUDINTServerのPort
bExecuteBOOL立ち上げ=実行
tTimeoutTIME := T#45s;(*!!!*)FBの最大実行時間

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FBが実行されてServerのAckまちです。
bErrorBOOL1=Error
nErrIdUDINTError情報
hSocketT_HSOCKETTCP/IP Connection handle

FB_SocketClose

TCP/IP or UDP socket connectionをCloseするFunction Blockです。

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;TwinCAT TCP/IP ServerのNetIdです。空文字ならLocal Serverになります。
sRemoteHostT_IPv4Addr := ”;ServerのIP
nRemotePortUDINTServerのPort
bExecuteBOOL立ち上げ=実行
tTimeoutTIME := T#45s;(*!!!*)FBの最大実行時間

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FBが実行されてServerのAckまちです。
bErrorBOOL1=Error
nErrIdUDINTError情報
hSocketT_HSOCKETTCP/IP Connection handle

FB_SocketSend

このFunction Blockを使用すればServerにPacketを送信できます。

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;TwinCAT TCP/IP ServerのNetIdです。空文字ならLocal Serverになります。
hSocketT_HSOCKETTCP/IP Connection handle
cbLenUDINT送信するByte数
pSrcPOINTER TO BYTE送信BufferのAddress(Pointer)
bExecuteBOOL立ち上げ=実行
tTimeoutTIME := T#45s;(*!!!*)FBの最大実行時間


VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FBが実行されてServerのAckまちです。
bErrorBOOL1=Error
nErrIdUDINTError情報

FB_SocketReceive

Serverからのデータを受信するFunction Blockです。bExecuteは立ち上げ実行なので、100msごとにTriggerしたほうが簡単に実装できます。

そしてServerから受信したBytesはnRecBytesに出力します。


VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;TwinCAT TCP/IP ServerのNetIdです。空文字ならLocal Serverになります。
hSocketT_HSOCKETTCP/IP Connection handle
cbLenUDINT受信するByte数
pSrcPOINTER TO BYTE受信BufferのAddress(Pointer)
bExecuteBOOL立ち上げ=実行
tTimeoutTIME := T#45s;(*!!!*)FBの最大実行時間

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FBが実行されてServerのAckまちです。
bErrorBOOL1=Error
nErrIdUDINTError情報
nReceBytesUDINTServerからの受信Bytes数

FB_ClientServerConnection

TwinCATのLibraryにはもっと簡単なFunction BlockでClient-Server connectionを実装できます。こちらのFB_ClientServerConnectionです。中身ではFB_SocketOpen と FB_SocketCloseがすでに含まれております。一回このFBを呼び出すと、次はアプリケーションよりB_SocketSend と FB_SocketReceiveを使うだけです。

そのFunction Blockでは診断情報eStateとErrorIDも出力されています。

VAR_INPUT

NameTypeDescription
sSrvNetIdT_AmsNetId := ”;TwinCAT TCP/IP ServerのNetIdです。空文字ならLocal Serverになります。
nModeDWORD:= 0;Parameters Flag
sRemoteHostT_IPv4Addr := ”;ServerのIP
nRemotePortUDINTServerのPort
bEnableBOOL1=接続開始し成功まではRetryする
tReconnectTIME := T#45s;(*!!!*)接続のRetry時間間隔

VAR_OUTPUT

NameTypeDescription
bBusyBOOL1=FBが実行されてServerのAckまちです。
bErrorBOOL1=Error
nErrIdUDINTError情報
hSocketT_HSOCKETTCP/IP Connection handle
eStateE_SocketConnectionState := eSOCKET_DISCONNECTED;現在のConnection Status


Error: 1828

もしFunction Blockが実行するときError1828が出てくると、それはライセンスがないことを示しています。

SYSTEM>License.

Manage License Taを開いて> T6310>Add License.

Trial Licenseが追加されました。

7 Days Trial Licenseをクリックします。

magic Codeを入力します。

License file 生成されました。

最後はConfigurationをDownloadすればOK。


Data type

T_HSOCKET 

まずこの変数はSocketがOpenされたときに更新されます。以後この変数でopen/close/send/receive をやりとりします。

E_SocketConnectionState

TCP/IP Connectionの現在状態を示すDUTです。

TYPE E_SocketConnectionState:
(
    eSOCKET_DISCONNECTED,
    eSOCKET_CONNECTED,
    eSOCKET_SUSPENDED
);
END_TYPE

Server with Python

最初にPythonで簡単なServerとClientを作成し、自分のServerが本当にOKかどうかをCheckします。

Server Side

ServerがClientに接続し、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

Severに接続しHello worldを送信する。

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

ではPython serverがちゃんと動作してるので次はClientをTwinCAT TF6310 TCP/IPに置き換えます。

SocketConnect/Close

Program1-まずTwinCAT側がServerとつながるかをテストします。

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

hsocket変数ではClientとServerのIPやPortが見えます。

これは接続してるんですね。

Result-Python Server Side

Server側ではClientから接続したことも確認できました。

Connected by (‘127.0.0.1’, 51665)

Send/Receive the Data

よし、次はTwinCATからデータを送受信してみます。

Modify the Python server

PythonのServerを少し変更します。応答がもう少しわかりやすいようにメッセージを変えます。

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

TwinCATがデータを送信し、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

最後にFB_ScoketOpenとFB_SocketCloseではなくFB_ClientServerConnection Helper function blockでConnectionを実装してみます。

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

シェアする

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

フォローする