Beckhoff#TwinCAT3 TF6100 OPCUA _Part3_PLCOPEN Library

This time, I would like to introduce how to connect OPC UA Server via PLC OPEN library, read/write Node, and call Method. First, here is a list of what Function Blocks are required to use each function.

If you are familiar with how to use this PLC OPEN library,the theory is same as other plc , such as Siemens, let’s learn it .

Support DataType

Add the library

As I mentioned earlier, this time we will use the PLC Open function block to connect and exchange data with the OPC UA server, so let’s add the library first.

PLC>Your Project>Reference>Add library.

Search for PLCOPEN_OPCUA and you will find Tc3_PLCopen_OpcUA,3.x.x.x.Select the library and click OK.

Connect/Disconnenct

Let’s start with the simplest functions, Connect and Disconnect. The Function Blocks to use are UA_Connect and UA_Disconnect。

UA_Connect

VAR_INPUT
ExecuteBOOLExecute with a positive edge
ServerUrlSTRING(MAX_STRING_LENGTH)OPC UA Server URL
SessionConnectInfoST_UASessionConnectInfoconnection configuration data
TimeoutTIMEtime out setting
VAR_OUTPUT
ConnectionHdlDWORDOPCUA Connection HandleOther Blocks are also used with important variables.
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID

UA_Disconnect

VAR_INPUT
ExecuteBOOLExecute with a positive edge
ConnectionHdlDWORDOPCUA Connection Handle
TimeoutTIMEDisconnect Timeout設定
VAR_OUTPUT
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID

Shouldn’t we just proceed to the program analysis of Node value reading at once? Some people may think that, but I believe that everything starts with simplicity. And if you slowly understand the theories and principles behind it, this process will surely come in handy when you do something else “new”.

So, Here is the flow diagram below:

  • Using UA_Connect to establish the connection with OPC UA Server
  • Using Some Function Block to exchange the data with OPC UA Server
  • Using UA_Dissconnect to disconnect the connection with OPC UA Server

Let’s clear Connect and Disconnect first.

And when using UA_Connect, the OPC UA Server first needs those two important pieces of information.

  • Server URL
  • Session Connect Information


Server URL

Where can I find the Server URL? I think so. I may get information from the customer, and I’m using the same OPC UA Server Demo as last time, so

The URL will be opc.tcp://DESKTOP-7FE1JP2:48010.

Session Connect Information

Session Connect Information was also introduced in the Function Blocks of UA_Connect introduced earlier.

ST_UASessionConnectInfo
sApplicationUriSTRING(MAX_STRING_LENGTH)Application URL(<=255 characters)
sApplicationNameSTRING(MAX_STRING_LENGTH)application name(<=255 characters)
eSecurityModeE_UASecurityMsgModeSecurity Mode setting
eSecurityPolicyUriE_UASecurityPolicySecurity policy setting
eTransportProfileUriE_UATransportProfileTransport Profile settings
tSessionTimeoutTIMESession Timeout time
tConnectTimeoutTIMEConnection timeout time

E_UASecurityMsgMode

  • eUASecurityMsgMode_BestAvailable := 0,
  • eUASecurityMsgMode_None          := 1,
  • eUASecurityMsgMode_Sign          := 2,
  • eUASecurityMsgMode_Sign_Encrypt  := 3;

E_UASecurityPolicy

  • eUASecurityPolicy_BestAvailable := 0
  • eUASecurityPolicy_None := 1,
  • eUASecurityPolicy_Basic128      := 2,
  • eUASecurityPolicy_Basic128Rsa15 := 3,
  • eUASecurityPolicy_Basic256      := 4

E_UATransportProfile

  • eUATransportProfileUri_UATcp             := 1,
  • eUATransportProfileUri_WSHttpBinary      := 2,
  • eUATransportProfileUri_WSHttpXmlOrBinary := 3,
  • eUATransportProfileUri_WSHttpXml         := 4

Code

That’s it for the description. Let’s start writing the program and here is the flow:

VAR

Instances for UA_CONNECT and UA_Disconnect are defined in the VAR Area.

I also mentioned earlier that UASessionInfo is a variable required to use the UA_Connect Block.And iState is the variable that manages the connection>do something>disconnect flow.There are also bError and others that indicate the Block execution status.

The array Timer is used as a delay from Disconnect to reconnect.

