Beckhoff#TwinCAT3 TF6310でSLMP Clientを立ち上げ三菱PLCと通信しよう

今回の記事ではBeckhoff TwinCAT3でTF6310を使用しSLMP Clientを立ち上げ、三菱電機のFX5U PLCと通信しレジスタを読み書きします。

さ、FAを楽しもう。

前書き

いつも私の技術ブログとYouTubeチャンネルをご覧いただき、心より感謝申し上げます。また、いまFullさん(full@桜 八重 (@fulhause) / X)と共に毎週水曜日の夜にお届けしている「高橋クリス」ラジオ番組を運営しています。

技術は独り占めせず、届けるもの

私たちは工場の生産技術や制御に関する技術情報を、ブログや動画などで無料公開しています。「知識は誰でもアクセスできるべき」という信念のもと、現場で役立つ具体的なノウハウやトラブル事例などを発信してきました。すべて無料で続けているのは、「知らなかったせいで困る人」を少しでも減らしたいからです。

また、もしあなたの現場で…

  • 「このPLCとデバイスの組み合わせ、ちゃんと動くのかな?」
  • 「EtherCAT通信でうまくいかない部分を検証してほしい」
  • 「新しいリモートI/Oを試したいけど社内に検証環境がない」

など、困っている構成や試してみたいアイデアがあれば、ぜひお知らせください。機器の貸出や構成の共有が可能であれば、検証し、記事や動画で発信します(ご希望に応じて匿名対応も可能です)。

支援のかたち

現在、私達の活動はほぼ無償で続けており、記事や動画の制作には、時間と検証環境の整備が必要です。この活動を継続的にコンテンツを提供するためには、皆様の温かいご支援が大変重要です。

メンバーシップ(ラジオの応援)

Fullさんとのラジオをより充実させるための支援プランです。

https://note.com/fulhause/membership/join

Amazonギフトリスト

コンテンツ制作に必要な機材・書籍をリストにしています。

https://www.amazon.co.jp/hz/wishlist/ls/H7W3RRD7C5QG?ref_=wl_share

Patreon(ブログ・動画活動への応援)

月額での小さなご支援が、記事の執筆・検証環境の充実につながります。

https://www.patreon.com/user?u=84249391

Paypal

小さな支援が大きな力になります。

https://paypal.me/soup01threes?country.x=JP&locale.x=ja_JP

知ってたら助かること、届けたいだけです

あなたの応援が、知識の共有をもっと自由で持続可能なものにしてくれます。これからもどうぞよろしくお願いします。

soup01threes*gmail.com

https://x.com/3threes2

技術はひとりじゃもったいない。

Reference Link

Beckhoff#TwinCAT TF6310_Build a TCP Client
Dobot#Part4_Real-time feedback portとBeckhoff TwinCAT3 TF6310通信しよう

MC protocol

SLMPは、イーサネットを搭載したモジュールや外部機器(パソコンやHMIなど)から、イーサネットを介してSLMP対応機器にアクセスするためのプロトコルです。

SLMP通信が可能な機器間では、SLMPによるメッセージ転送が可能です。CPUにイーサネット搭載モジュールのイーサネットポートは、SLMPのサーバーとして使用できます。

各SLMPは、以下のMCプロトコルのフレームと同じである。

  • 3Eフレーム: MCプロトコルのQnA互換3Eフレーム
  • 1Eフレーム MCプロトコルと互換性のある1Eフレーム

上記のMCプロトコルで使用する外部機器は、SLMP対応機器に接続することができます。

Functions

サーバー機能

外部機器からの要求メッセージ(コマンド)に基づいて、CPUモジュールがデータ処理やデータ転送を行う。

クライアント機能

専用命令により、外部機器へのリクエストメッセージの送信や、外部機器からのレスポンスメッセージの受信が可能。

外部機器(パソコン、HMIなど)からのシステム監視

