OPC-UA

启用 OPC-UA 添加 -插件

本文档将向您介绍如何为 RoboDK 添加 OPC-UA 连接。OPC UA 连接允许您与支持该协议的 PLC 和其他设备进行交互。您应启用 RoboDK 中的 OPC-UA 附加插件,以便为您的项目添加 OPC UA 服务器和客户端功能。

RoboDK 包含一个 OPC-UA 插件,可为 RoboDK 项目添加 OPC UA 兼容性。

默认情况下,RoboDK 禁用 OPC-UA 加载项。启用后,每次启动 RoboDK 时都会显示该插件。

您可以通过以下步骤启用 OPC UA插件:

1.选择工具-插件。

2.双击 OPC-UA。

您会看到一个额外的工具栏,其中包含 OPC-UA 功能。

注:您可以在 RoboDK 市场部分找到更多有关 OPC UA插件的信息: https://robodk.com/addin/com.robodk.plugin.opc-ua。

OPC UA - 图片 1    OPC UA - 图片 2

您应该可以在工具栏中看到 OPC-UA 按钮,并在菜单中看到 OPC-UA 条目。

OPC UA - 图片 3

OPC UA 服务器示例

在本示例中,您将学习如何启用 OPC UA插件并将 RoboDK 转换为 OPC UA 服务器。我们将使用 UaExpert 软件和 Beckhoff TwinCAT3 TF6100 浏览一些设置。

OPC UA - 图片 4

配置 OPC UA 服务器

OPC UA插件允许您配置一些设置,如服务器端口。您还可以选择激活服务器、停用服务器或使用 RoboDK 自动启动服务器。

启用 OPC UA 插件后,选择 OPC UA-OPC-UA 设置来配置 OPC UA 设置

OPC UA 设置屏幕显示在左侧,如下图所示。

OPC UA - 图片 5

提示:您可以更改 OPC UA 服务器的端口,按 "Start(开始)"按钮更改 OPC UA 服务器的端口。

OPC UA - 图片 6

如果您看到类似 "RoboDK 的 OPC UA 服务器在 4840 端口运行 "的信息,则表示 RoboDK 中的 OPC UA 服务器已启动。

注意:请确保上一节中配置的 OPC UA 端口已在 Windows 防火墙、反病毒软件或系统要求的任何其他安全设置中启用。

创建自己的站点

您可以与拥有一个或多个机器人的任何 RoboDK 站测试 OPC UA 连接性。

OPC UA - 图片 7

使用 UaExpert 实施

您可以使用UaExpert 软件测试与 RoboDK OPC UA 服务器的连接性。

您可以从统一自动化网站https://www.unified-automation.com/downloads/opc-ua-clients.html 下载免费版 UaExpert 软件。

OPC UA - 图片 8

插件 UaExpert 服务器

启动 UaExpert,点击 "+"按钮,插件 RoboDK OPC UA 服务器。

OPC UA - 图片 9

展开 "自定义发现",选择 <双击添加服务器.> 选项,添加 RoboDK OPC UA 服务器。

OPC UA - 图片 10

输入上一步配置的 OPC UA 服务器 URL opc.tcp://127.0.0.1:48440。

OPC UA - 图片 11

以 "无 "安全性连接 OPC UA 服务器。

OPC UA - 图片 12

服务器已配置。

OPC UA - 图片 13

连接到服务器

现在,您可以从 UaExpert 连接到 RoboDK OPC UA 服务器。

OPC UA - 图片 14

建立连接后,您可以看到节点和方法。

OPC UA - 图片 15

服务器节点

RoboDK OPC UA 服务器内有一些节点,可让您交换有关您的工作站的一些基本信息。

RoboDK

RoboDK 节点是提供 RoboDK 软件实际版本的节点。

OPC UA - 图片 16

本例中使用的版本为 RoboDK 64 Bit v5.5.3.23031。

OPC UA - 图片 17

模拟速度

仿真速度是一个节点,显示实际仿真速度并允许用户覆盖当前仿真速度。

OPC UA - 图片 18

节点值参考模拟速度的滑动条。

可以从该节点读取当前的模拟结果,并可以覆盖模拟速度。

OPC UA - 图片 19

站点

站节点(Station Node)是一个允许用户获取 RoboDK 中当前站名称的节点。

OPC UA - 图片 20

如下所示,"站 "节点在 RoboDK 中引用了您的 "站名"。

OPC UA - 图片 21

站参数/站值

站参数(Station Parameter)和站值(Station Value)是一对设置节点,允许用户获取或设置站内的任何参数。RoboDK OPC UA 服务器将持续监控 "StationParameter "的实际值,并从 "Station Value "节点返回该 "StationParameter "的值。

注意:如果站参数不存在,则返回空字符串。

OPC UA - 图片 22

右键单击 RoboDK 管理站 > 管理站参数,即可查看管理站参数。

OPC UA - 图片 23

在常量参数字段中,可以看到默认台站参数及其值。

OPC UA - 图片 24

台站参数指的是 "参数 "字段,台站值指的是 "值 "字段。

OPC UA - 图片 25

点击 "插件 "按钮,我们就可以创建自己的参数。

