OPC-UA

OPC-UA Add-in有効する

このドキュメントでは、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 - 画像 1    OPC UA - 画像 2

ツールバーに OPC-UA ボタンが表示され、メニューにも OPC-UA 関連の項目が表示されます。

OPC UA - 画像 3

OPC UA サーバー例

こちらの例ではRoboDK OPC UA Add-Inを導入しOPC UAサーバーを立ち上げ、UaExpertとBeckhoff TwinCAT3 TF6100で接続テストを行います。

OPC UA - 画像 4

サーバー設定

OPC UA Add-Inを使用すると、OPC UAサーバーのポート・無効・有効またはOPC UAサーバの自動起動などの設定が可能です。OPC UA Add-Inを有効にして、OPC UA-OPC-UA設定を選択すれば設定画面が表示されます。OPC UA設定関連は下図のように示さてています。

OPC UA - 画像 5

Tip:OPC UA サーバーのポートを設定し、” Start”ボタンを押して OPC UA サーバーを起動します。

OPC UA - 画像 6

“RoboDK’s OPC UA server running on port 4840”のメッセイジが表示すれば、RoboDK のOPC UA サーバーが正常に起動できました。

Note:.前のセクションで構成した OPC UA ポートが、ファイアウォール、ウイルス対策ソフト、またはシステムに必要なその他のセキュリティ設定で有効になっていることを確認してください。

ステーション作成

RoboDKのOPC UAサーバを使用すれば、OPC UAクライアントからRoboDKステーションにある複数のロボット情報を同時アクセスできます。

OPC UA - 画像 7

UaExpertの検証

ソフトUaExpertを使用しRoboDKのOPC UAサーバを検証します。

こちらのリングからUaExpertをダウンロードしてください。

https://www.unified-automation.com/downloads/opc-ua-clients.html.

OPC UA - 画像 8

サーバー追加

UaExpertを起動し、“+”ボタンをクリックしRoboDKのOPC UAサーバを追加します。

OPC UA - 画像 9

Custom Discovery”を展開し<Double clicks to Add Server.>からRoboDK OPC UAサーバを追加します。

OPC UA - 画像 10

OPC UAサーバのURL欄から先程追加したOPC UAサーバエンドポイントを入力ます。今回のチュートリアルではopc.tcp://127.0.0.1:48440になります。

OPC UA - 画像 11

セキュリティ設定は“None”に設定します。

OPC UA - 画像 12

OPC UAサーバが追加しました。

OPC UA - 画像 13

サーバに接続する

次はUaExpertからRoboDKのOPC UAサーバに接続します。

OPC UA - 画像 14

RoboDK OPC UAサーバと接続成功すれば、UaExpertからにノードやメソッドを一覧できます。

OPC UA - 画像 15

ノード

サードパーティーから簡単にRoboDKステーションの情報をOPC UA 経由でアクセスできます。

RoboDK

RoboDKノードは現在RoboDKステーションのソフトウェアバージョンを取得できます。

OPC UA - 画像 16

このチュートリアルで使用してるRoboDKバージョンはRoboDK 64 Bit v5.5.3.23031です。

OPC UA - 画像 17

SimulationSpeed

Simulation Speedは現在RoboDK ステーションのシミュレーションスピードを取得や変更できるノードです。

OPC UA - 画像 18

Simulation SpeedノードはスライドバーにあるSimulation Speedになります。

OPC UA - 画像 19

Station

Station Nodeは現在RoboDKのステーション名を取得できます。

OPC UA - 画像 20

下図のように、このチュートリアルに使用してるステーション名は“New Station(1)”になります。

OPC UA - 画像 21

Station parameters/Station Value

サードパーティはStation ParameterとStation Valueノードを組み合わせて使用することによって、RoboDKステーション内にあるステーションパラメータをアクセスできます。サードパーティOPC UA サーバーは、“StationParameter“の実際の値を継続的に監視し、ステーション値ノードからその“StationParameter“の値を返します。

Note:該当する “StationParameter”が存在しない場合、“StationValue”値は空文字列になります。

OPC UA - 画像 22

RoboDKステーションパラメータを確認するには、RoboDK ステーションを右クリック>Station parametersをクリックします。

OPC UA - 画像 23

Constant parametersからステーションのデフォルトパラメータを確認できます。

OPC UA - 画像 24

StationParameterは“Parameters” フィールドに該当し、StationValueは”Value” フィールドに該当します。

OPC UA - 画像 25

“Add”ボタンをクリックし、RoboDKステーションに新規のパラメータを作成することも可能です。

OPC UA - 画像 26

新しいステーションパラメータが追加されました。

OPC UA - 画像 27

ステーションパラメータ名とその現在値を入力し、Applyタボンをクリックして保存します。

OPC UA - 画像 28

該当するステーションパラメータも取得できます。

OPC UA - 画像 29

Time

RoboDKステーションの現在時間はTimeノードから取得できます。

OPC UA - 画像 30

RoboDKステーションの現在時間はTimeフォーマットとしてノードに格納されました。

OPC UA - 画像 31

そのTimeノードは周期で更新されています。

OPC UA - 画像 32

メソッド

RoboDK OPC UA Serverではいくつかのメソッドが提供しており、サードパーティがダイナミック的にRoboDKステーションの情報をアクセスできます。

UaExpertからメソッドを右クリック>Callでメソッドを実行できます。

OPC UA - 画像 33

getItem

getItem は、ユーザーがアイテムのメモリポインターを取得するメソッドです。

