OPC-UA

启用OPC-UA外接程序

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

RoboDK包含OPC-UA插件,允许您将OPC UA兼容性添加到RoboDK项目中。

默认情况下,RoboDK禁用OPC-UA插件。一旦启用,每次启动RoboDK时都应该显示外接程序。

您可以通过以下步骤启用OPC UA加载项:

1.选择Tools-Add-ins。

2.双击OPC-UA。

您应该看到带有OPC-UA特性的附加工具栏。

//www.x7093.com/addin/com.robodk.plugin.opc-ua

OPC UA -图像1OPC UA -图像2

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

OPC UA -图像3

OPC UA服务器示例

在本例中,您将学习如何启用OPC UA插件,并将RoboDK转换为OPC UA服务器。我们将使用UaExpert软件和倍福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 -图像6

如果您看到诸如“RoboDK的OPC UA服务器在端口4840上运行”这样的消息,这意味着RoboDK中的OPC UA服务器已经启动。

创建自己的站点

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

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

展开自定义发现并选择<双击添加服务器。>选项,添加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

SimulationSpeed

“模拟速度”是一个节点,它显示实际的模拟速度,并允许用户覆盖当前的模拟速度。

OPC UA -图片18

节点值参考仿真速度的滑动条。

当前的仿真可以从该节点读取,并可以覆盖仿真速度。

OPC UA -图19

站点节点是允许用户在RoboDK中获取当前站点名称的节点。

OPC UA -图20

如下所示,站节点引用了RoboDK中的“站名”。

OPC UA -图片21

站参数/站值

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

OPC UA -图片22

您可以通过右键单击您的RoboDK Station>Station参数来查看您的Station参数。

OPC UA -图片23

在Constant parameters字段中,您可以看到默认的站参数及其值。

OPC UA -图片24

站参数引用“参数”字段,站值引用“值”字段。

OPC UA -图片25

我们可以通过点击“添加”按钮创建自己的参数。

OPC UA -图片26

添加了一个新的Station参数。

OPC UA -图片27

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

OPC UA -图片28

你也可以得到你自己的站参数。

OPC UA -图29

时间

节点时间是一个节点,用于获取RoboDK站的当前时间。

OPC UA -图像30

返回DataTime格式的值。

OPC UA -图片31

这个节点是不断更新的。

OPC UA -图片32

方法

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

我们只需右击方法>Call来执行该方法。

OPC UA -图片33

getItem

getItem是一个方法,它允许用户获取你的Item的指针。

OPC UA -图片34

对于InputArguments,设备名称是必需的,你可以想象设备名称是你的工作站名称,机器人名称等。Item ID是返回该设备指针的OutputArguments。

OPC UA -图片35

在这个例子中,我收到了我的ABB机器人的项目ID(指针),命名为“ABB_RB1”。

OPC UA -图片36

如果项目名称无效或在您的站点中不存在,则返回0。

OPC UA -图片37

getJoints

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

OPC UA -图片38

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

OPC UA -图片39

我们将获得这个“ABB_RB1”项目名称的项目ID,并返回一个UInt64值。

OPC UA -图片40

关节值在传递前一个方法中的Item ID时返回。

OPC UA -图片41

getJointsStr

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

OPC UA -图片42

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

OPC UA -图片43

在My Station中,ABB_RB1是我的机器人的名字。

OPC UA -图片44

我们可以在Robot name参数中传递" ABB_RB1 ",并调用方法-返回String格式的joint值。

OPC UA -图片45

setJointsStr

setJointsStr是一个方法,允许用户基于一个字符串值来设置机器人的关节值。

OPC UA -图片46

在Robot名称中,传递的是ABB_RB1,我们可以在关节参数中传递一个带有关节值的字符串。

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

OPC UA -图47

Beckhoff TwinCAT3实现

添加服务器

现在我们可以通过I/O>Devices>Add New Item插入OPC UA Client。

OPC UA -图片48

在“OPC >OK”中选择“Virtual OPC UA Device”。

OPC UA -图49

OPC UA Virtual插入。

OPC UA -图像50

我们需要添加一个OPC UA Client来访问RoboDK OPC UA Server。

选择设备1 >右键单击>添加新项目。

OPC UA -图片51

选择“OPC UA客户端(模块)”,确定。

OPC UA -图片52

已插入OPC UA Client。

OPC UA -图片53

配置服务器

打开OPC UA客户端>进入“设置”页签>单击“选择端点”,配置您想访问的OPC UA服务器端点。

OPC UA -图片54

输入“RoboDK OPC UA服务器URL”并“Update it”。

OPC UA -图片55

添加RoboDK Server Method

按“添加节点”键浏览OPC UA服务器内部的节点。

OPC UA -图片56

如果TwinCAT与OPC UA Server建立连接,则可以浏览OPC UA Server的详细信息。

OPC UA -图57

选择所有的方法并确定。

OPC UA -图片58

方法被插入到配置中。

OPC UA -图片59

自动生成RoboDK方法

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

OPC UA -图像60

按“Create Plc Code”从TwinCAT创建Plc Code。

OPC UA -图片61

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

OPC UA -图像62

PLC程序示例

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

项目主要

VAR

bConnected: BOOL;

StationPointer:力;

iStep: INT;

bStart: BOOL;;

我:INT;

吨:吨;

bReset: BOOL;

bWrite: BOOL;

TON2:吨;

bShow: BOOL: = TRUE;

英属维尔京群岛:BOOL: = True;

END_VAR

VAR

Robot_name: STRING(80): =“ABB_RB1”;

Item_ID: ULINT;

arrJoints: ARRAY [0 . .LREAL 11);

strJoints:字符串(80):= ";

arrJointsFromStr: ARRAY [1 . .LREAL 11);

