Further Samples
The following samples show different types of application of the TwinCAT XML Data Servers. The PLC-project, which contains the samples, can be downloaded here.
Sample 5 shows an initialization once at program startup, Sample 6 shows cyclic and event-driven printing procedures. Both samples again use the structure ST_MYSTRUCT, which in turn includes ST_INNTERSTRUCT. Both Structures are shown in the following:
Structures
TYPE ST_MYSTRUCT:
STRUCT
fReal : REAL;
bBool : ARRAY [0..2] OF BOOL;
stInner : ST_INNTERSTRUCT;
END_STRUCT
END_TYPE
TYPE ST_INNTERSTRUCT:
STRUCT
nInteger : INT;
sString : STRING;
END_STRUCT
END_TYPE
Sample 5: Initialization once at program startup
Sample 5 shows the initialization of value1 once at program startup. Therefore FB_XmlSrvRead is used.
(* Sample5 reads and initializes value1 when the PLC is started FUNCTIONBLOCK: FB_XmlSrvRead *)
PROGRAM Sample5
VAR
value1 : ST_MyStruct;
fbXmlSrvRead : FB_XmlSrvRead;
bExecute : BOOL;
sFilePath : T_MaxString := 'C:\Test.xml'; (* CE: '\Hard Disk\Test.xml' *)
sXPath : T_MaxString := '/dataentry/MAIN.value1';
nState : INT := 0;
END_VAR
CASE nState OF
0: (* initialize *)
fbXmlSrvRead(
pSymAddr := ADR(value1),
cbSymSize := SIZEOF(value1),
sFilePath := sFilePath,
sXPath := sXPath,
bExecute := bExecute
);
fbXmlSrvRead(bExecute:= TRUE);
nState:= 1;
1: (* wait for read operation *)
fbXmlSrvRead(bExecute:= FALSE);
IF NOT fbXmlSrvRead.bBusy AND NOT fbXmlSrvRead.bError THEN
nState:= 2;
ELSIF fbXmlSrvRead.bError THEN
nState:= 100;
END_IF
2: (* operations *)
;
100:(* errorState *)
;
END_CASE
Sample 6: Cyclic and event-driven printing
The following sample creates a new XML file every 20 seconds and writes the above-mentioned structure to it. The filename is made up of the current windows-date, -time and the string sFileName. Furthermore, the printing procedure can be started by pressing a button (or setting the respective variable bButton). If the printing procedure is triggered twice a second, the latest file will be overwritten.
(* Sample6: Every 20s value1 will be written into a new XML-File named after the current date and
time. Furthermore you can activate the printing procedure by pressing a button (or setting the
corresponding variable *)
PROGRAM Sample6
VAR
value1 : ST_MyStruct;
fbXmlSrvWrite : FB_XmlSrvWrite;
sFileFolder : T_MaxString :='C:\'; (* CE: '\Hard Disk\' *)
sFileName : T_MaxString:= '_test.xml';
sFilePathWrite : T_MaxString
(*sFilePathWrite = sFileFolder + time + sFileName*)
sXPathWrite : T_MaxString :='/dataentry/MAIN.value1';
ntGetTime : NT_GetTime;
stMyTimestruct : TIMESTRUCT;
iState : INT := 1;
bTwentySec : BOOL:= FALSE;
bButton : BOOL:= FALSE;
bTwentySecOver : BOOL;
triggerWrite : R_TRIG;
triggerButton : R_TRIG;
END_VAR
triggerButton(CLK:= bButton);
CASE iState OF
0: (* idle state *)
;
1: (* initialize *)
fbXmlSrvWrite(nMode:=XMLSRV_ADDMISSING, pSymAddr:= ADR(value1),
cbSymSize:= SIZEOF(value1));
ntGetTime(START:= TRUE, TIMESTR=>stMyTimestruct); (* get Windows time *)IF NOT ntGetTime.BUSY AND NOT ntGetTime.ERR THEN
iState:= 2;
ELSIF ntGetTime.ERR THEN
iState:= 100;
END_IF
2: (* working state *)
(* change some values - replace with production-process *)
value1.stInner.nInteger:= value1.stInner.nInteger + 1;
IF value1.stInner.nInteger = 32767 THEN
value1.stInner.nInteger:= 0;
END_IF(* get Windows time *)
ntGetTime(START:= FALSE);
IF NOT ntGetTime.BUSY AND NOT ntGetTime.ERR THEN
ntGetTime(START:= TRUE, TIMESTR=>stMyTimestruct);
ELSIF ntGetTime.ERR THEN
iState:= 100;
END_IF(* check if 20s have passed*)IF stMyTimestruct.wSecond = 0 OR stMyTimestruct.wSecond = 20 OR stMyTimeStruct.wSecond = 40 THEN
bTwentySecOver:= TRUE;
ELSE
bTwentySecOver:= FALSE;
END_IF(* if 20s have passed => trigger writing-process *)
triggerWrite(CLK:=bTwentySecOver);
IF (triggerWrite.Q OR triggerButton.Q) AND NOT fbXmlSrvWrite.bBusy
AND NOT fbXmlSrvWrite.bError THEN (* create filename *)
sFilePathWrite:= CONCAT(sFileFolder, SYSTEMTIME_TO_STRING(stMyTimestruct)); (* set folder + time *)
sFilePathWrite:= DELETE(STR:= sFilePathWrite, LEN:= 4 ,
POS:= LEN(STR:=sFilePathWrite)-3); (* delete milliseconds *)
sFilePathWrite:= REPLACE(STR1:= sFilePathWrite , STR2:= '.' , L:= 1,
P:= LEN(STR:=sFilePathWrite)-2); (* replace colon with point *)
sFilePathWrite:= REPLACE(STR1:= sFilePathWrite , STR2:= '.' , L:= 1,
P:= LEN(STR:=sFilePathWrite)-5); (* replace colon with point *)
sFilePathWrite:= CONCAT(sFilePathWrite, sFileName); (* add filename (default: test) *)(* write *)
fbXmlSrvWrite(sFilePath:=sFilePathWrite, sXPath:=sXPathWrite, bExecute:= TRUE);
ELSIF fbXmlSrvWrite.bError THEN
iState:= 100;
END_IF(* reset fbXmlSrvWrite *)IF fbXmlSrvWrite.bBusy AND NOT ntGetTime.ERR THEN
fbXmlSrvWrite(bExecute:= FALSE);
ELSIF ntGetTime.ERR THEN
iState:= 100;
END_IF
100: (* error state*)
;
END_CASE
Requirements
Entwicklungsumgebung | Zielplattform | Einzubindende SPS Bibliotheken |
---|---|---|
TwinCAT v2.10.0 | PC or CX (x86, ARM) | TcXmlDataSrv.Lib |