Writing CSV files
The TwinCAT 3 Database Server supports the CSV file format. There are different approaches, each with advantages and disadvantages, to write content to the file or read from it. Two of these approaches are explained in more detail here.
Select the ASCII database. The .csv file format can be specified under the file path. The ASCII-DB 3.0 format flag indicates the format of the ASCII/CSV file. If the format is checked, the SAX procedure is used. With this setting, write access to the file, especially with the FB_PLCDBCmdEvt function block, is also very efficient for large files. If the format is unchecked, the DOM procedure is used, which is particularly suitable for reading a file. The data is stored in a structured form in the RAM. Therefore this method is recommended for smaller files (less than 1 MB). However, this method offers some advantages due to the structured storage. The CSV file can be used as an SQL database using a stored table structure. Use the SQL Query Editor to do this. This file can be created directly via the 'Create' button.
Load your configuration onto your TwinCAT Database Server target system.
Function block | Table structure | ASCII 3.0 format | Standard ASCII |
---|---|---|---|
FB_PLCDBWriteEvt.Write | standard | ||
FB_PLCDBWriteEvt.WriteStruct* | variable | ||
FB_PLCDBReadEvt.Read | standard | ||
FB_:PLCDBReadEvt.ReadStruct* | variable | ||
FB_PLCDBCmdEvt.Execute* | variable | ||
FB_SQLCommandEvt | variable |
Items marked with * are used in the following sample
High-performance writing to the CSV file
The most efficient way to write to a CSV file is based on the function block FB_PLCDBCmdEvt. To this end, the link to the CSV file must be set in ASCII-DB 3.0 format. The DBValueType is irrelevant here. A table structure does not have to be defined in advance.
Sample:
The following structure is used as an example:
TYPE ST_CSVDataStruct :
STRUCT
ID: LINT;
Timestamp: DT;
Name: STRING(80);
Velocity: LREAL;
Temperature: LREAL;
END_STRUCT
END_TYPE
The function block is initialized as follows:
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
The individual parameters are specified in curly brackets within the command. Information about the type, byte length and name is assigned via the initialization. The name is used to recognize the parameter in the command and to replace it with the value from the PLC when it is written to the file.
The call in the PLC source code of the function block consists of a call:
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
The hDBID depends on its configuration and can be taken from the database link. pData (or cbData) can be the address for the individual structure or for an array of its structure. This can lead to further performance improvements.
Structured writing and reading of a CSV file
Not all function blocks are possible with the ASCII format 3.0. Some functions of the TwinCAT Database Server require a preconfigured table structure. However, this cannot be stored in ASCII format 3.0. In this sample, a fixed structure is used to write and read the data with the PLCDBWriteEvt and PLCDBReadEvt function blocks in any structure.
The following structure is used as an example:
Export for the PLC under the 'Select' tab is also possible:
TYPE ST_CSVDataStruct :
STRUCT
ID: LINT;
Timestamp: DT;
Name: STRING(80);
Velocity: LREAL;
Temperature: LREAL;
END_STRUCT
END_TYPE
The Write/ReadStruct methods of the respective PLC function blocks are used for any table structures:
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
The WriteStruct(...) method writes the Data structure to the database. The structures of the PLC and the CSV file are compared based on the ColumnNames.
The ReadStruct(...) method reads a certain number (nRecordCount) of records from the CSV file. These may be sorted based on a selected column. The size of the ReadData target array should be sufficient to receive all the retrieved data.
Appendix
Sample configurations for both samples, as well as the complete code of a simple sample program, can be downloaded here: TF6420_BestPractise_CSV.zip. To illustrate the process, the program generates values and repeatedly sends them to the CSV. The settings used above were stored in a separate function block, which communicates in different ways with the two CSV formats.