Further Samples
The following samples show different types of application of the TC3 XML Server. The PLC-projekt which contains the samples can be downloaded here: TC3_XmlSrv_Samples.zip
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: One-time initialization at program startup
Sample 5 shows the one-time initialization of value1 on program startup. The function block 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 writing
The following example generates a new XML file every 20 seconds and writes the familiar structure into it. As usual, the file name is generated based on the current Windows date and time and a string. The write process can also be started by pressing switch (or by setting the switch variable bButton). If the write process is triggered several times within one second, the current file is 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) *)
(*change value 1*)
value1.stInner.sString := sFilePathWrite;
value1.stInner.nInteger := stMyTimestruct.wSecond;
(* write *)
fbXmlSrvWrite(sFilePath:=sFilePathWrite, sXPath:=sXPathWrite, bExecute:= TRUE);
ELSIF fbXmlSrvWrite.bError THEN
iState:= 100;
END_IF
(* reset fbXmlSrvWrite *)
IF fbXmlSrvWrite.bBusy AND NOT tGetTime.ERR THEN
fbXmlSrvWrite(bExecute:= FALSE);
ELSIF ntGetTime.ERR THEN
iState:= 100;
END_IF
100: (* error state*)
;
END_CASE
Requirements
Development environment |
Target system type |
PLC libraries to be linked |
---|---|---|
TwinCAT v3.1 Build 4011 |
PC or CX (x86, x64, ARM) |
Tc2_XmlDataSrv |