外部機器からイーサネット搭載モジュールにSLMPメッセージ・フォーマットでリクエスト・メッセージを送信することで、デバイス・リードが可能になり、システム・モニタリングが可能になります。SLMPを使用すると、デバイス・データの読み出しだけでなく、デバイス・データの書き込みやイーサネット搭載モジュールのリセットも可能になります。

MCプロトコルで使用する外部機器との接続

MCプロトコルのQnA互換3EフレームおよびMCプロトコルのA互換1Eフレームを使用する外部機器を、イーサネット搭載モジュールに直接接続することができます。

ネットワーク経由のアクセス

SLMPは、外部デバイスがSLMP対応デバイスを介して、同じネットワーク内のモジュールや他のネットワークにシームレスにアクセスすることを可能にします。

SLMPの概念

それでは、外部機器がSLMPを用いてイーサネット対応モジュールにアクセスする際の手順(制御手順)の概念を見ていきましょう。

コマンドメッセージの送信

SLMP通信がイーサネット搭載モジュールにアクセスするには、イーサネット搭載モジュールから前のコマンドメッセージに対する応答メッセージを受信した後、次のコマンドメッセージを送信する必要があります。注意するのは、応答メッセージの受信が完了するまで、次のコマンドメッセージを送信することはできません。)

完了応答メッセージを受信できない場合

エラーを伴う完了応答メッセージを受信した場合、応答メッセージ内のエラーコードに応じて処理してください。

メッセージ形式

これからはイーサネットポートへの3Eフレームを用いたSLMPデータ通信を行う際の、メッセージデータ形式、データ指定方法などを見ていきましょう。

データ形式

内蔵イーサネットポートと外部デバイス間の通信におけるデータ形式は、ヘッダーとアプリケーションデータで構成されています。

Header

このヘッダーはTCP/IPおよびUDP/IP用です。メッセージ送信前に、外部機器側のイーサネット対応モジュール(コマンドメッセージ)に、外部機器が通常、ヘッダーは自動的に追加されます。

Application data

アプリケーションデータはサブヘッダーとテキストに分けられる。サブヘッダーはメッセージがコマンドメッセージか応答メッセージかを示します。また、テキストは各機能における要求データ(コマンド)と応答データ(応答)であります。

ASCIIコードでデータを通信する場合
Binaryコードでデータを通信する場合
サブヘッダー設定

こちらは3E Frameのサブヘッダー設定です。

ASCIIコードでデータを通信する場合
Binaryコードでデータを通信する場合
制御手順

これからデータ通信を実行する際の制御手順とアプリケーションデータのフォーマットについて見ていきましょう。

ASCIIコードでデータを通信する場合
Binaryコードでデータを通信する場合
Reading and writing data

CPUモジュールのデバイスメモリおよびインテリジェント機能モジュールのバッファメモリへのデータの読み書きをする場合、以下の操作を実行できます:

Reading data

CPUモジュールの動作監視、データ解析、生産制御などは外部装置で実行できます。

Writing data

PLCはは外部デバイスからデータを書き込みます。

Batch Read and Write

こちらは連続するデバイスの値を、デバイスポイント数を指定して一括で読み書きするコマンドです。

Batch read in word units (command: 0401)

こちらのコマンドをワード単位でデバイスから値を読み取ります。

Batch write in word units (command: 1401)

こちらのコマンドはワード単位でデバイスに値を書き込みます。

Protocols

TCPプロトコルはコネクション指向の転送プロトコル(OSIレイヤー4)であり、電話接続に近いイメージです。データストリーム(バイト)は、TCPを介して要求に応じて確実に転送できます。

TCPプロトコルは、クライアントまたはサーバーから送信されたデータが相手からの確認を必要とするネットワークで使用される。TCPプロトコルは、大量のデータや、開始/終了識別子が定義されていないデータストリームの転送に適しています。

送信側にとっては、何バイトのデータが送信されたかを知っているので、これは問題ではない。しかし、受信側はデータストリームのどこでメッセージが終わり、どこで次のデータストリームが始まるかを検出することができない。

TCP/IP Client