VAR
UA_CONNENT :UA_CONNECT;
UASessionInfo :ST_UASessionConnectInfo;
UA_Disconnect :UA_Disconnect;

iState :INT;
bError :BOOL;
bDone :BOOL;
bBusy :BOOL;
bReset :BOOL;
nErrorID :DWORD;
nConnectionHdi :DWORD;

arrTON :ARRAY[0..3]OF TON;

END_VAR

VAR CONSTANT

This is a constant of the iState Step number, Timeout, and OPCUA Server URL.

VAR CONSTANT

ciStep_Parameters_Initlize :INT :=0;
ciStep_UAConnect     :INT :=10;
ciStep_UADIsconnect :INT :=20;
ciStep_End :INT :=7000;

ciStep_UAError :INT :=9000;


ctUASession_Connect_Timeout :TIME :=T#1M;
ctUASession_Session_Timeout :TIME :=T#1M;
ctUAConnect_Timeout :TIME :=T#5S;

cstServerURL :STRING :=’opc.tcp://DESKTOP-7FE1JP2:48010′;

END_VAR

PROGRAM

The program is the same as the Flow Chart.

CASE iState OF

ciStep_Parameters_Initlize:
bError:=FALSE;
bDone:=FALSE;
bBusy:=FALSE;
nErrorID:=0;
UASessionInfo.tConnectTimeout:=ctUASession_Connect_Timeout;
UASessionInfo.tSessionTimeout:=ctUASession_Session_Timeout;
UASessionInfo.eSecurityMode:=eUASecurityMsgMode_None;
UASessionInfo.eSecurityPolicyUri:=eUASecurityPolicy_None;
UASessionInfo.eTransportProfileUri:=eUATransportProfileUri_UATcp;
iState:=ciStep_UAConnect;

ciStep_UAConnect:
UA_CONNENT(
Execute:=TRUE
,ServerUrl:=cstServerURL
,SessionConnectInfo:=UASessionInfo
,Timeout:=ctUAConnect_Timeout
,ConnectionHdl=>nConnectionHdi
);
IF UA_CONNENT.Done AND NOT UA_CONNENT.Error THEN
iState:=ciStep_UADIsconnect;
UA_CONNENT(
Execute:=FALSE
);
ELSIF UA_CONNENT.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_CONNENT.ErrorID;
END_IF
ciStep_UADIsconnect:
UA_Disconnect(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
);
IF UA_Disconnect.Done AND NOT UA_Disconnect.Error THEN
iState:=ciStep_End;
ELSIF UA_Disconnect.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_Disconnect.ErrorID;
END_IF

ciStep_End:
arrTON[0](
IN:=TRUE
,PT:=T#2S
);
IF arrton[0].Q THEN
arrton[0](
IN:=FALSE
);
iState:=ciStep_UAConnect;
END_IF

ciStep_UAError:
bError:=TRUE;
IF bReset THEN
iState:=ciStep_Parameters_Initlize;
END_IF;

END_CASE

Polling (Read)

Now that we do the Polling,and it can reads and writes Nodes from the UA Name space.

In the actual flow, a connection is established with UA_Connect, Namespace is obtained with UA_GetNamespaceIndex > Handle is obtained > Node value is read > Handle is released > Disconnect.

UA_GetNamespaceIndex

VAR_INPUT
ExecuteBOOLExecute with a Positive edge
ConnectionHdlDWORDOPCUA Connection Handle
NamespaceUriSTRING(MAX_STRING_LENGTH)Specify NamespaceURL. With TwinCAT Server,urn:BeckhoffAutomation:Ua:PLC1 is used,
TimeoutTIMEDisconnect Timeout setting
VAR_OUTPUT
NamespaceIndexUINTThe Namesapce numbers that will be used in UA_Read,etc.
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID

UA_NodeGetHandle

VAR_INPUT
ExecuteBOOLExecute with a Positive edge
ConnectionHdlDWORDOPCUA Connection Handle
NodeIDST_UANodeIDThe index that you got from UA_GetNamesapceIndex
TimeoutTIMEDisconnect Timeout Setting
VAR_OUTPUT
NamespaceIndexUINTThe Namesapce numbers that will be used in UA_Read,etc.
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID

UA_Read

VAR_INPUT
ExecuteBOOLExecute with a Positive edge
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeIDThe index that you got from UA_GetNamesapceIndex
stNodeAddInfoST_UANodeAdditionalInfoThe node settings
pVariablePVOIDMemory Pointer
cbDataUDINTThe size of node that you need to read(bytes)
TimeoutTIMETimeout setting
VAR_OUTPUT
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID
cbData_RUDINTTotal Bytes that is read