OPC UA - 画像 34

InputArgumentsのデバイス名はRoboDKステーションのロボットやターゲットなどに該当します。OutputArgumentsのItemIDはそのアイテムのメモリポインターになります。

OPC UA - 画像 35

こちらの例ではItem Nameを“ABB_RB1”を入力しメソッドを呼び出せば、ステーションにある“ABB_RB1”というアイテムのメモリポインターが取得しました。

OPC UA - 画像 36

Item Nameは無効やステーション存在しないの場合、Item ID値は0になります。

OPC UA - 画像 37

getJoints

getJonitsはアイテム ID に基づいて、ユーザーがステーションからロボットのジョイント値を取得できるメソッドです。

OPC UA - 画像 38

ID はRoboDKステーションにあるアイテムのポインター値であり、getItem メソッドから取得できます。

OPC UA - 画像 39

“ABB_RB1”のItemIDはgetItemメソッドから取得できるUIn64フォーマットの整数です。

OPC UA - 画像 40

先ほどのgetItemメソッドで取得したItem ID を渡しメソッドを実行すれば、Joints の値が返ってきます。

OPC UA - 画像 41

getJointsStr

getJointsStr は、ユーザーが文字列フォーマットのジョイント値を取得できるメソッドです。

OPC UA - 画像 42

このメソッドのRobot nameはステーション内のロボット名 (文字列) に該当します。

OPC UA - 画像 43

こちらのステーションではロボット名はABB_RB1です。

OPC UA - 画像 44

Robot nameパラメーターに “ABB_RB1“を渡してメソッドを呼び出すだけで、文字列フォーマットのジョイント値が返されます。

OPC UA - 画像 45

setJointsStr

setJointsStr は、ロボットのジョイントを文字列値から設定できるようにするメソッドです。

OPC UA - 画像 46

Robot nameには ABB_RB1 が渡され、Joints パラメータにジョイント値を含む文字列を渡すだけです。

例:-0.000000,0.000000,-0.000000,-0.000000,-0.0,-0.000000

OPC UA - 画像 47

Beckhoff TwinCAT3の実装

OPC UAサーバ追加

OPC UA クライアントを追加します。I/O>Devices>右クリック>Add New Itemします。

OPC UA - 画像 48

OPC UA>Virtual OPC UA Deviceを選択し>Okで追加します。

OPC UA - 画像 49

OPC UA Virtualが追加されました。

OPC UA - 画像 50

次はRoboDK のOPC UA ServerをアクセスするためにOPC UA クライアントを追加します。Device1を右クリック>Add New Itemします。

OPC UA - 画像 51

OPC UA Client(Module)を選択し>Okします。

OPC UA - 画像 52

OPC UA クライアントが追加されました。

OPC UA - 画像 53

OPC UAサーバ設定

OPC UA クライアントをダブルクリックしSettingsタブを開きます。“Select Endpoint”をクリックしOPC UAサーバの接続情報を設定します。

OPC UA - 画像 54

RoboDK OPC UA サーバーのエンドポイントを入力し、Updateボタンで更新します。

OPC UA - 画像 55

RoboDK OPC UA メソッド追加

Add NodesボタンをクリックしOPC UAサーバーにあるノードやメソッドをプロジェクトに追加します。

OPC UA - 画像 56

TwinCATとOPC UAサーバが接続してる状態であれば、該当するサーバーの情報をアクセスできます。

OPC UA - 画像 57

全てのメソッドを選択し>Okで確定します。

OPC UA - 画像 58

RoboDK OPC UA サーバーのメソッドがプロジェクトに追加されました。

OPC UA - 画像 59

RoboDKメソッド自動作成

Prefixからメソッドの名前を設定します。

OPC UA - 画像 60

“Create Plc Code”でPLCプログラムを自動作成しましょう。

OPC UA - 画像 61

OpcUAClient フォルダあプロジェクトに追加され、中にRoboDKメソッドもIEC61131-3 Function Blockフォーマットとして格納しています。

OPC UA - 画像 62

PLC プログラム例

こちらのセクションでは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;

OPC UA クライアント例

こちらの例ではRoboDK ステーションでOPC UAクライアントを立ち上げ、OPC UAサーバーをアクセスします。

Note:既存のステーションにある古いステーションパラメータを削除できます。ステーションのルート位置を右クリック>Station Parametersをクリックします。

OPC UA - 画像 63

既存のステーションにあるパラメータが表示され、“Clear All”ボタンでをクリックして全てのステーションパラメータを削除します。

OPC UA - 画像 64

OPC UAクライアントインタフェース実装

RoboDKステーションの中にOPC-UAサーバーを立ち上げます。

OPC UA - 画像 65

OPC UAクライアント追加

こちらのセクションではOPC UAクライアントを追加する方法を説明します。エンドポイントURLでOPC UAサーバのURLを入力してください。例えば:opc.tcp://127.0.0.1:48441(ポート番号とIPアドレスはアプリケーションに合わせてください)

OPC UA - 画像 66

ConnectボタンをクリックしてOPC UAサーバと接続します。Server variables retrieved. Right Click the station item and select ‘Station parameters’ to see the variablesが表示すれば、OPC UAサーバの接続は成功しました。

OPC UA - 画像 67

ステーションを右クリッククリックし>Station Parametersをクリックします。

OPC UA - 画像 68

ノード

各ノードの情報はnodesセクションから確認できます。

OPC UA - 画像 69

RoboDK APIの実装

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