PLC 内に最小限の TCP/IP クライアントを実装するには、以下のファンクションブロックが必要です:

  • リモートサーバーとの接続を確立および終了するためのFB
    • FB_SocketConnectおよびFB_SocketCloseのインスタン
    • また、FB_ClientServerConnectionは、両方の関数ブロックの機能を兼ね備えています
    • リモートサーバーとのデータ交換(送受信)のためのファンクションブロックFB_SocketSendおよび/またはFB_SocketReceiveのインスタンス。

TCP/IP server

PLC 内に最小限の TCP/IP サーバを実装するには、以下のファンクションブロックが必要です:

  • リスナーソケットをオープンするFB_SocketListen FBのインスタンス
  • FB_SocketAcceptおよびFB_SocketClose FBのインスタンス
  • FB_ServerClientConnectionは3つのファンクションブロックの機能を組み合わせています。

またリモートクライアントとの接続の確立と終了を行うには:

  • リモートクライアントとのデータ交換(送受信)には、FB_SocketSend および/または FB_SocketReceive のインスタンスを 1 つ使用します。
  • ソケットをオープンする各 PLC ランタイムシステムで、FB FB_SocketCloseAll のインスタンスを 1 つ使用する。
  • FB_SocketAccept と FB_SocketReceive のインスタンスは周期的に呼び出され(ポーリング)、その他は必要に応じて呼び出される。

Implementation

それでは実際にプログラムを構築していきましょう。

GXWORKS Side

三菱IQ-R側では基本プログラムする必要なく設定のみです。R00CPU→Module Parameterをクリックします。

IPアドレスをアプリケーションに合わせて設定します。

Enable/Disable Online Changeを”Enable All(SLMP)”に設定します。

今回Beckhoff TwinCAT3側でByteデータを使ってSLMP ProtocolのFrameを組みますので、Communication Data Codeを”Binary”にします。

次はSLMP Clientの接続Portを設定しますので、External Device Configurationをクリックします。

Ethernet Device→SLMP Connection Moduleを追加してください。最後はプロジェクトを三菱IQ-R PLCにDownloadしていきましょう。

Test with Packet Sender

TwinCATでプログラム組むまえ、無償ツールPacket SenderでSLMP Protocolの電文を三菱IQ-R PLCに送信し、通信確認しましょう。

https://packetsender.com/

Done!三菱IQ-R PLCから正常返答がきました。

Beckhoff TwinCAT3

TF6310

もしSocket通信のFAが0x06のエラーが発生した場合、実際TF6310を実施するTwinCAT環境にTF6310をインストールしたかを確認してください。

PLC

TwinCATプロジェクトにPLCを追加します。

ENUM

最初にENUMデータ・タイプを作成します。

eMCProtocol

こちらのENUMはSLMP e3Frameを使用するときのコードです。

{attribute ‘qualified_only’}
{attribute ‘strict’}
TYPE eMCProtocol :
(
e3EFrame := 16#50


);
END_TYPE

eMCProtocolDeviceCode

こちらのENUMはSLMP経由で各デバイスにアクセスするときに使用するコードです。

{attribute ‘qualified_only’}
{attribute ‘strict’}
TYPE eMCProtocolDeviceCode :
(
eDeviceCodeD:=16#A8
,eDeviceCodeM:=16#90
,eDeviceCodeX:=16#9C
,eDeviceCodeY:=16#9D
,eDeviceCodeW:=16#B4
);
END_TYPE

FB

次はFBを作成します。

fbMCProtocolRead

こちらのFBはコマンド0401を使用し、三菱IQ-R PLCのある領域メモリを一括読み取りします。

VAR

こちらはfbMCProtocolRead内部やINPUT/OUTPUTパラメータをの変数を定義します。