OPC UA - 图片 26

添加了一个新的站参数。

OPC UA - 图片 27

输入参数名称和参数值,然后按应用保存。

OPC UA - 图片 28

您还可以获得自己的站点参数。

OPC UA - 图片 29

时间

时间节点是一个可以获取 RoboDK 管理站当前时间的节点。

OPC UA - 图片 30

返回 DataTime 格式的值。

OPC UA - 图片 31

这个节点会不断更新。

OPC UA - 图片 32

方法

RoboDK OPC UA 服务器还提供了一些方法,允许用户动态访问 RoboDK 工作站的数据。

我们只需右击 "方法">"调用 "即可执行该方法。

OPC UA - 图片 33

获取项目

getItem 是一种允许用户获取 Item 指针的方法。

OPC UA - 图片 34

对于 InputArguments(输入参数),设备名称是必需的,您可以将设备名称想象为您的站名、机器人名称等。项目 ID 是输出参数,用于返回该设备的指针。

OPC UA - 图片 35

在本例中,我收到了 ABB 机器人的项目 ID(指针),其名称为 "ABB_RB1"。

OPC UA - 图片 36

如果项目名称无效或在站内不存在,则返回 0。

OPC UA - 图片 37

getJoints

getJonits 是一种允许用户根据项目 ID 从站台获取机器人关节值的方法。

OPC UA - 图片 38

Item ID 是 Item 的指针值,可以通过 getItem() 方法获取。

OPC UA - 图片 39

我们将通过 "ABB_RB1 "项目名称获取项目 ID,并返回一个 UInt64 值。

OPC UA - 图片 40

在上一个方法中传递项目 ID 时,会返回关节值。

OPC UA - 图片 41

getJointsStr

getJointsStr 是一种允许用户根据字符串值获取关节值的方法。

OPC UA - 图片 42

我们可以在此方法中传递机器人名称(字符串)。

OPC UA - 图片 43

在 "我的工作站 "中,ABB_RB1 是我的机器人名称。

OPC UA - 图片 44

我们只需在机器人名称参数中输入 "ABB_RB1",然后调用该方法--以字符串格式返回关节值。

OPC UA - 图片 45

setJointsStr

setJointsStr 是一个允许用户根据字符串值设置机器人关节值的方法。

OPC UA - 图片 46

在机器人名称中,传递的是 ABB_RB1,我们只需在关节参数中传递一个包含关节值的字符串即可。

For example:-0.000000,0.000000,-0.000000,-0.000000,-0.0,-0.000000

OPC UA - 图片 47

使用 Beckhoff TwinCAT 3 实施

您可以使用 Beckhoff TwinCAT 3 软件测试与 RoboDK OPC UA 服务器的连接性。

添加 TwinCAT3 服务器

首先,您可以通过选择 I/O>Devices>Add New Item(I/O>设备>添加新项目)来创建 OPC UA 客户端。

OPC UA - 图片 48

从 OPC >OK 中选择虚拟 OPC UA 设备。

OPC UA - 图片 49

插入 OPC UA 虚拟。

OPC UA - 图片 50

我们需要添加一个 OPC UA 客户端来访问 RoboDK OPC UA 服务器。

选择设备 1 >右键单击 >添加新插件。

OPC UA - 图片 51

选择 "OPC UA 客户端(模块)",然后确定。

OPC UA - 图片 52

插入 OPC UA 客户端。

OPC UA - 图片 53

配置服务器

打开 OPC UA 客户端 > 进入设置选项卡 > 点击 "选择端点 "配置要访问的 OPC UA 服务器端点。

OPC UA - 图片 54

输入 RoboDK OPC UA 服务器 URL 并更新。

OPC UA - 图片 55

插件 RoboDK 服务器方法

按 "Add Nodes(添加节点)"浏览 OPC UA Server 内部的节点。

OPC UA - 图片 56

如果 TwinCAT 与 OPC UA 服务器之间的连接已建立,则可以浏览 OPC UA 服务器的详细信息。

OPC UA - 图片 57

选择所有方法,然后确定。

OPC UA - 图片 58

方法会插入到您的 "配置 "中。

OPC UA - 图片 59

自动生成 RoboDK 方法

在此字段中配置您的名称前缀。

OPC UA - 图片 60

按 "创建 PLC 代码",从 TwinCAT 创建 PLC 代码。

OPC UA - 图片 61

在项目中创建 OpcUaClient 文件夹,并以 IEC61131-3 功能块格式创建所有 RoboDK 方法。

OPC UA - 图片 62

PLC 程序示例

本节展示了 Beckhoff TwinCAT PLC 与 RoboDK OPC UA 服务器通信的示例程序。

主程序

VAR

   bConnected      BOOL;

   站点指针    :DINT;

   iStep           :INT;

   bStart          :BOOL;;

   i               :INT;

   吨               :TON;

   bReset          :BOOL;

   bWrite          :BOOL;

   TON2            :TON;

   bShow           BOOL:=TRUE;

   bVis            BOOL:=True;

END_VAR

 

VAR

   机器人名称        :string(80):='abb_rb1';

   项目 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;

