Beckhoff#TwinCAT3 TF6100 OPCUA _Part3_PLCOPEN Library

みんなさんこんばんわ。あっという間にTwinCAT OPCUA TF6100の第4話になりました。

今回はPLC OPENライブラリ経由しOPC UA Serverを接続・Node読み書き・Method 呼び出しの方法を紹介したいと思います。まずこちらは各機能を使うにはどんなFunction Blocksが必要になるか、の一覧表になります。

このPLC OPEN ライブラリの使い方なれますと、Siemensなど他にPLC OPENライブラリが対応してるPLCメーカならやりかたほぼ同じなので、無理やゆるゆるで覚えましょう。

Support DataType

ライブラリ追加

先いった通り、今回はPLC Open function blockを使用しOPC UA サーバと接続やデータやりとりしますので、まずライブラリを追加しましょう。

PLC>Your Project>Refenerce>Add libraryします。

PLCOPEN_OPCUAを検索し、Tc3_PLCopen_OpcUA,3.x.x.xが出てきます。

そのライブラリ選び、OKします。

Connect/Disconnenct

では最初には一番簡単な機能のConnect・Disconnectから説明しましょう。使うFunction BlockはUA_ConnectとUA_Disconnectになります。

UA_Connect

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ServerUrlSTRING(MAX_STRING_LENGTH)OPC UA Server URL
SessionConnectInfoST_UASessionConnectInfo接続用の設定データ
TimeoutTIME接続Timeout設定
VAR_OUTPUT
ConnectionHdlDWORDOPCUA Connection Handle大事な変数で他のBlockも使われます。
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID

UA_Disconnect

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
TimeoutTIMEDisconnect Timeout設定
VAR_OUTPUT
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID

うん?一気にNode値読みのプログラム解析まで進めばいいじゃない?と思う人がいるかもしれませんが、なにことも簡単から始まります、と私が思っています。そしてゆっくりゆっくり中にの理論や原理わかってって、このプロセスは別の”新しい”ことやるときにもきっと役にたちます。

なので、下図も書いてますが、まず:

  • ”UA_Connect”で接続準備
  • なにかしらのFunction BlockでOPC Serverとやり取り
  • ”UA_Disconnect”でServerと切断

まずConnectとDisconnectをクリア行きましょう。

そして、UA_Connectを使うとき、OPC UA Serverにまずその2つ大事な情報が必要です。

  • Server URL
  • Session Connect Information

です。


Server URL

Server URLはどこで探せば良い?だと思いますね。客から情報もらうかもしれませんし、前回と同じのOPC UA Server Demoを使っていますので、

URLはopc.tcp://DESKTOP-7FE1JP2:48010になりますね。

Session Connect Information

Session Connect Informationは、先程紹介したUA_ConnectのFunction Blocks内にも紹介しましたよね。

ST_UASessionConnectInfo
sApplicationUriSTRING(MAX_STRING_LENGTH)アプリケーションURL(<=255文字)
sApplicationNameSTRING(MAX_STRING_LENGTH)アプリケーション名(<=255文字)
eSecurityModeE_UASecurityMsgModeセキュリティMode設定
eSecurityPolicyUriE_UASecurityPolicyセキュリティPolicy設定
eTransportProfileUriE_UATransportProfileTrasportのProfile設定
tSessionTimeoutTIMESession Timeout時間
tConnectTimeoutTIME接続Timeout時間

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

説明はそこまでです。プログラムを書き始まりましょう。

どうしてもながらくなりますので、最後まで一緒に見ましょう。

そしてInterfaceとProgramは分けて説明します。

VAR

UA_CONNECTとUA_DisconnectのInstanceの定義します。

UASessionInfoはUA_Connect Blockを使うのに必要な変数です、にも前書きました。

そしてiStateは接続>なにかやる>Disconnectの流れを管理する変数です。

Block実行状態を示すbErrorなどもあります。

配列のTimerはDisconnectから再接続するまでのDelayなど使われています。

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

こちらはiStateのStep番号・Timeout・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

こちらはIStateの番号によって違うBlockを呼び出します。

流れは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)

ConnectとDisconnectができたところで、次はPollingをやりますね。