UA_NodeReleaseHandle

VAR_INPUT
ExecuteBOOLExecute with a Positive edge
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeIDThis is the Index obtained from the previous UA_GetNamesapceIndex.
TimeoutTIMETimeout setting
VAR_OUTPUT
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID


NamespaceURI

When you looked at the UA_GetNamesapceIndex Function Block, there was a NamespaceUri parameter, right?

If you make a mistake in that, the subsequent Handle and Read Function Blocks will result in execution errors, so I would like to explain here.

Open UAExpert and connect to OPC UA Server and browse Server>NamespaceArray.

Then you will get an array of strings. Note that the Namespace will change depending on the Node you want to access later.

For example I want to access Demo>000_Static>Scalar>Int16.

If you browse this Node, you will see that NamespaceIndex is 2.

So the NamespaceUrl will use the second URL.

Node Identifier

Next, UA_NodeGetHandle has a parameter called NodeID. Its NodeID is defined from the DUT called ST_UANodeID.

ST_UANodeID

  • nNamespaceIndex  : UINT;
  • nReserved        : ARRAY [1..2] OF BYTE; //fill bytes
  • sIdentifier      : STRING(MAX_STRING_LENGTH);
  • eIdentifierType  : E_UAIdentifierType;
    • E_UAIdentifierType
      • eUAIdentifierType_String  := 1,
      • eUAIdentifierType_Numeric := 2,
      • eUAIdentifierType_GUID    := 3,
      • eUAIdentifierType_Opaque  := 4

nNamespaceIndex puts the NameIndex obtained from UA_GetNamesapceIndex.

eIdentifierType needs to be defined with String or Number. (IdentifierType in the figure below)For sIdentifier, just copy the Identifier value in the figure below.

Code

Here is the flow.

VAR

VAR
//Connect/DisConnect Functionality
UA_CONNENT :UA_CONNECT;
UASessionInfo :ST_UASessionConnectInfo;
UA_Disconnect :UA_Disconnect;

//Polling Functionlity
//Get NameIndex
UA_GetNamespaceIndex:UA_GetNamespaceIndex;
nNameSpaceIndex :UINT;
//Get Handle
UA_NodeGetHandle:UA_NodeGetHandle;
NodeID :ST_UANodeID;
nNodeHdl :DWORD;
//UA Read
UA_Read :UA_Read;
stIndexRange : ARRAY [1..nMaxIndexRange] OF ST_UAIndexRange;
nIndexRangeCount : UINT;
stNodeAddInfo : ST_UANodeAdditionalInfo;
nReadData : INT;
cbDataRead : UDINT;
//UA Node Release Handle
UA_NodeReleaseHandle : UA_NodeReleaseHandle;

iState :INT;
bError :BOOL;
bDone :BOOL;
bBusy :BOOL;
bReset :BOOL;
bInit :BOOL;
nErrorID :DWORD;
nConnectionHdi :DWORD;

arrTON :ARRAY[0..3]OF TON;

END_VAR

VAR_CONSTANT

VAR CONSTANT

ciStep_Parameters_Initlize :INT :=0;
ciStep_UAConnect :INT :=10;

ciStep_UAGetNamespaceIndex :INT :=20;
ciStep_UAGetHandle :INT :=30;
ciStep_UARead :INT :=40;
ciStep_UARelease :INT :=50;

ciStep_UADIsconnect :INT :=100;
ciStep_End :INT :=7000;

ciStep_UAError :INT :=9000;


ctUASession_Connect_Timeout :TIME :=T#1M;
ctUASession_Session_Timeout :TIME :=T#1M;
ctUAConnect_Timeout :TIME :=T#5S;

cstServerURL :STRING :=’opc.tcp://DESKTOP-7FE1JP2:48010′;

END_VAR

PROGRAM

CASE iState OF

ciStep_Parameters_Initlize:
bError:=FALSE;
bDone:=FALSE;
bBusy:=FALSE;
nErrorID:=0;
UASessionInfo.tConnectTimeout:=ctUASession_Connect_Timeout;
UASessionInfo.tSessionTimeout:=ctUASession_Session_Timeout;
UASessionInfo.eSecurityMode:=eUASecurityMsgMode_None;
UASessionInfo.eSecurityPolicyUri:=eUASecurityPolicy_None;
UASessionInfo.eTransportProfileUri:=eUATransportProfileUri_UATcp;
stNodeAddInfo.nIndexRangeCount := nIndexRangeCount;
      stNodeAddInfo.stIndexRange := stIndexRange;