调试         :BOOL;

   URL        :STRING:='http://192.168.3.42:8091';

END_VAR

bConnected:=OPCUA_VirtualClient_RoboDK_Station.bConnected;

 

案例 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]:='';

        结束

        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

              然后

              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

              然后

              iStep:=cStepGetJoints;

        END_IF

   cStepGetJoints:

 

        IF OPCUA_VirtualClient_RoboDK_Station.getJoints.bDone

              AND NOT OPCUA_VirtualClient_RoboDK_Station.getJoints.bBusy

              然后

              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

       

              然后

              iStep:=cStepGetJointsStr;

        END_IF;

       

   cStepGetJointsStr:

 

        IF OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bDone

              AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bBusy

             然后

              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

              然后

                   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:

 

       

        如果 (

        OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bDone

              而不是   

        OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy

         )

              OR NOT bWrite

              然后

              iStep:=cStepSetJointsStrReset;

        ELSIF OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError           

          然后

              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

              然后

              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;

              否则

                   iStep:=cStepSetJointStrDelay;

              END_IF;

        END_IF

       

   cStepGetItemError:

        Item_ID:=0;

        iStep:=cStepWaitReset;

  

   cStepGetJointsError:

        FOR i :=0 TO 11 DO

              arrJoints[i]:=-99999.99;

        结束

        iStep:=cStepWaitReset;

       

   cStepGetJointsStrError:

        strJoints:='';

        iStep:=cStepWaitReset;

       

   cStepWaitReset:

        IF bReset THEN

              iStep:=cStepInit;

              bReset:=FALSE;

        END_IF;  

结束

 

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

退出;

END_IF

结束

 

FOR i :=1 TO 6 DO

   arrJointsFromStr[i]:=STRING_TO_LREAL(aSplit[i]);

END_FOR;

 

//

OPCUA_VirtualClient_RoboDK_Station.getItem(

bExecute:=iStep=cStepGetItem

项目名称:=机器人名称

);

 

 

OPCUA_VirtualClient_RoboDK_Station.getJoints(

bExecute:=iStep=cStepGetJoints

,Item_ID:=Item_ID,Joints=>arrJoints

);

 

 

OPCUA_VirtualClient_RoboDK_Station.getJointsStr(

bExecute:=iStep=cStepGetJointsStr

,机器人名称:=Robot_name,关节=>strJoints

);

 

IF bWrite THEN

OPCUA_VirtualClient_RoboDK_Station.setJointsStr(

   bExecute:=TRUE

   ,Robot_name:=Robot_name,关节:=strJointsCommand);

END_IF;

OPC UA 客户端示例

本例将向您展示如何在 RoboDK 中添加 OPC-UA 客户端连接。RoboDK包含一个OPC-UA插件,允许您在RoboDK项目中添加OPC UA兼容性。

在本示例中,您将学习如何通过 OPC UA 客户端从 RoboDK 站获取数据。

注:您可以通过右键单击台根并选择台站参数来删除台站参数。

OPC UA - 图片 63

显示 "台站参数 "屏幕,按 "全部清除 "删除所有台站参数。

OPC UA - 图片 64

使用接口

我们可以再创建一个 RoboDK 项目,配置并启动OPC UA 服务器。

OPC UA - 图片 65

添加插件

本节介绍如何添加 OPC UA 客户端。

输入端点 URL,例如:opc.tcp://127.0.0.1:48441。

您需要将 IP 地址和端口配置与目标 OPC UA 服务器相匹配。

OPC UA - 图片 66

按 "连接 "建立连接。

如果出现 "已检索到服务器变量。右键单击台站项并选择 "台站参数 "以查看变量",则连接已建立。

OPC UA - 图片 67

右键单击管理平台,选择 "管理平台参数"。

OPC UA - 图片 68

客户端节点

您可以从节点部分查看每个节点的详细信息。

OPC UA - 图片 69

使用 RoboDK API

通过 RoboDK 中的 OPC UA 客户端从 OPC UA 服务器获取节点数据后,还可以使用 RoboDK-Python-API 获取这些数据。

安装

您可以参考此链接来安装 RoboDK PythonAPI。

https://robodk.com/doc/en/PythonAPI/intro.html#how-to-install

或者手动为 Python 安装 RoboDK 包:

pip install robodk

脚本

本示例脚本展示了如何通过RoboDK 的 Python API 获取站参数。

from robodk import robolink # RoboDK API

 

RDK = robolink.Robolink()

 

from robodk import * # RoboDK API

from robolink import * # 机器人工具箱

itemlist = RDK.ItemList()

如果 itemlist:

# 获取所有台站参数

print('Vaild Paramaters are configured in your Station...')

StationParameters=RDK.getParams()

for StationParameter in StationParameters:

print("Station Parameters %s : %s"%(StationParameter[0],str((StationParameter[1]))))

否则

print('No Parameter list...')

下面是示例脚本的结果:

虚拟参数在您的站台中配置...

工作站参数 RoboDK : RoboDK 64 位 v5.5.3.23031

站参数时间 : 02/14/2023 03:58:29.191.000.000

台站参数模拟速度:13.8551

台站参数台站:MyTestStation