このドキュメントでは、OPC-UA 接続機能を RoboDK に追加する方法について説明します。 OPC UA 接続を使用すると、このプロトコルをサポートする PLC やその他のデバイスとやり取りできます。この機能をプロジェクトに追加するには、RoboDK で OPC-UA アドインを有効にする必要があります。
RoboDK には、OPC UA Add-InをRoboDK プロジェクトに追加できます。
デフォルトでは、RoboDK の OPC-UA Add-Inが無効になっています。OPC-UA Add-Inを有効にすると、RoboDK を起動するたびにそのAdd-Inが表示されます。
こちらの手順でOPC UA Add-inを有効できます:
1.Tools>Add-insを選択します。
2.OPC-UAをダブルクリックします。
OPC-UA 機能が追加されたツールバーが表示されます。
Note:OPC UA Add-Inの詳細については、RoboDK マーケットプレイスセクションを参照してください。
https://robodk.com/addin/com.robodk.plugin.opc-ua.
ツールバーに OPC-UA ボタンが表示され、メニューにも OPC-UA 関連の項目が表示されます。
こちらの例ではRoboDK OPC UA Add-Inを導入しOPC UAサーバーを立ち上げ、UaExpertとBeckhoff TwinCAT3 TF6100で接続テストを行います。
OPC UA Add-Inを使用すると、OPC UAサーバーのポート・無効・有効またはOPC UAサーバの自動起動などの設定が可能です。OPC UA Add-Inを有効にして、OPC UA-OPC-UA設定を選択すれば設定画面が表示されます。OPC UA設定関連は下図のように示さてています。
Tip:OPC UA サーバーのポートを設定し、” Start”ボタンを押して OPC UA サーバーを起動します。
“RoboDK’s OPC UA server running on port 4840”のメッセイジが表示すれば、RoboDK のOPC UA サーバーが正常に起動できました。
Note:.前のセクションで構成した OPC UA ポートが、ファイアウォール、ウイルス対策ソフト、またはシステムに必要なその他のセキュリティ設定で有効になっていることを確認してください。
RoboDKのOPC UAサーバを使用すれば、OPC UAクライアントからRoboDKステーションにある複数のロボット情報を同時アクセスできます。
ソフトUaExpertを使用しRoboDKのOPC UAサーバを検証します。
こちらのリングからUaExpertをダウンロードしてください。
https://www.unified-automation.com/downloads/opc-ua-clients.html.
UaExpertを起動し、“+”ボタンをクリックしRoboDKのOPC UAサーバを追加します。
Custom Discovery”を展開し<Double clicks to Add Server.>からRoboDK OPC UAサーバを追加します。
OPC UAサーバのURL欄から先程追加したOPC UAサーバエンドポイントを入力ます。今回のチュートリアルではopc.tcp://127.0.0.1:48440になります。
セキュリティ設定は“None”に設定します。
OPC UAサーバが追加しました。
次はUaExpertからRoboDKのOPC UAサーバに接続します。
RoboDK OPC UAサーバと接続成功すれば、UaExpertからにノードやメソッドを一覧できます。
サードパーティーから簡単にRoboDKステーションの情報をOPC UA 経由でアクセスできます。
RoboDKノードは現在RoboDKステーションのソフトウェアバージョンを取得できます。
このチュートリアルで使用してるRoboDKバージョンはRoboDK 64 Bit v5.5.3.23031です。
Simulation Speedは現在RoboDK ステーションのシミュレーションスピードを取得や変更できるノードです。
Simulation SpeedノードはスライドバーにあるSimulation Speedになります。
Station Nodeは現在RoboDKのステーション名を取得できます。
下図のように、このチュートリアルに使用してるステーション名は“New Station(1)”になります。
サードパーティはStation ParameterとStation Valueノードを組み合わせて使用することによって、RoboDKステーション内にあるステーションパラメータをアクセスできます。サードパーティOPC UA サーバーは、“StationParameter“の実際の値を継続的に監視し、ステーション値ノードからその“StationParameter“の値を返します。
Note:該当する “StationParameter”が存在しない場合、“StationValue”値は空文字列になります。
RoboDKステーションパラメータを確認するには、RoboDK ステーションを右クリック>Station parametersをクリックします。
Constant parametersからステーションのデフォルトパラメータを確認できます。
StationParameterは“Parameters” フィールドに該当し、StationValueは”Value” フィールドに該当します。
“Add”ボタンをクリックし、RoboDKステーションに新規のパラメータを作成することも可能です。
新しいステーションパラメータが追加されました。
ステーションパラメータ名とその現在値を入力し、Applyタボンをクリックして保存します。
該当するステーションパラメータも取得できます。
RoboDKステーションの現在時間はTimeノードから取得できます。
RoboDKステーションの現在時間はTimeフォーマットとしてノードに格納されました。
そのTimeノードは周期で更新されています。
RoboDK OPC UA Serverではいくつかのメソッドが提供しており、サードパーティがダイナミック的にRoboDKステーションの情報をアクセスできます。
UaExpertからメソッドを右クリック>Callでメソッドを実行できます。
getItem は、ユーザーがアイテムのメモリポインターを取得するメソッドです。
InputArgumentsのデバイス名はRoboDKステーションのロボットやターゲットなどに該当します。OutputArgumentsのItemIDはそのアイテムのメモリポインターになります。
こちらの例ではItem Nameを“ABB_RB1”を入力しメソッドを呼び出せば、ステーションにある“ABB_RB1”というアイテムのメモリポインターが取得しました。
Item Nameは無効やステーション存在しないの場合、Item ID値は0になります。
getJonitsはアイテム ID に基づいて、ユーザーがステーションからロボットのジョイント値を取得できるメソッドです。
ID はRoboDKステーションにあるアイテムのポインター値であり、getItem メソッドから取得できます。
“ABB_RB1”のItemIDはgetItemメソッドから取得できるUIn64フォーマットの整数です。
先ほどのgetItemメソッドで取得したItem ID を渡しメソッドを実行すれば、Joints の値が返ってきます。
getJointsStr は、ユーザーが文字列フォーマットのジョイント値を取得できるメソッドです。
このメソッドのRobot nameはステーション内のロボット名 (文字列) に該当します。
こちらのステーションではロボット名はABB_RB1です。
Robot nameパラメーターに “ABB_RB1“を渡してメソッドを呼び出すだけで、文字列フォーマットのジョイント値が返されます。
setJointsStr は、ロボットのジョイントを文字列値から設定できるようにするメソッドです。
Robot nameには ABB_RB1 が渡され、Joints パラメータにジョイント値を含む文字列を渡すだけです。
例:-0.000000,0.000000,-0.000000,-0.000000,-0.0,-0.000000
OPC UA クライアントを追加します。I/O>Devices>右クリック>Add New Itemします。
OPC UA>Virtual OPC UA Deviceを選択し>Okで追加します。
OPC UA Virtualが追加されました。
次はRoboDK のOPC UA ServerをアクセスするためにOPC UA クライアントを追加します。Device1を右クリック>Add New Itemします。
OPC UA Client(Module)を選択し>Okします。
OPC UA クライアントが追加されました。
OPC UA クライアントをダブルクリックしSettingsタブを開きます。“Select Endpoint”をクリックしOPC UAサーバの接続情報を設定します。
RoboDK OPC UA サーバーのエンドポイントを入力し、Updateボタンで更新します。
Add NodesボタンをクリックしOPC UAサーバーにあるノードやメソッドをプロジェクトに追加します。
TwinCATとOPC UAサーバが接続してる状態であれば、該当するサーバーの情報をアクセスできます。
全てのメソッドを選択し>Okで確定します。
RoboDK OPC UA サーバーのメソッドがプロジェクトに追加されました。
Prefixからメソッドの名前を設定します。
“Create Plc Code”でPLCプログラムを自動作成しましょう。
OpcUAClient フォルダあプロジェクトに追加され、中にRoboDKメソッドもIEC61131-3 Function Blockフォーマットとして格納しています。
こちらのセクションではBeckhoff TwinCAT PLCとRoboDK OPC UA サーバーをアクセスするサンプルコードを紹介します。
PROGRAM MAIN
VAR
bConnected :BOOL;
StationPointer :DINT;
iStep :INT;
bStart :BOOL;;
i :INT;
TON :TON;
bReset :BOOL;
bWrite :BOOL;
TON2 :TON;
bShow :BOOL:=TRUE;
bVis :BOOL:=True;
END_VAR
VAR
Robot_name :STRING(80):='ABB_RB1';
Item_ID :ULINT;
arrJoints :ARRAY[0..11]OF LREAL;
strJoints :STRING(80):='';
arrJointsFromStr:ARRAY[1..11]OF LREAL;
sSeparator :STRING(1) := ',';
arrJointsCommand:ARRAY[1..11]OF LREAL;
strJointsCommand:STRING(80);
END_VAR
VAR CONSTANT
cStepWaitCmd :INT:=0;
cStepInit :INT:=5;
cStepGetItem :INT:=10;
cStepGetItemReset :INT:=20;
cStepGetItemError :INT:=990;
cStepGetJoints :INT:=30;
cStepGetJointsReset :INT:=40;
cStepGetJointsError :INT:=991;
cStepGetJointsStr :INT:=50;
cStepGetJointsStrReset:INT:=60;
cStepGetJointsStrError:INT:=992;
cStepSetJointStrDelay :INT:=69;
cStepSetJointsStr :INT:=70;
cStepSetJointsStrReset:INT:=80;
cStepSetJointsStrError:INT:=993;
cStepEnd :INT:=300;
cStepWaitReset :INT:=999;
END_VAR
VAR
aSplit :ARRAY[1..11] OF STRING(80);
bResultSplit :BOOL;
debug :BOOL;
URL :STRING:='http://192.168.3.42:8091';
END_VAR
bConnected:=OPCUA_VirtualClient_RoboDK_Station.bConnected;
CASE iStep OF
cStepWaitCmd:
IF bStart THEN
iStep:=cStepInit;
bStart:=FALSE;
END_IF
cStepInit:
StationPointer:=0;
FOR i :=1 TO 11 DO
arrJoints[i]:=0.0;
arrJointsFromStr[i]:=0.0;
aSplit[i]:='';
END_FOR
IF NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bBusy
AND NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJoints.bBusy
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJoints.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bBusy
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.setJoints.bBusy
AND NOT OPCUA_VirtualClient_RoboDK_Station.setJoints.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy
AND NOT OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError
THEN
iStep:=cStepGetItem;
END_IF
iStep:=cStepGetItem;
cStepGetItem:
IF OPCUA_VirtualClient_RoboDK_Station.getItem.bDone THEN
iStep:=cStepGetItemReset;
Item_ID:=OPCUA_VirtualClient_RoboDK_Station.getItem.Item_ID;
ELSIF OPCUA_VirtualClient_RoboDK_Station.getItem.bError THEN
iStep:=cStepGetItemError;
END_IF
cStepGetItemReset:
IF NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bBusy
THEN
iStep:=cStepGetJoints;
END_IF
cStepGetJoints:
IF OPCUA_VirtualClient_RoboDK_Station.getJoints.bDone
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJoints.bBusy
THEN
iStep:=cStepGetJointsReset;
ELSIF OPCUA_VirtualClient_RoboDK_Station.getJoints.bError THEN
iStep:=991;
END_IF
cStepGetJointsReset:
IF NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bBusy
THEN
iStep:=cStepGetJointsStr;
END_IF;
cStepGetJointsStr:
IF OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bDone
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bBusy
THEN
iStep:=cStepGetJointsStrReset;
ELSIF OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bError THEN
iStep:=cStepGetJointsStrError;
END_IF
cStepGetJointsStrReset:
IF NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bBusy
THEN
iStep:=cStepSetJointStrDelay;
END_IF;
cStepSetJointStrDelay:
strJointsCommand:=''; strJointsCommand:=CONCAT(LREAL_TO_STRING(arrJointsCommand[1]),strJointsCommand);
strJointsCommand:=CONCAT(strJointsCommand,',');
strJointsCommand:=CONCAT(strJointsCommand,LREAL_TO_STRING(arrJointsCommand[2]));
strJointsCommand:=CONCAT(strJointsCommand,',');
strJointsCommand:=CONCAT(strJointsCommand,LREAL_TO_STRING(arrJointsCommand[3]));
strJointsCommand:=CONCAT(strJointsCommand,',');
strJointsCommand:=CONCAT(strJointsCommand,LREAL_TO_STRING(arrJointsCommand[4]));
strJointsCommand:=CONCAT(strJointsCommand,',');
strJointsCommand:=CONCAT(strJointsCommand,LREAL_TO_STRING(arrJointsCommand[5]));
strJointsCommand:=CONCAT(strJointsCommand,',');
strJointsCommand:=CONCAT(strJointsCommand,LREAL_TO_STRING(arrJointsCommand[6]));
TON2(IN:=TRUE,PT:=T#0.2S);
IF TON2.Q THEN
TON2(IN:=FALSE);
iStep:=cStepSetJointsStr;
END_IF
cStepSetJointsStr:
IF (
OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bDone
AND NOT
OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy
)
OR NOT bWrite
THEN
iStep:=cStepSetJointsStrReset;
ELSIF OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError
THEN
iStep:=cStepSetJointsStrError;
END_IF
cStepSetJointsStrReset:
bWrite:=FALSE;
OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bExecute:=FALSE;
IF NOT OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError
AND NOT OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy
THEN
iStep:=cStepEnd;
END_IF;
cStepEnd:
TON(IN:=TRUE,PT:=T#0.1S);
IF TON.Q THEN
TON(IN:=FALSE);
IF NOT debug THEN
iStep:=10;
ELSE
iStep:=cStepSetJointStrDelay;
END_IF;
END_IF
cStepGetItemError:
Item_ID:=0;
iStep:=cStepWaitReset;
cStepGetJointsError:
FOR i :=0 TO 11 DO
arrJoints[i]:=-99999.99;
END_FOR
iStep:=cStepWaitReset;
cStepGetJointsStrError:
strJoints:='';
iStep:=cStepWaitReset;
cStepWaitReset:
IF bReset THEN
iStep:=cStepInit;
bReset:=FALSE;
END_IF;
END_CASE
aSplit[1] := strJoints;
FOR i:=1 TO 7 DO
bResultSplit := FindAndSplit(
pSeparator := ADR(sSeparator)
,pSrcString := ADR(aSplit[i])
,pLeftString:= ADR(aSplit[i])
,nLeftSize := SIZEOF(aSplit[i])
,pRightString:= ADR(aSplit[i+1])
,nRightSize := SIZEOF(aSplit[i+1])
,bSearchFromRight := FALSE );
IF NOT bResultSplit THEN
EXIT;
END_IF
END_FOR
FOR i :=1 TO 6 DO
arrJointsFromStr[i]:=STRING_TO_LREAL(aSplit[i]);
END_FOR;
//
OPCUA_VirtualClient_RoboDK_Station.getItem(
bExecute:=iStep=cStepGetItem
,Item_Name:=Robot_name
);
OPCUA_VirtualClient_RoboDK_Station.getJoints(
bExecute:=iStep=cStepGetJoints
,Item_ID:=Item_ID,Joints=>arrJoints
);
OPCUA_VirtualClient_RoboDK_Station.getJointsStr(
bExecute:=iStep=cStepGetJointsStr
,Robot_name:=Robot_name,Joints=>strJoints
);
IF bWrite THEN
OPCUA_VirtualClient_RoboDK_Station.setJointsStr(
bExecute:=TRUE
,Robot_name:=Robot_name,Joints:=strJointsCommand);
END_IF;
こちらの例ではRoboDK ステーションでOPC UAクライアントを立ち上げ、OPC UAサーバーをアクセスします。
Note:既存のステーションにある古いステーションパラメータを削除できます。ステーションのルート位置を右クリック>Station Parametersをクリックします。
既存のステーションにあるパラメータが表示され、“Clear All”ボタンでをクリックして全てのステーションパラメータを削除します。
RoboDKステーションの中にOPC-UAサーバーを立ち上げます。
こちらのセクションではOPC UAクライアントを追加する方法を説明します。エンドポイントURLでOPC UAサーバのURLを入力してください。例えば:opc.tcp://127.0.0.1:48441(ポート番号とIPアドレスはアプリケーションに合わせてください)
ConnectボタンをクリックしてOPC UAサーバと接続します。Server variables retrieved. Right Click the station item and select ‘Station parameters’ to see the variablesが表示すれば、OPC UAサーバの接続は成功しました。
ステーションを右クリッククリックし>Station Parametersをクリックします。
各ノードの情報はnodesセクションから確認できます。
OPC UAサーバからノードデータを取得でれば、RoboDK-Python APIからそれらのデータをアクセスできます。
こちらのリングからRoboDK-Python APIの詳しい情報を確認できます。
https://robodk.com/doc/en/PythonAPI/intro.html#how-to-install
もしかくは手動でrobodkパッケージをインストールします。
pip install robodk
こちらの例ではRoboDK Python APIからステーションパラメータをアクセスする方法を紹介します。
from robodk import robolink # RoboDK API
RDK = robolink.Robolink()
from robodk import * # RoboDK API
from robolink import * # Robot toolbox
itemlist = RDK.ItemList()
if itemlist:
# Get all Station Parameters
print('Vaild Paramaters are configurated in your Station..')
StationParameters=RDK.getParams()
for StationParameter in StationParameters:
print("Station Parameters %s : %s"%(StationParameter[0],str((StationParameter[1]))))
else:
print('No Parameter list..')
スクリプトの実行結果は以下になります。
Vaild Paramaters are configurated in your Station..
Station Parameters RoboDK : RoboDK 64 bit v5.5.3.23031
Station Parameters time : 02/14/2023 03:58:29.191.000.000
Station Parameters SimulationSpeed : 13.8551
Station Parameters Station : MyTestStation