CSV Dateien schreiben
Der TwinCAT 3 Database Server unterstützt das CSV-Dateiformat. Es gibt unterschiedliche Ansätze mit jeweils Vor- und Nachteilen, um Inhalte in die Datei zu schreiben oder zu lesen. Zwei dieser Ansätze werden hier genauer erläutert.
Wählen Sie die ASCII-Datenbank aus. Dort kann unter dem Dateipfad das Dateiformat .csv angegeben werden. Das ASCII-DB 3.0 Format-Flag gibt das Format der ASCII/CSV-Datei an. Fall das Format angehakt ist, wird das SAX-Verfahren genutzt. Mit dieser Einstellung ist der Schreibzugriff auf die Datei insbesondere mit dem FB_PLCDBCmdEvt-Baustein auch bei großen Dateien sehr performant. Ist das Format nicht angehakt, wird das DOM-Verfahren genutzt, welches sich besonders für das Lesen einer Datei eignet. Die Daten liegen dabei strukturiert im Arbeitsspeicher. Deshalb ist dieses Verfahren eher bei kleinere Dateien <1MB zu empfehlen. Durch die strukturierte Ablage bietet dieses Verfahren jedoch einige Vorteile. Die CSV-Datei kann mithilfe einer abgelegten Tabellenstruktur als SQL Datenbank genutzt werden. Nutzen Sie hierfür den SQL Query Editor. Über den ‚Create‘-Button kann diese Datei direkt erzeugt werden.
Laden Sie ihre Konfiguration auf Ihr TwinCAT Database Server Target System.
Funktionsbaustein | Tabellen Struktur | ASCII-Format 3.0 | Standard ASCII |
---|---|---|---|
FB_PLCDBWriteEvt.Write | standard | ||
FB_PLCDBWriteEvt.WriteStruct* | beliebig | ||
FB_PLCDBReadEvt.Read | standard | ||
FB_:PLCDBReadEvt.ReadStruct* | beliebig | ||
FB_PLCDBCmdEvt.Execute* | beliebig | ||
FB_SQLCommandEvt | beliebig |
*Markierte werden im folgenden Beispiel verwendet
Performant in die CSV-Datei schreiben
Die performanteste Art in eine CSV-Datei zu schreiben, ist die Nutzung des FB_PLCDBCmdEvt Bausteines. Dafür muss die Verknüpfung zu CSV-Datei im ASCII-DB 3.0 Format eingestellt werden. Der DBValueType spielt dabei keine Rolle. Eine Tabellenstruktur muss vorher nicht definiert werden.
Beispiel:
Gegeben sei folgende Struktur:
TYPE ST_CSVDataStruct :
STRUCT
ID: LINT;
Timestamp: DT;
Name: STRING(80);
Velocity: LREAL;
Temperature: LREAL;
END_STRUCT
END_TYPE
Der Baustein wird folgendermaßen initialisiert:
VAR
InputData: ST_CSVDataStruct;
fbPLCDBCmd: FB_PLCDBCmd (sNetID:= '', tTimeout := T#30S);
sCmd : T_MaxString := '{ID};{Timestamp};{Name};{Velocity};{Temperature}';
para : ARRAY [0..4] OF ST_ExpParameter :=[
(eParaType:= E_ExpParameterType.Int64, nParaSize := 8, sParaName := 'ID'),
(eParaType:= E_ExpParameterType.DateTime, nParaSize := 4, sParaName := 'Timestamp'),
(eParaType:= E_ExpParameterType.STRING_, nParaSize := 81, sParaName := 'Name'),
(eParaType:= E_ExpParameterType.Double64, nParaSize := 8, sParaName := 'Velocity'),
(eParaType:= E_ExpParameterType.Double64, nParaSize := 8, sParaName := 'Temperature')];
END_VAR
Die einzelnen Parameter werden in geschweiften Klammern im Kommando angegeben. Diese werden in über die Initialisierung beschrieben mit den Informationen zum Typ, der Bytelänge und dem Namen. Anhand des Namens wird der Parameter im Kommando wiedererkannt und entsprechend beim Schreiben in die Datei durch den Wert aus der PLC ersetzt.
Der Aufruf im PLC-Quellcode des Bausteins besteht aus einem Aufruf:
IF fbPLCDBCmd.Execute(
hDBID:= 3,
pExpression:= ADR(sCmd),
cbExpression:= SIZEOF(sCmd),
pData:= ADR(InputData),
cbData:= SIZEOF(InputData) ,
pParameter:= ADR(para),
cbParameter:=SIZEOF(para))
THEN
;//Place for errorhandling or reactions;
END_IF
// Result: 16160;19-10-2018 12:27:38;Water Turbine;35.2238040741592;62.6461585412374
Die hDBID ist abhängig von ihrer Konfiguration und kann der Datenbankverknüpfung entnommen werden. Als pData (bzw. cbData) kann nicht nur die Adresse zur einzelnen Struktur, sondern auch zu einem Array ihrer Struktur angegeben werden. Dies kann nochmals zu Performanceverbesserungen führen.
Strukturiertes Schreiben und Lesen einer CSV-Datei
Nicht alle Funktionsbausteine sind mit dem ASCII-Format 3.0 möglich. Für einige Funktionen des TwinCAT Database Servers ist eine vorher konfigurierte Tabellenstruktur nötig. Diese lässt sich jedoch nicht im ASCII-Format 3.0 hinterlegen. In diesem Beispiel wird eine fest definierte Struktur verwendet, um die Daten mit den PLCDBWriteEvt- und PLCDBReadEvt-Bausteinen in beliebiger Struktur zu schreiben und zu lesen.
Folgende Struktur ist gegeben:
Auch als Export für die PLC unter dem ‚Select‘-Tab möglich:
TYPE ST_CSVDataStruct :
STRUCT
ID: LINT;
Timestamp: DT;
Name: STRING(80);
Velocity: LREAL;
Temperature: LREAL;
END_STRUCT
END_TYPE
Für beliebige Tabellenstrukturen werden die Write-/ReadStruct Methoden der jeweiligen PLC-Funktionsbausteine verwendet:
VAR
fbPLCDBWrite: FB_PLCDBWrite(sNetID:= '', tTimeout := T#30S);
fbPLCDBRead : FB_PLCDBRead(sNetID:= '', tTimeout := T#30S);
ColumnNames : ARRAY [0..4] OF STRING(50) := ['ID','Timestamp','Name','Velocity','Temperature'];
Data: ST_CSVDataStruct;
ReadData: ARRAY[0..4] OF ST_CSVDataStruct;
END_VAR
IF fbPLCDBWrite.WriteStruct(
hDBID:= hDBID,
sTableName:= 'CSV_Sample',
pRecord:= ADR(Data),
cbRecord:= SIZEOF(Data),
pColumnNames:= ADR(ColumnNames),
cbColumnNames:= SIZEOF(ColumnNames) )
THEN
;//Place for errorhandling or reactions
END_IF
IF fbPLCDBRead.ReadStruct(
hDBID:= hDBID,
sTableName:= 'CSV_Sample',
pColumnNames:= ADR(ColumnNames),
cbColumnNames:= SIZEOF(ColumnNames) ,
sOrderByColumn:= 'ID',
eOrderType := E_OrderType.ASC,
nStartIndex:= 0,
nRecordCount:= 5,
pData:= ADR(ReadData),
cbData:=SIZEOF(ReadData))
THEN
;//Place for errorhandling or reactions
END_IF
Die Methode WriteStruct(…) schreibt die Struktur Data in die Datenbank. Anhand der ColumnNames werden die Strukturen der PLC und der CSV-Datei abgeglichen.
Die Methode ReadStruct(…) liest eine bestimmte Anzahl (nRecordCount) von Datensätzen aus der CSV-Datei. Diese können auch nach einer ausgewählten Spalte geordnet werden. Das Ziel-Array ReadData sollte dabei mindestens so groß sein, wie die Anzahl der abgeholten Daten, um alle Daten empfangen zu können.
Anhang
Eine Beispielkonfiguration beider Beispiele, sowie der vollständige Code eines einfachen Beispielprogramms können Sie hier herunterladen:TF6420_BestPractise_CSV.zip. Um den Vorgang zu veranschaulichen, generiert das Programm Werte und schickt diese wiederholt in die CSV. Die oben verwendeten Einstellungen wurden dabei in einen eigenen Funktionsbaustein ausgelagert, welcher auf verschiedene Weise mit den beiden CSV-Formaten kommuniziert.