sSeparator:STRING(1):= ',';

arrJointsCommand: ARRAY [1 . .LREAL 11);

strJointsCommand:字符串(80);

END_VAR

VAR常数

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]的字符串(80);

bResultSplit: BOOL;

调试: BOOL;

URL:字符串:= ' http://192.168.3.42:8091 ';

END_VAR

bConnected: = OPCUA_VirtualClient_RoboDK_Station.bConnected;

CASE iStep

cStepWaitCmd:

IF bStart THEN

iStep: = cStepInit;

bStart: = FALSE;

END_IF

cStepInit:

StationPointer: = 0;

对于i:=1到11做

arrJoints[我]:= 0.0;

arrJointsFromStr[我]:= 0.0;

aSplit[我]:= ";

END_FOR

如果不是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:

如果OPCUA_VirtualClient_RoboDK_Station.getItem。bDone然后

iStep: = cStepGetItemReset;

Item_ID: = OPCUA_VirtualClient_RoboDK_Station.getItem.Item_ID;

ELSIF OPCUA_VirtualClient_RoboDK_Station.getItem。bError然后

iStep: = cStepGetItemError;

END_IF

cStepGetItemReset:

如果不是OPCUA_VirtualClient_RoboDK_Station.getItem.bError

AND NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bBusy

然后

iStep: = cStepGetJoints;

END_IF

cStepGetJoints:

如果OPCUA_VirtualClient_RoboDK_Station.getJoints.bDone

AND NOT OPCUA_VirtualClient_RoboDK_Station.getJoints.bBusy

然后

iStep: = cStepGetJointsReset;

ELSIF OPCUA_VirtualClient_RoboDK_Station.getJoints。bError然后

iStep: = 991;

END_IF

cStepGetJointsReset:

如果不是OPCUA_VirtualClient_RoboDK_Station.getItem.bError

AND NOT OPCUA_VirtualClient_RoboDK_Station.getItem.bBusy

然后

iStep: = cStepGetJointsStr;

END_IF;

cStepGetJointsStr:

如果OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bDone

AND NOT OPCUA_VirtualClient_RoboDK_Station.getJointsStr.bBusy

然后

iStep: = cStepGetJointsStrReset;

ELSIF OPCUA_VirtualClient_RoboDK_Station.getJointsStr。bError然后

iStep: = cStepGetJointsStrError;

END_IF

cStepGetJointsStrReset:

如果不是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 (: = TRUE, PT: = T # 0.2秒);

如果TON2。问那么

TON2 (: = FALSE);

iStep: = cStepSetJointsStr;

END_IF

cStepSetJointsStr:

如果(

OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bDone

而不是

OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy

或不写

然后

iStep: = cStepSetJointsStrReset;

ELSIF OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError

然后

iStep: = cStepSetJointsStrError;

END_IF

cStepSetJointsStrReset:

bWrite: = FALSE;

OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bExecute: = FALSE;

如果不是OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bError

AND NOT OPCUA_VirtualClient_RoboDK_Station.setJointsStr.bBusy

然后

iStep: = cStepEnd;

END_IF;

cStepEnd:

吨(:= TRUE, PT: = T # 0.1秒);

如果吨。问那么

吨(:= FALSE);

如果不是调试

iStep: = 10;

其他的

iStep: = cStepSetJointStrDelay;

END_IF;

END_IF

cStepGetItemError:

Item_ID: = 0;

iStep: = cStepWaitReset;

cStepGetJointsError:

对于i:=0到11做

arrJoints[我]:= -99999.99;

END_FOR

iStep: = cStepWaitReset;

cStepGetJointsStrError:

strJoints: = ";

iStep: = cStepWaitReset;

cStepWaitReset:

IF bReset THEN

iStep: = cStepInit;

bReset: = FALSE;

END_IF;

END_CASE

aSplit[1]:= strjoint;

对于i:=1到7做

bResultSplit:= findsplit (

pSeparator:= ADR(sSeparator)

,pSrcString:= ADR(aSplit[i])

pLeftString: = ADR (aSplit[我])

,nLeftSize:= SIZEOF(aSplit[i])

pRightString: = ADR (aSplit (i + 1))

,nRightSize:= SIZEOF(aSplit[i+1])

,bSearchFromRight:= FALSE);

如果不是bResultSplit那么

退出;

END_IF

END_FOR

对于i:=1到6做

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

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关节= > arrJoints

);

OPCUA_VirtualClient_RoboDK_Station.getJointsStr (

bExecute: = iStep = cStepGetJointsStr

Robot_name: = Robot_name关节= > strJoints

);

IF bWrite THEN

OPCUA_VirtualClient_RoboDK_Station.setJointsStr (

bExecute: = TRUE

Robot_name: = Robot_name关节:= strJointsCommand);

END_IF;

OPC UA客户端示例

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

在本例中,您将学习如何通过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

节点

中查看每个Node的详细信息节点部分。

OPC UA -图片69

使用RoboDK API实现

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

安装

您可以引用此链接来安装RoboDK Python-API。

//www.x7093.com/doc/en/PythonAPI/intro.html#how-to-install

或者手动安装Python的robodk包:

PIP安装robodk

脚本

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

从robodk导入robolink # robodk API

RDK = robolink.Robolink()

从robodk导入# robodk API

从robolink导入* #机器人工具箱

itemlist = RDK.ItemList()

如果itemlist:

#获取所有站点参数

打印('有效的参数已配置在您的站点..')

StationParameters = RDK.getParams ()

对于StationParameters中的StationParameter:

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

其他:

print('无参数列表..')

下面是脚本示例的结果:

站内已配置有效参数。

站点参数RoboDK: RoboDK 64位v5.5.3.23031

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

仿真速度:13.8551

站点参数:MyTestStation