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