Implementation with Beckhoff TwinCAT 3

You can use Beckhoff TwinCAT 3 software to test the connectivity with the RoboDK OPC UA Server.

Add TwinCAT3 Server

You can start by creating the OPC UA Client byselecting I/O>Devices>Add New Item.

OPC UA - Image 48

Select Virtual OPC UA Device from OPC >OK.

OPC UA - Image 49

OPC UA Virtual is inserted.

OPC UA - Image 50

We need to add an OPC UA Client to access the RoboDK OPC UA Server.

Select Device 1 >Right Click >Add New Item.

OPC UA - Image 51

Select “OPC UA Client(Module)” and Ok.

OPC UA - Image 52

OPC UA Client is inserted.

OPC UA - Image 53

Configure the Server

Open the OPC UA Client >Go to Settings Tab>click the “Select Endpoint” to configure the OPC UA Server endpoint that you would like to access.

OPC UA - Image 54

Enter the RoboDK OPC UA server URL and Update it.

OPC UA - Image 55

Add RoboDK Server Method

Press “Add Nodes” to browse the node that is inside the OPC UA Server.

OPC UA - Image 56

If the connection between TwinCAT and OPC UA Server is established, you can Browse the details of OPC UA server.

OPC UA - Image 57

Select all Methods and Ok.

OPC UA - Image 58

Methods are inserted in your Configuration.

OPC UA - Image 59

Auto Generate RoboDK Method

Configure your Name Prefix in this field.

OPC UA - Image 60

Press “Create Plc Code” to create the PLC Code from TwinCAT.

OPC UA - Image 61

An OpcUaClient folder is created in your project, and all RoboDK Method are created in IEC61131-3 Function Block format.

OPC UA - Image 62

PLC Program Example

This section shows a sample program of a Beckhoff TwinCAT PLC that communicates with RoboDK OPC UA server.

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;