UA_CONNENT(
Execute:=FALSE
);
UA_Disconnect(
Execute:=FALSE
);
UA_GetNamespaceIndex(
Execute:=FALSE
);
UA_NodeGetHandle(
Execute:=FALSE
);
UA_Read(
Execute:=FALSE
);
UA_NodeReleaseHandle(
Execute:=FALSE
);
IF NOT UA_CONNENT.Busy
AND NOT UA_Disconnect.Busy
AND NOT UA_GetNamespaceIndex.Busy
AND NOT UA_NodeGetHandle.Busy
AND NOT UA_Read.Busy
AND NOT UA_NodeReleaseHandle.Busy
THEN
iState:=ciStep_UAConnect;
END_IF;


ciStep_UAConnect:
UA_CONNENT(
Execute:=TRUE
,ServerUrl:=cstServerURL
,SessionConnectInfo:=UASessionInfo
,Timeout:=ctUAConnect_Timeout
,ConnectionHdl=>nConnectionHdi
);
IF UA_CONNENT.Done AND NOT UA_CONNENT.Error THEN
iState:=ciStep_UAGetNamespaceIndex;
UA_CONNENT(
Execute:=FALSE
);
ELSIF UA_CONNENT.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_CONNENT.ErrorID;
END_IF


ciStep_UAGetNamespaceIndex:
UA_GetNamespaceIndex(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NamespaceUri :=’http://www.unifiedautomation.com/DemoServer/’
,NamespaceIndex=>nNameSpaceIndex
);
IF UA_GetNamespaceIndex.Done AND NOT UA_GetNamespaceIndex.Error THEN
UA_GetNamespaceIndex(
Execute:=FALSE
);
iState:=ciStep_UAGetHandle;
ELSIF UA_GetNamespaceIndex.Error THEN
nErrorID:=UA_GetNamespaceIndex.ErrorID;
iState:=ciStep_UAError;
END_IF



ciStep_UAGetHandle:
NodeID.eIdentifierType:=eUAIdentifierType_String;
NodeID.nNamespaceIndex:=nNameSpaceIndex;
NodeID.sIdentifier:=’Demo.Static.Scalar.Int16′;
UA_NodeGetHandle(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeID:=NodeID
,NodeHdl=>nNodeHdl
);
IF UA_NodeGetHandle.Done AND NOT UA_NodeGetHandle.Error THEN
UA_NodeGetHandle(
Execute:=FALSE
);
iState:=ciStep_UARead;
ELSIF UA_NodeGetHandle.Error THEN
nErrorID:=UA_NodeGetHandle.ErrorID;
iState:=ciStep_UAError;
END_IF

ciStep_UARead:
UA_Read(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeHdl:=nNodeHdl
,cbData:=SIZEOF(nReadData)
,stNodeAddInfo:=stNodeAddInfo
,pVariable:=ADR(nReadData)
);
IF UA_Read.Done AND NOT UA_Read.Error THEN
UA_Read(
Execute:=FALSE
,cbData_R=>cbDataRead
);
iState:=ciStep_UARelease;
ELSIF UA_Read.Error THEN
nErrorID:=UA_Read.ErrorID;
iState:=ciStep_UAError;
END_IF;



ciStep_UARelease:
UA_NodeReleaseHandle(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeHdl:=nNodeHdl
);
IF UA_NodeReleaseHandle.Done AND NOT UA_NodeReleaseHandle.Error THEN
UA_NodeReleaseHandle(
Execute:=FALSE
);
iState:=ciStep_End;
ELSIF UA_NodeReleaseHandle.Error THEN
nErrorID:=UA_NodeReleaseHandle.ErrorID;
iState:=ciStep_UAError;
END_IF

ciStep_UADIsconnect:
UA_Disconnect(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
);
IF UA_Disconnect.Done AND NOT UA_Disconnect.Error THEN
iState:=ciStep_End;
ELSIF UA_Disconnect.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_Disconnect.ErrorID;
END_IF