FUNCTION_BLOCK fbMCProtocolRead
VAR_INPUT
udiFirstRegister:UDINT:=0;
uiTotalDevices :UINT:=10;
ProtocolDeviceCode:eMCProtocolDeviceCode;
sRemoteHost :STRING:=’127.0.0.1′;
nRemotePort :INT:=7500;
xStart :BOOL;
END_VAR
VAR_OUTPUT
oiStep :INT;
oxBusy :BOOL;
oxError :BOOL;
oiErrorID :INT;
END_VAR
VAR_IN_OUT
arrwWord :ARRAY[0..999]OF WORD;
END_VAR
VAR
fbSocketSend :FB_SocketSend;
fbSocketReceive :FB_SocketReceive;
iStep :INT:=0;
fbRTrig :R_TRIG;
fbClientServrConnection :FB_ClientServerConnection;
iCounter :INT;
_arrbTempArray:ARRAY[0..3] OF BYTE;
arrbSendBuffer :ARRAY[0..999]OF BYTE;
arrbReceBuffer :ARRAY[0..999]OF BYTE;
iReceiveWord :UINT;
END_VAR

VAR
xBusy,xError :BOOL;
iErrorID :INT;
fbTON :TON;
END_VAR

Program

次はプログラムを作成します。

  • Step0=FBなどを初期化とxStartの起動待ち
  • Step10=三菱IQーRと接続する、接続成功ならStep=20、失敗したらStep=990
  • Step20=MC ProtocolのFrame作成
  • Step30=Frameを三菱IQ-R に送信する、送信成功ならStep=35、失敗したらStep=991
  • Step35=三菱IQ-Rの返答を待つ。受信着てるならStep40
  • Step40=受信FBの実行をOFF待ち
  • Step50=受信着てなおかつデータが正常であればStep=60、エラーありればStep=992
  • Step60=受信したデータを出力、そしてまたStep20戻る
  • Step100=三菱IQ-R PLCとTCP接続を切断
  • Step299=Stepを0に戻す
  • Step990,Step991,Step992=エラー処理

fbRTrig(CLK:=xStart);

CASE iStep OF

0:
fbSocketSend.bExecute:=FALSE;
fbSocketReceive.bExecute:=FALSE;
fbClientServrConnection.bEnable:=FALSE;
fbTON.IN:=FALSE;
IF NOT fbSocketSend.bBusy
AND NOT fbSocketReceive.bBusy
AND NOT fbClientServrConnection.bBusy
AND fbRTrig.Q
THEN
MEMSET(
destAddr:=ADR(arrbReceBuffer)
,fillByte:=0
,n:=SIZEOF(arrbReceBuffer)
);
MEMSET(
destAddr:=ADR(arrwWord)
,fillByte:=0
,n:=SIZEOF(arrwWord)
);
iStep:=10;
xStart:=FALSE;
xBusy:=TRUE;
xError:=FALSE;

END_IF
10:
fbClientServrConnection.bEnable:=TRUE;
IF fbClientServrConnection.eState = E_SocketConnectionState.eSOCKET_CONNECTED THEN
iCounter:=iCounter+1;
iStep:=20;
END_IF;

IF fbClientServrConnection.bError THEN
iStep:=990;
iErrorID:=990;
END_IF

20:

//
arrbSendBuffer[0]:=INT_TO_BYTE(eMCProtocol.e3EFrame);
//
arrbSendBuffer[1]:=16#0;
//Network Number
arrbSendBuffer[2]:=16#0;
//SubNetwork Number
arrbSendBuffer[3]:=16#FF;
//Requested unit I/O number
arrbSendBuffer[4]:=16#FF;
arrbSendBuffer[5]:=16#03;
//Requesting Unit Station Number
arrbSendBuffer[6]:=16#00;
//Requested data length Bytes
arrbSendBuffer[7]:=16#0C;
arrbSendBuffer[8]:=16#00;
//Monitor Timer
arrbSendBuffer[9]:=16#10;
arrbSendBuffer[10]:=16#00;
//Command
arrbSendBuffer[11]:=16#01;
arrbSendBuffer[12]:=16#04;
//SubCommand
arrbSendBuffer[13]:=16#00;
arrbSendBuffer[14]:=16#00;
//first number of Register
MEMMOVE(
ADR(_arrbTempArray)
,ADR(udiFirstRegister)
,n:=SIZEOF(udiFirstRegister)
);
arrbSendBuffer[15]:=_arrbTempArray[0];
arrbSendBuffer[16]:=_arrbTempArray[1];
arrbSendBuffer[17]:=_arrbTempArray[2];
//device code
arrbSendBuffer[18]:=INT_TO_BYTE(ProtocolDeviceCode);
//numbers
MEMMOVE(
ADR(_arrbTempArray)
,ADR(uiTotalDevices)
,n:=SIZEOF(uiTotalDevices)
);
arrbSendBuffer[19]:=_arrbTempArray[0];
arrbSendBuffer[20]:=_arrbTempArray[1];
iStep:=30;
30:
fbSocketSend.cbLen:=21;
fbSocketSend.bExecute:=TRUE;
IF fbSocketSend.bBusy THEN
iStep:=35;
ELSIF fbSocketSend.bError THEN
iStep:=991;
iErrorID:=991;
END_IF;

