Weiterführende Beispiele
Die folgenden Beispiele zeigen verschiedene Anwendungsarten des TwinCAT XML Data Servers. Das SPS-Projekt, das die Beispiele enthält, können Sie hier runterladen.
Beispiel 5 zeigt eine einmalige Initialisierung bei Programmstart, Beispiel 6 zyklische und ereignisgesteuerte Schreibvorgänge. Beide Beispiele arbeiten mit der schon aus den Beispielen 1-4 bekannten Struktur ST_MYSTRUCT, die wiederum die Struktur ST_INNTERSTRUCT enthält. Die beiden Strukturen sind im Folgenden dargestellt:
Die Strukturen
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: Einmalige Initalisierung bei Programmstart
Sample 5 zeigt die einmalige Initialisierung von value1 bei Programmstart. Zum Einsatz kommt der Funktionsbaustein FB_XmlSrvRead.
(* 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: Zyklisches und ereignisgesteuertes Schreiben
Das folgende Beispiel erzeugt alle 20 Sekunden eine neue XML-Datei und beschreibt diese mit der bekannten Struktur. Der Dateiname wird immer aus dem aktuellen Windows-Datum, der -Uhrzeit und einem String generiert. Außerdem kann der Schreibprozess durch Drücken eines Schalters (bzw. Setzen der Schaltervariable bButton) gestartet werden. Sollte der Schreibprozess in einer Sekunde mehrfach ausgelöst werden, wird die aktuelle Datei überschrieben.
(* 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
Voraussetzungen
Entwicklungsumgebung | Zielplattform | Einzubindende SPS Bibliotheken |
---|---|---|
TwinCAT v2.10.0 | PC oder CX (x86) | TcXmlDataSrv.Lib |