つまりUA Name spaceからNodeを読み書きを行います。

実際の流れだとUA_ConnectでConnectionを確立し、UA_GetNamespaceIndexをNamespaceもらい>Handleをもらい>Node値を読む>Handleをリリース>Disconnectになりますね。

UA_GetNamespaceIndex

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
NamespaceUriSTRING(MAX_STRING_LENGTH)NamespaceURL指定します。TwinCAT Serverならurn:BeckhoffAutomation:Ua:PLC1
TimeoutTIMEDisconnect Timeout設定
VAR_OUTPUT
NamespaceIndexUINTNamespace番号。UA_Readなどは使わてています
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID

UA_NodeGetHandle

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
NodeIDST_UANodeID先のUA_GetNamesapceIndexでもらったIndexです。
TimeoutTIMEDisconnect Timeout設定
VAR_OUTPUT
NamespaceIndexUINTNamespace番号。UA_Readなどは使わてています
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID

UA_Read

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeID先のUA_GetNamesapceIndexでもらったIndexです。
stNodeAddInfoST_UANodeAdditionalInfoNodeの設定定義 例えばattribute内でどんな値を読むか
pVariablePVOIDMemory Pointer
cbDataUDINT読むNodeのData Size
TimeoutTIMETimeout設定
VAR_OUTPUT
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID
cbData_RUDINT何Byte読んでたか

UA_NodeReleaseHandle

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeID先のUA_GetNamesapceIndexでもらったIndexです。
TimeoutTIMETimeout設定
VAR_OUTPUT
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID


NamespaceURI

先UA_GetNamesapceIndexのFunction Blockをみたとき、NamespaceUriのパラメターがありますよね。

それが間違えますと、あとのHandleやReadのFunction Blockが実行エラーになりますので、ここで説明させていただきたいと思います。

UAExpertを開いて、OPC UA Serverと繋がります。

Server>NamespaceArrayをBrowseしてください。

そうすると文字列の配列が出てきます。のちほどでアクセスしたいNodeによってそのNamespaceが変わりますので、注意してください。

例えば、私はDemo>000_Static>Scalar>Int16をアクセスしたいと考えています。

このNodeをBrowseしますと、NamespaceIndexは2が入っていますよね。

つまり、NamespaceUrlは2番目のURLはを使用することになります。

Node Identifier

次は、UA_NodeGetHandleにはNodeIDというパラメタがあります。そのNodeIDはST_UANodeIDというDUTから定義されています。

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はUA_GetNamesapceIndexからもらったNameIndexを入れます。

eIdentifierTypeはStringか、Numberから定義すると設定します。(下図のIdentifierType)

sIdentifierは下図のIdentifierのValueをそのままCopyすればよいです。

Code

こちらはNode Readの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


結果

いまOPC UA Demo ServerではNode値は99です。

同じくUA_Read()からのnReadDataも99になります。

Polling(Write)

読み終わったら、次は書き込みですね。

UA_Readと同じの流れで、呼び出しのFunction BlockがUA_Write()に変わっただけになります。

UA_Write

VAR_INPUT
ExecuteBOOL立ち上げてコマンド実行
ConnectionHdlDWORDOPCUA Connection Handle
NodeHdlST_UANodeID先のUA_GetNamesapceIndexでもらったIndexです。
stNodeAddInfoST_UANodeAdditionalInfoNodeの設定定義 例えばattribute内でどんな値を読むか
pVariablePVOIDMemory Pointer
cbDataUDINT読むNodeのData Size
TimeoutTIMETimeout設定
VAR_OUTPUT
DoneBOOLエラーなしで実行OK
BusyBOOL実行中
ErrorBOOLエラーあり
ErrorIDDWORDエラーID
cbData_RUDINT何Byte読んでたか

Code

こちらはNode Readの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

結果

Sample Codeは以下でダウンロードしてください。

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

はーい、お疲れ様です。

もしなにか質問あれば、メール・コメント・Twitterなどでもどうぞ!

Twitterのご相談:@3threes2

メールのご相談:soup01threes*gmail.com (*を@に)

Footer_Basic

Find ME

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

シェアする

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

フォローする