35:

fbSocketSend.bExecute:=FALSE;
fbSocketReceive.bExecute:=TRUE;
IF fbSocketReceive.nRecBytes >0 THEN
iStep:=40;
END_IF
40:
fbSocketReceive.bExecute:=FALSE;
IF NOT fbSocketReceive.bBusy THEN
iStep:=50;
END_IF

50:
//IF arrbReceBuffer[0]
IF arrbReceBuffer[0] <> 16#D0 AND arrbReceBuffer[9] <> 16#00 AND arrbReceBuffer[10] <> 16#00 THEN
iStep:=992;
iErrorID:=992;
ELSE
iStep:=60;
END_IF
60:
//11 is data
MEMMOVE(
destAddr:=ADR(iReceiveWord)
,srcAddr:=ADR(arrbReceBuffer[7])
,n:=SIZEOF(iReceiveWord)
);
MEMMOVE(
destAddr:=ADR(arrwWord)
,srcAddr:=ADR(arrbReceBuffer[11])
,n:=iReceiveWord*2
);
xError:=FALSE;
iStep:=20;

100:
fbClientServrConnection.bEnable:=FALSE;
IF fbClientServrConnection.eState = E_SocketConnectionState.eSOCKET_DISCONNECTED THEN
iStep:=299;
END_IF;
299:
iStep:=0;