ciStep_End:
arrTON[0](
IN:=TRUE
,PT:=T#2S
);
IF arrton[0].Q THEN
arrton[0](
IN:=FALSE
);
iState:=ciStep_UAConnect;
END_IF

ciStep_UAError:
bError:=TRUE;
IF bReset THEN
iState:=ciStep_Parameters_Initlize;
END_IF;
END_CASE


Result

Currently the Node value is modified as 99.

Similarly, nReadData from UA_Read() is also 99.

Polling(Write)

Now we can operate the write function.

In the same flow as UA_Read, just change the Function Block to UA_Write().

UA_Write

VAR_INPUT
ExecuteBOOLExecute with a positive edge
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeIDThe index that get from UA_GetNamesapceIndex
stNodeAddInfoST_UANodeAdditionalInfoThe Node information
pVariablePVOIDMemory Pointer
cbDataUDINTThe total bytes that will write into the Node.
TimeoutTIMETimeout setting
VAR_OUTPUT
DoneBOOLFunction Block is executed without error
BusyBOOLFunction Block is executing
ErrorBOOLError is occupied 
ErrorIDDWORDThe Error ID
cbData_RUDINTThe total bytes are written in this request

Code

Here is the Flow.

VAR

VAR
//Connect/DisConnect Functionality
UA_CONNENT :UA_CONNECT;
UASessionInfo :ST_UASessionConnectInfo;
UA_Disconnect :UA_Disconnect;

//Polling Functionlity
//Get NameIndex
UA_GetNamespaceIndex:UA_GetNamespaceIndex;
nNameSpaceIndex :UINT;
//Get Handle
UA_NodeGetHandle:UA_NodeGetHandle;
NodeID :ST_UANodeID;
nNodeHdl :DWORD;
//UA Read
UA_Read :UA_Read;
stIndexRange : ARRAY [1..nMaxIndexRange] OF ST_UAIndexRange;
nIndexRangeCount : UINT;
stNodeAddInfo : ST_UANodeAdditionalInfo;
nReadData : INT;
cbDataRead : UDINT;
//UA Write
UA_Write : UA_Write;
nWriteData: INT := 0;
//UA Node Release Handle
UA_NodeReleaseHandle : UA_NodeReleaseHandle;

iState :INT;
bError :BOOL;
bDone :BOOL;
bBusy :BOOL;
bReset :BOOL;
bInit :BOOL;
nErrorID :DWORD;
nConnectionHdi :DWORD;

arrTON :ARRAY[0..3]OF TON;

END_VAR


VAR_CONSTANT

VAR CONSTANT

ciStep_Parameters_Initlize :INT :=0;
ciStep_UAConnect :INT :=10;

ciStep_UAGetNamespaceIndex :INT :=20;
ciStep_UAGetHandle :INT :=30;
ciStep_UARead :INT :=40;
ciStep_UARelease :INT :=50;
ciStep_UAWrite :INT :=60;

ciStep_UADIsconnect :INT :=100;
ciStep_End :INT :=7000;

ciStep_UAError :INT :=9000;


ctUASession_Connect_Timeout :TIME :=T#1M;
ctUASession_Session_Timeout :TIME :=T#1M;
ctUAConnect_Timeout :TIME :=T#5S;

cstServerURL :STRING :=’opc.tcp://DESKTOP-7FE1JP2:48010′;

END_VAR

PROGRAM

CASE iState OF

ciStep_Parameters_Initlize:
bError:=FALSE;
bDone:=FALSE;
bBusy:=FALSE;
nErrorID:=0;
UASessionInfo.tConnectTimeout:=ctUASession_Connect_Timeout;
UASessionInfo.tSessionTimeout:=ctUASession_Session_Timeout;
UASessionInfo.eSecurityMode:=eUASecurityMsgMode_None;
UASessionInfo.eSecurityPolicyUri:=eUASecurityPolicy_None;
UASessionInfo.eTransportProfileUri:=eUATransportProfileUri_UATcp;
stNodeAddInfo.nIndexRangeCount := nIndexRangeCount;
      stNodeAddInfo.stIndexRange := stIndexRange;
UA_CONNENT(
Execute:=FALSE
);
UA_Disconnect(
Execute:=FALSE
);
UA_GetNamespaceIndex(
Execute:=FALSE
);
UA_NodeGetHandle(
Execute:=FALSE
);
UA_Read(
Execute:=FALSE
);
UA_NodeReleaseHandle(
Execute:=FALSE
);
IF NOT UA_CONNENT.Busy
AND NOT UA_Disconnect.Busy
AND NOT UA_GetNamespaceIndex.Busy
AND NOT UA_NodeGetHandle.Busy
AND NOT UA_Read.Busy
AND NOT UA_NodeReleaseHandle.Busy
THEN
iState:=ciStep_UAConnect;
END_IF;


