今回の記事では三菱のRJ71EIP91モジュールを使用しUCMMメッセージをTwinCAT3 Ethernet/IP Adapterに発行します。もし手元にRJ71EIP91あるのにEthernet/IPのAdapterがない…!
UCMMメッセージが試せない時やEthernet/IP 接続テストをしたいとおもったらBeckhoff TwinCAT3を試してください。
Thanks!
この記事が出来上がるのはベッコフ日本法人ベッコフオートメーション株式会社さまとMana Design worksさまから機材を貸してくださったおかけです。誠にありがとうございます。
ベッコフ日本法人ベッコフオートメーション株式会社
IPC6920-005はベッコフ日本法人ベッコフオートメーション株式会社さまが貸してくださったものです。Beckhoff Automationは1980 年会社設立、PCベースの制御技術をベースにしたオープンオートメーションシステム導入の先頭に立つドイツ企業です。
ベッコフ日本法人ベッコフオートメーション株式会社は、2011年に横浜に本社、2017年に名古屋オフィスを設立しました。
こちらはベッコフ日本法人ベッコフオートメーション株式会社様のホームページです。
どうぞよろしくお願いします。
https://www.beckhoff.com/ja-jp/
Reference Link
UCMM message?
UCMMはEthernet/IPの中でServerとConnectionを確立しない状態でデータを読み書きできるコマンドになります。昔のTutorialにも書きましたExplicit Messageと相当し、そのUCMM MessageはServer・Client機能もSupportしており、Client機能ではBuffer Memoryを使用し通信行い、Server機能では自動返答になります。
Client Function
こちらはClient Functionです。
- まずEIP91_1.bSet_CommunicationStartupRequest(Y10) をTrueにします。
- User ProgramでデータをBuffer Memoryに転送します。
- UCMM Data Link実行リクエスト(EIP91_1.bnSet_UCMMSendRequest_D)をTrueにします。
- UCMM コマンドを実行します。
- Ethernet/IP デバイスはコマンドを処理します。
- Ethernet/IP デバイスをコマンドに沿ってデータを返答します。
- UCMM Data Link 完成Flag(EIP91_1.bnSts_UCMMSendCompletion_D)がTrueになります。
Server Function
こちらはServer FunctionのFlowでClientより簡単です。
- まずEIP91_1.bSet_CommunicationStartupRequest(Y10) をTrueにします。
- Ethernet/IP デバイスからコマンドを受信します。
- RJ71EIP91がそのコマンドを処理します。
- コマンドに沿ってたデータをEthernet/IP デバイスに返答します。
Labels
実際Module Labelを使用せず直接Buffer Memoryにアクセスすることもできます。
Buffer Memory Request Command Area – 1st Un\G393280 to Un\G39404 |
Buffer Memory Receive Command Area – 1st Un\G394048 to Un\G394815 |
ですがBuffer MemoryのアドレスOffsetを数えるのは間違えやすいので、今回の記事はModule Labelを使用します。
Basic
Labels | Type | Description |
EIP91_1.bSts_ModuleReady | Bit | モジュール準備完了 |
EIP91_1.bSts_ModuleError | Bit | モジュールエラーあり |
EIP91_1.bSts_CommunicationReady | Bit | モジュール通信状態OK |
EIP91_1.bSet_CommunicationStartupRequest | Bit | Ethernet/IP Class1通信開始信号 |
EIP91_1.bSet_ModuleErrorClearRequest | Bit | モジュールエラーリセット信号 |
UCMM
Labels | Type | Description |
EIP91_1.bnSet_UCMMSendRequest_D | Bit(1..32) | UCMM メッセージリクエスト(Connection1-32) |
EIP91_1.stnUCMMCommandArea | M+RJ71EIP91_stUCMMCommand(1..32) | UCMM メッセージ通信エリア |
EIP91_1.bnSts_UCMMSendRequestAcceptance_D | Bit(1..32) | UCMM メッセージが受け入れた信号 |
EIP91_1.bnSts_UCMMSendCompletion_D | Bit(1..32) | UMCC メッセージ実行完了信号 |
EIP91_1.stnUCMMCommandArea
Labels | Type | Description |
uSet_Request_Service_D | Word | UCMM リクエスト Service Code |
uSet_Request_Class_D | Word | UCMM リクエスト Class Code |
uSet_Request_Instance_D | Word | UCMM リクエスト Instance Code |
uSet_Request_Attribute_D | Word | UCMM リクエスト Attribute Code |
uSet_Request_DataLength_D | Word | UCMM リクエストの合計データサイズ |
unSet_Request_RequestData_D | Word(0..706) | UCMM リクエスト データ |
uResult_Response_Service_D | Word | UCMM リスボン Service Code |
uResult_Response_Class_D | Word | UCMM リスボン Class Code |
uResult_Response_Instance_D | Word | UCMM リスボン Instance Code |
uResult_Response_Attribute_D | Word | UCMM リスボン Attribute Code |
uResult_Response_DataLength_D | Word | UCMM リスボンの合計データサイズ |
unResult_Response_ReceiveData_D | Word(0..706) | UCMM リスボン データ |
Implementation
TwinCAT Side
Add Adapter
TwinCAT3を起動し、I/O>Devices>Add New Itemします。
EtherNet/IP Adapter(Slave)を選び>Okします。
Ethernet/IP ネットワークに使用するEthernet Interfaceを選び>Okします。
それでEthernet/IP Adapterが追加されました。
Append IO
次はIO Assemblyを追加します。Box1>右クリック>Append IO Assemblyします。
Assembly 1が追加されました。
Add Input
Inputsを定義します。Assembly 1(input/Output)>Inputs>右クリック>Add New Itemします。
Create Array Typeで配列変数を定義します。
今回はINPUT 20個のWordになります。
Variable>Name Fieldで名前を変更しましょう。
Add Output
Outputsを定義します。Assembly 1(input/Output)>Outputs>右クリック>Add New Itemします。
先程配列を追加しましたので、直接Array[0..19]of WORDを選択すればOkです。
今回はOutput 20個のWordになります。
OUTPUTS変数も名前変更しましょう。
Config Adapter IP
Ethernet/IP AdapterのBoxにIPを設定します。Boxをダブルクリックします。
SettingsのTabを開き、8000.21、8000.22のFieldでIPとNetwork Maskを入力してください。
最初の構成で書いたように、TwinCAT Ethernet/IP Adapterは192.168.11.122になります。
Add PLC
次はPLCを追加します。PLC>Add New Itemします。
Standard PLC Project>Addします。
Add GVL
Global Variable Listを追加します。GVLs>Add>Global Variable Listします。
GVLの名前をいれて>Open。
GVLが作成されました。
Define Ethernet/IP Variables
Ethernet/IP AdapterのProcess I/Oと紐つけますので、長さ20のWord配列を定義します。%I*と%Q*も忘れないでください。
Build Solution
Build>Build Solutionでプロジェクトをコンパイルします。
Link Inputs
Ethernet/IP Adapter Box1 Assembly1のProcess InputとUser ProgramのGVL変数に紐つけます。Assembly1>Inputs>Data>Variable>右クリック>Change Linkします。
先程に宣言したAT %I* 変数を選び>OK。
Link Output
Ethernet/IP Adapter Box1 Assembly1のProcess OutputとUser ProgramのGVL変数に紐つけます。Assembly1>Outputs>Data>Variable>右クリック>Change Linkします。
先程に宣言したAT %Q* 変数を選び>OK。
Activate Configuration
Activate ConfigurationでHardware ConfigurationをRuntimeにDownloadします。
OKで進みます。
ライセンスが足りないと言われたら、Yesで進みます。
Popupで表示したSecurity Codeとおなじ文字入れたら、TrailライセンスがActivateになり、7日使用可能になります。7日過ぎたらまたSecurity Code入れればまたTrial ライセンスが生成されますので、TwinCATは基本的には無料です。
OKでRuntimeを再起動します。
Login
LoginでUser ProgramをDownloadします。
Yesで進みます。
Start
最後はStartボタンでRuntimeをRun Modeに切り替えます。
Mitsubishi Side
Flow
こちらは三菱GXWORKS3のプログラムFlowです。まずRJ71EIP91の状態をChecksi>Readyなら送信コマンドを待ちます。送信コマンドが来たらTarget IP(今回の場合はTwinCAT)設定>コマンドのClass/Attribute/Instance/Data length/Service Codeを設定>次は送信受信Bufferをクリア>UCMMメッセージ発行>TwinCAT側まつ>また戻すのようなLoopです。
Structured Data Type.
まずは今回使用する構造体を定義します。
DUT_UCMM
毎回Instance・IPなどの変数を定義するのは面倒なので、まとめて構造体として定義すれば便利です。
IP Word [Unsigned]/Bit String [16-bit](0..3) uInstance Word [Unsigned]/Bit String [16-bit] uServices Word [Unsigned]/Bit String [16-bit] uAttribute Word [Unsigned]/Bit String [16-bit] uClass Word [Unsigned]/Bit String [16-bit] uDataLen Word [Unsigned]/Bit String [16-bit] |
DUT_IECTIMER
TON Timerで送信Timeoutを検知しますので、TON Timerに必要なパラメータもまとめて定義すれば楽になります。
tPT Time tET Time bQ Bit bTrigger Bit |
Function
FC_IPEncode
IPをRJ71EIP91のLabel Formatに合わせて変換するFunctionです。MUSTではないが、ip[0]=192,ip[1]=168のほうがわかりやすいと思いますので。
VAR
i_ip Word [Unsigned]/Bit String [16-bit](0..3) VAR_INPUT |
PROGRAM
FC_IPEncode[1]:=SHL(i_ip[0],8); FC_IPEncode[1]:=FC_IPEncode[1]+i_ip[1]; FC_IPEncode[0]:=SHL(i_ip[2],8); FC_IPEncode[0]:=FC_IPEncode[0]+i_ip[3]; |
;
MAIN
こちらはMainのプログラムです。
Local Label
bReady Bit VAR bSendUCMM Bit VAR bSendingUCMM Bit VAR bTimeOut Bit VAR iUCMMStep Word [Signed] VAR iCounter Word [Signed] VAR MyData Word [Unsigned]/Bit String [16-bit](0..706) VAR SendMessage R_TRIG VAR tTimeOUT TON VAR Request DUT_UCMM VAR Response DUT_UCMM VAR TimeOUT_Flags DUT_IECTIMER VAR ciStepCheckReady Word [Signed] VAR_CONSTANT 0 ciStepWaitCommand Word [Signed] VAR_CONSTANT 1 ciStepIPConfig Word [Signed] VAR_CONSTANT 10 ciStepUCMMConfig Word [Signed] VAR_CONSTANT 20 ciStepClearBuffer Word [Signed] VAR_CONSTANT 30 ciStepSendUCMM Word [Signed] VAR_CONSTANT 40 ciStepWaitResponse Word [Signed] VAR_CONSTANT 50 ciStepGetData Word [Signed] VAR_CONSTANT 60 ciStepTimeOut Word [Signed] VAR_CONSTANT 999 |
Program
//Ready bReady:= EIP91_1.bSts_ModuleReady AND NOT EIP91_1.bSts_ModuleError AND EIP91_1.bSts_CommunicationReady ; EIP91_1.bSet_CommunicationStartupRequest:=bReady; //Auto Reset EIP91_1.bSet_ModuleErrorClearRequest:=EIP91_1.bSts_ModuleError; CASE iUCMMStep OF ciStepCheckReady: IF bReady THEN iUCMMStep:=ciStepWaitCommand; bSendingUCMM:=FALSE; END_IF; ciStepWaitCommand: SendMessage(CLK:=bSendUCMM); IF SendMessage.Q AND NOT bSendingUCMM THEN iUCMMStep:=ciStepIPConfig; bTimeOut:=FALSE; EIP91_1.bnSet_UCMMSendRequest_D[1]:=FALSE; END_IF; ciStepIPConfig: //ip Request.IP[0]:=192; Request.IP[1]:=168; Request.IP[2]:=11; Request.IP[3]:=122; EIP91_1.stnUCMMCommandArea[1].unSet_Request_TargetIPAddress_D:=FC_IPEncode(Request.IP); iUCMMStep:=ciStepUCMMConfig; ciStepUCMMConfig: //UCMM Connection No1. //Services Request.uServices:=16#1; EIP91_1.stnUCMMCommandArea[1].uSet_Request_Service_D:=Request.uServices; //Class Request.uClass:=16#1; EIP91_1.stnUCMMCommandArea[1].uSet_Request_Class_D:=Request.uClass; //Instance Request.uInstance:=16#1; EIP91_1.stnUCMMCommandArea[1].uSet_Request_Instance_D:=Request.uInstance; //Attribute Request.uAttribute:=16#0; EIP91_1.stnUCMMCommandArea[1].uSet_Request_Attribute_D:=Request.uAttribute; //Data Length Request.uDataLen:=0; EIP91_1.stnUCMMCommandArea[1].uSet_Request_DataLength_D:=Request.uDataLen; iUCMMStep:=ciStepClearBuffer; ciStepClearBuffer: //Clear the Data Buffer FOR iCounter:=0 TO 707 DO //Send Buffer EIP91_1.stnUCMMCommandArea[1].unSet_Request_RequestData_D[iCounter]:=16#0; //Receive Buffer EIP91_1.stnUCMMCommandArea[1].unResult_Response_ReceiveData_D[iCounter]:=16#0; END_FOR; iUCMMStep:=ciStepSendUCMM; ciStepSendUCMM: //Set the Requset EIP91_1.bnSet_UCMMSendRequest_D[1]:=TRUE; bSendingUCMM:=TRUE; iUCMMStep:=ciStepWaitResponse; ciStepWaitResponse: IF EIP91_1.bnSts_UCMMSendRequestAcceptance_D[1] AND EIP91_1.bnSts_UCMMSendCompletion_D[1] THEN iUCMMStep:=ciStepGetData; END_IF; //Time out Detections TimeOUT_Flags.bTrigger := NOT EIP91_1.bnSts_UCMMSendRequestAcceptance_D[1] OR NOT EIP91_1.bnSts_UCMMSendCompletion_D[1] ; TimeOUT_Flags.tPT :=T#2s; tTimeOUT( IN:= TimeOUT_Flags.bTrigger ,PT:= TimeOUT_Flags.tPT ,Q=> TimeOUT_Flags.bQ ,ET=> TimeOUT_Flags.tET ); IF TimeOUT_Flags.bQ THEN tTimeOUT( IN:= FALSE ); iUCMMStep:=ciStepTimeOut; END_IF; ciStepGetData: Response.uAttribute:=EIP91_1.stnUCMMCommandArea[1].uResult_Response_Attribute_D; Response.uClass:=EIP91_1.stnUCMMCommandArea[1].uResult_Response_Class_D; Response.uDataLen:=EIP91_1.stnUCMMCommandArea[1].uResult_Response_DataLength_D; Response.uInstance:=EIP91_1.stnUCMMCommandArea[1].uResult_Response_Instance_D; Response.uServices:=EIP91_1.stnUCMMCommandArea[1].uResult_Response_Service_D; MyData:=EIP91_1.stnUCMMCommandArea[1].unResult_Response_ReceiveData_D; iUCMMStep:=ciStepCheckReady; ciStepTimeOut: bTimeOut:=TRUE; iUCMMStep:=ciStepCheckReady; END_CASE; |
Result
Wiresharkからみると192.168.11.34(RJ71EIP91)からGet Attributes Allのコマンドを192.168.11.122(TwinCAT)に発行し、192.168.11.122(TwinCAT)が返答します。