990,991,992:
fbTON(IN:=TRUE,PT:=T#1S);
IF fbTON.Q THEN
iStep:=0;
END_IF
END_CASE


fbSocketReceive(
sSrvNetId:=
,hSocket:=fbClientServrConnection.hSocket
,cbLen:=SIZEOF(arrbReceBuffer)
,pDest:=ADR(arrbReceBuffer)
);

fbSocketSend(
sSrvNetId:=
,hSocket:=fbClientServrConnection.hSocket
,pSrc:=ADR(arrbSendBuffer)
);

fbClientServrConnection(
sSrvNetID:=”
,sRemoteHost:=sRemoteHost
,nRemotePort:=nRemotePort
);


oiStep:=iStep;
oiErrorID:=iErrorID;
oxError:=xError;
oxBusy:=xBusy;

fbMCProtocolWrite

こちらのFBはコマンド1401を使用し、三菱IQ-R PLCのある領域メモリを一括書き込みします。

VAR

こちらはfbMCProtocolWrite内部やINPUT/OUTPUTパラメータをの変数を定義します。

FUNCTION_BLOCK fbMCProtocolWrite
VAR_INPUT
udiFirstRegister:UDINT:=0;
uiTotalDevices :UINT:=10;
ProtocolDeviceCode:eMCProtocolDeviceCode;
sRemoteHost :STRING:=’127.0.0.1′;
nRemotePort :INT:=7501;
xStart :BOOL;
END_VAR
VAR_OUTPUT
oiStep :INT;
oxBusy :BOOL;
oxError :BOOL;
oiErrorID :INT;
END_VAR
VAR_IN_OUT
arrwWord :ARRAY[0..999]OF WORD;
END_VAR
VAR
fbSocketSend :FB_SocketSend;
fbSocketReceive :FB_SocketReceive;

iStep :INT:=0;

fbRTrig :R_TRIG;
fbClientServrConnection :FB_ClientServerConnection;
iCounter :INT;
arrbSendBuffer :ARRAY[0..999]OF BYTE;
arrbReceBuffer :ARRAY[0..999]OF BYTE;

uiSendDataTotalLength :UINT;
_arrbTempArray:ARRAY[0..3] OF BYTE;

END_VAR

VAR
xBusy,xError :BOOL;
iErrorID :INT;
fbTON :TON;
END_VAR

Program

次はプログラムを作成します。

  • Step0=FBなどを初期化とxStartの起動待ち
  • Step10=三菱IQーRと接続する、接続成功ならStep=20、失敗したらStep=990
  • Step20=MC ProtocolのFrame作成
  • Step30=Frameを三菱IQ-R に送信する、送信成功ならStep=35、失敗したらStep=991
  • Step35=三菱IQ-Rの返答を待つ。受信着てるならStep40
  • Step40=受信FBの実行をOFF待ち
  • Step50=受信着てなおかつデータが正常であればStep=60、エラーありればStep=992
  • Step60=Step20戻る
  • Step100=三菱IQ-R PLCとTCP接続を切断
  • Step299=Stepを0に戻す
  • Step990,Step991,Step992=エラー処理

fbRTrig(CLK:=xStart);

CASE iStep OF


0:
fbSocketSend.bExecute:=FALSE;
fbSocketReceive.bExecute:=FALSE;
fbClientServrConnection.bEnable:=FALSE;
IF NOT fbSocketSend.bBusy
AND NOT fbSocketReceive.bBusy
AND NOT fbClientServrConnection.bBusy
AND fbRTrig.Q
THEN
iStep:=10;
xStart:=FALSE;
xBusy:=TRUE;
xError:=FALSE;
END_IF
10:
fbClientServrConnection.bEnable:=TRUE;
IF fbClientServrConnection.eState = E_SocketConnectionState.eSOCKET_CONNECTED THEN
iCounter:=iCounter+1;
iStep:=20;
END_IF;

IF fbClientServrConnection.bError THEN
iStep:=990;
iErrorID:=990;
END_IF

20:
//
arrbSendBuffer[0]:=INT_TO_BYTE(eMCProtocol.e3EFrame);
//
arrbSendBuffer[1]:=16#0;
//Network Number
arrbSendBuffer[2]:=16#0;
//SubNetwork Number
arrbSendBuffer[3]:=16#FF;
//Requested unit I/O number
arrbSendBuffer[4]:=16#FF;
arrbSendBuffer[5]:=16#03;
//Requesting Unit Station Number
arrbSendBuffer[6]:=16#00;
//Requested data length Bytes
uiSendDataTotalLength:=12+uiTotalDevices*2;
MEMMOVE(
ADR(_arrbTempArray)
,ADR(uiSendDataTotalLength)
,n:=SIZEOF(uiSendDataTotalLength)
);
arrbSendBuffer[7]:=_arrbTempArray[0];
arrbSendBuffer[8]:=_arrbTempArray[1];
//Monitor Timer
arrbSendBuffer[9]:=16#10;
arrbSendBuffer[10]:=16#00;
//Command
arrbSendBuffer[11]:=16#01;
arrbSendBuffer[12]:=16#14;
//SubCommand
arrbSendBuffer[13]:=16#00;
arrbSendBuffer[14]:=16#00;
//first number of Register
MEMMOVE(
ADR(_arrbTempArray)
,ADR(udiFirstRegister)
,n:=SIZEOF(udiFirstRegister)
);
arrbSendBuffer[15]:=_arrbTempArray[0];
arrbSendBuffer[16]:=_arrbTempArray[1];
arrbSendBuffer[17]:=_arrbTempArray[2];
//device code
arrbSendBuffer[18]:=INT_TO_BYTE(ProtocolDeviceCode);
//numbers
MEMMOVE(
ADR(_arrbTempArray)
,ADR(uiTotalDevices)
,n:=SIZEOF(uiTotalDevices)
);
arrbSendBuffer[19]:=_arrbTempArray[0];
arrbSendBuffer[20]:=_arrbTempArray[1];

MEMMOVE(
destAddr:=ADR(arrbSendBuffer[21])
,srcAddr:=ADR(arrwWord[0])
,n:=uiTotalDevices*2
);
// arrbSendBuffer[21]:=51;
// arrbSendBuffer[22]:=0;
iStep:=30;
30:
fbSocketSend.cbLen:=21+uiTotalDevices*2;
fbSocketSend.bExecute:=TRUE;
IF fbSocketSend.bBusy THEN
iStep:=35;
ELSIF fbSocketSend.bError THEN
iStep:=991;
iErrorID:=991;
END_IF;

35:
MEMSET(
destAddr:=ADR(arrbReceBuffer)
,fillByte:=0
,n:=SIZEOF(arrbReceBuffer)
);
fbSocketSend.bExecute:=FALSE;
fbSocketReceive.bExecute:=TRUE;
IF fbSocketReceive.nRecBytes >0 THEN
iStep:=40;
END_IF
40:
fbSocketReceive.bExecute:=FALSE;
IF NOT fbSocketReceive.bBusy THEN
iStep:=50;
END_IF

50:
//IF arrbReceBuffer[0]
IF arrbReceBuffer[0] <> 16#D0 OR arrbReceBuffer[9] <> 16#00 OR arrbReceBuffer[10] <> 16#00 THEN
iStep:=992;
iErrorID:=992;
ELSE
iStep:=60;
END_IF
60:
//11 is data
iStep:=20;

100:
fbClientServrConnection.bEnable:=FALSE;
IF fbClientServrConnection.eState = E_SocketConnectionState.eSOCKET_DISCONNECTED THEN
iStep:=299;
END_IF;
299:
iStep:=0;

990,991,992:
fbTON(IN:=TRUE,PT:=T#1S);
IF fbTON.Q THEN
iStep:=0;
END_IF
END_CASE




fbSocketReceive(
sSrvNetId:=
,hSocket:=fbClientServrConnection.hSocket
,cbLen:=SIZEOF(arrbReceBuffer)
,pDest:=ADR(arrbReceBuffer)
);

fbSocketSend(
sSrvNetId:=
,hSocket:=fbClientServrConnection.hSocket
,pSrc:=ADR(arrbSendBuffer)
);

fbClientServrConnection(
sSrvNetID:=”
,sRemoteHost:=sRemoteHost
,nRemotePort:=nRemotePort
);


oiStep:=iStep;
oiErrorID:=iErrorID;
oxError:=xError;
oxBusy:=xBusy;

MAIN

最後はMAINプログラムです。

VAR

先ほど作成したFBを宣言します。

PROGRAM MAIN
VAR
fbMCProtocolRead:fbMCProtocolRead;
arrwiWords :ARRAY[0..999]OF WORD;
fbMCProtocolWrite:fbMCProtocolWrite;
arrwqWords :ARRAY[0..999]OF WORD;

END_VAR

Program

そして三菱 IQ-R PLCのIPアドレス、Port、なおかつアクセスするデバイスタイプ・先頭アドエス・数を設定すればOKです。

fbMCProtocolRead(
udiFirstRegister:=0
,uiTotalDevices:=10
,ProtocolDeviceCode:=eMCProtocolDeviceCode.eDeviceCodeD
,sRemoteHost:=’192.168.0.95′
,nRemotePort:=7500
,xStart:=
,arrwWord:=arrwiWords
);

fbMCProtocolWrite(
udiFirstRegister:=100
,uiTotalDevices:=10
,ProtocolDeviceCode:=eMCProtocolDeviceCode.eDeviceCodeD
,sRemoteHost:=’192.168.0.95′
,nRemotePort:=7501
,xStart:=
,arrwWord:=arrwqWords
);

結果

こちらの動画から動作確認できます。

Donwload

こちらのLinkからプロジェクトをDownloadしてください。

https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT-TestingWithMCProtocol.tnzip

シェアする

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

フォローする