ciStep_UAConnect:
UA_CONNENT(
Execute:=TRUE
,ServerUrl:=cstServerURL
,SessionConnectInfo:=UASessionInfo
,Timeout:=ctUAConnect_Timeout
,ConnectionHdl=>nConnectionHdi
);
IF UA_CONNENT.Done AND NOT UA_CONNENT.Error THEN
iState:=ciStep_UAGetNamespaceIndex;
UA_CONNENT(
Execute:=FALSE
);
ELSIF UA_CONNENT.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_CONNENT.ErrorID;
END_IF


ciStep_UAGetNamespaceIndex:
UA_GetNamespaceIndex(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NamespaceUri :=’http://www.unifiedautomation.com/DemoServer/’
,NamespaceIndex=>nNameSpaceIndex
);
IF UA_GetNamespaceIndex.Done AND NOT UA_GetNamespaceIndex.Error THEN
UA_GetNamespaceIndex(
Execute:=FALSE
);
iState:=ciStep_UAGetHandle;
ELSIF UA_GetNamespaceIndex.Error THEN
nErrorID:=UA_GetNamespaceIndex.ErrorID;
iState:=ciStep_UAError;
END_IF



ciStep_UAGetHandle:
NodeID.eIdentifierType:=eUAIdentifierType_String;
NodeID.nNamespaceIndex:=nNameSpaceIndex;
NodeID.sIdentifier:=’Demo.Static.Scalar.Int16′;
UA_NodeGetHandle(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeID:=NodeID
,NodeHdl=>nNodeHdl
);
IF UA_NodeGetHandle.Done AND NOT UA_NodeGetHandle.Error THEN
UA_NodeGetHandle(
Execute:=FALSE
);
iState:=ciStep_UAWrite;
ELSIF UA_NodeGetHandle.Error THEN
nErrorID:=UA_NodeGetHandle.ErrorID;
iState:=ciStep_UAError;
END_IF

ciStep_UAWrite:
nWriteData:=nWriteData+1;
UA_Write(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeHdl:=nNodeHdl
,stNodeAddInfo:=stNodeAddInfo
,pVariable:=ADR(nWriteData)
,cbData:=SIZEOF(nWriteData)
);
IF UA_Write.Done AND NOT UA_Read.Error THEN
UA_Write(
Execute:=FALSE
,pVariable:=ADR(nWriteData)
);
iState:=ciStep_UARelease;
ELSIF UA_Write.Error THEN
nErrorID:=UA_Write.ErrorID;
iState:=ciStep_UAError;
END_IF;



ciStep_UARelease:
UA_NodeReleaseHandle(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
,NodeHdl:=nNodeHdl
);
IF UA_NodeReleaseHandle.Done AND NOT UA_NodeReleaseHandle.Error THEN
UA_NodeReleaseHandle(
Execute:=FALSE
);
iState:=ciStep_End;
ELSIF UA_NodeReleaseHandle.Error THEN
nErrorID:=UA_NodeReleaseHandle.ErrorID;
iState:=ciStep_UAError;
END_IF

ciStep_UADIsconnect:
UA_Disconnect(
Execute:=TRUE
,ConnectionHdl:=nConnectionHdi
);
IF UA_Disconnect.Done AND NOT UA_Disconnect.Error THEN
iState:=ciStep_End;
ELSIF UA_Disconnect.Error THEN
iState:=ciStep_UAError;
nErrorID:=UA_Disconnect.ErrorID;
END_IF



ciStep_End:
arrTON[0](
IN:=TRUE
,PT:=T#2S
);
IF arrton[0].Q THEN
arrton[0](
IN:=FALSE
);
iState:=ciStep_UAConnect;
END_IF

ciStep_UAError:
bError:=TRUE;
IF bReset THEN
iState:=ciStep_Parameters_Initlize;
END_IF;

END_CASE

Result

Please download the source code from this link:

https://github.com/soup01Threes/TwinCAT3/blob/main/TwinCAT%20Project_TF6100_Using_PLCOPEN_LIBRARY_1.tnzip

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする