Problem Overview: S7-1200 / S7-1500 DataLog CSV Output Defects
The DataLog instruction family in TIA Portal (DataLogCreate, DataLogOpen, DataLogWrite, DataLogClose, DataLogDelete, DataLogNewFile) is intended to produce a portable, comma-separated log file on the load memory / SD card of an S7-1200 or S7-1500 CPU. In practice, four recurring defects break downstream consumption in Microsoft Excel, Python pandas, MES historians, and any tool that expects a clean RFC 4180-style CSV:
- Forced "RECORDS" index column – A monotonically incrementing counter column is prepended to every record when timestamp stamping is active. It cannot be disabled through the block interface.
- UTC offset on timestamp – When the wizard preconfigures timestamp = "1" (System time), the CPU writes the values from the realtime clock but applies no localization. Operators in CET / CEST observe a −1h or −2h drift relative to the wall clock.
-
Quoted string fields – String tags passed through the
DATAparameter are wrapped in double-quote characters ("..."). The DataLog engine treats this as a hard-coded escape, even when the content contains no comma, semicolon, or quote. -
Separator mismatch – The default separator is the comma
,. Changing it to;in the wizard does not retroactively affect the header generation logic, and the "RECORDS" column re-appears whenever a timestamp is requested.
Root Cause: How the DataLog Engine Builds the CSV
The DataLogCreate instruction (FB block number varies by firmware; documented in the S7-1200 / S7-1500 system manual) writes a fixed header row, then a fixed record row, into a binary record file. When the CSV is later extracted from the S7 load memory (or read directly from the SD card on a CPU that supports it), the engine concatenates fields with the configured separator.
Three behaviors drive the defects:
| Behavior | Mechanism | Engineering Consequence |
|---|---|---|
| Auto-RECORDS column | Hard-coded counter is generated server-side by the firmware when TIMESTAMP > 0
|
Cannot be turned off; appears as the first data column regardless of HEADER string content |
| UTC timestamp | Value "1" = system time, not localized; firmware stores raw RTC ticks | No daylight-saving awareness; CSV consumer must re-apply the time zone |
| Always-quoted strings | Each STRING tag is wrapped to protect embedded separators | Excel shows "Value" in the cell; downstream parsers must strip outer quotes |
| Comma default separator | Block default for "Separator" is 0 = comma | European locales with ; CSV default fail to auto-split |
These are not bugs in the strict sense; they are documented edge cases of the DataLog firmware implementation, but the TIA Portal wizard exposes very little of this state, which is why field engineers hit the wall.
Affected Products, Firmware, and Software Versions
The defects map to specific firmware generations. Confirm the firmware build on the CPU first — the available TIMESTAMP constants differ across versions.
| CPU | Firmware (FW) | TIA Portal | Timestamp Values Supported | Notes |
|---|---|---|---|---|
| S7-1200 (all) | FW 4.x | V15 / V15.1 / V16 / V17 / V18 | 0, 1 | No localized timestamp; wizard shows only 0 / 1 |
| S7-1500 | FW 1.x / 2.0 / 2.5 | V14 / V15 | 0, 1 | Legacy; same defects |
| S7-1500 | FW 2.6+ | V15.1+ | 0, 1, 2, 3, 4, 5 | Localized timestamp + ISO-8601 layouts available |
| S7-1500 | FW 2.9 / 3.0 / 3.1 | V16 / V17 / V18 | 0, 1, 2, 3, 4, 5 | Same constants; identical CSV output structure |
| ET 200SP CPU | FW 2.6+ | V15.1+ | 0, 1, 2, 3, 4, 5 | Behaves as S7-1500 |
For the full firmware / TIA Portal compatibility matrix, refer to the Siemens SIMATIC S7-1500/ET 200MP system manual and the SIMATIC S7-1200 system manual.
TIMESTAMP = 4 on a CPU whose firmware does not support it returns error 8453 (W#16#2101: invalid parameter / illegal timestamp constant). Upgrade the CPU firmware or fall back to a supported constant.TIMESTAMP Parameter Reference
The full TIMESTAMP enum is documented in the TIA Portal online help under "DataLogCreate: Create data log" (F1 on the block). Switch the project "Editing language" to English to see the authoritative list, as localized help bundles are occasionally out of date.
| Value | Meaning | Format Produced | Minimum FW |
|---|---|---|---|
| 0 | OFF — no time stamp column | none | all |
| 1 | System time (UTC, firmware-rendered) | dd.mm.yyyy hh:mm:ss |
all |
| 2 | Local time | dd.mm.yyyy hh:mm:ss |
S7-1500 FW 2.6+ |
| 3 | System time (US layout) | mm/dd/yyyy, hh:mm:ss[.999] |
S7-1500 FW 2.6+ |
| 4 | Local time (ISO-8601) | yyyy-mm-dd, hh:mm:ss[.999] |
S7-1500 FW 2.6+ |
| 5 | System time (ISO-8601) | yyyy-mm-dd, hh:mm:ss[.999] |
S7-1500 FW 2.6+ |
For European plants, the recommended constant is TIMESTAMP = 2 on S7-1500 FW 2.6+ when local time in classic layout is needed, or TIMESTAMP = 4 when ISO-8601 is required by the downstream MES / historian. Neither constant is available on S7-1200 at any firmware; S7-1200 users must manually localize in the application code (see workarounds below).
DataLogCreate Block Interface – Key Inputs
The full block signature is published in the TIA Portal help. The parameters that drive the defects above are summarized here for quick reference:
| Parameter | Type | Allowed Values | Effect on CSV |
|---|---|---|---|
RECORD |
VARIANT pointing to a STRUCT or UDT | Any UDT / STRUCT | Defines one log row; each element becomes one column |
HEADER |
STRING[256] | Comma-separated column names | Used as-is; a String array is rejected at runtime |
TIMESTAMP |
UINT | 0 / 1 (all FW); 2–5 (FW 2.6+) | Adds the time column and forces the RECORDS counter column |
DATA |
VARIANT | Any elementary type or STRUCT | Quoting is applied to STRING elements unconditionally |
NAME |
STRING | Max 24 chars | File name on the load memory |
ID |
DWORD | Returned by DataLogCreate | Used by Open / Write / Close / NewFile / Delete |
FORMAT (alias separator-related) |
UINT | 0 = comma, 1 = semicolon (per help) | Field separator character |
Verified Workaround: Disable TimeStamp, Build the Header / Data in Application Code
The only field-proven path that yields a clean CSV — no RECORDS column, no double-quoted string fields, with local time and a configurable separator — is to set TIMESTAMP = 0 and emit the timestamp yourself as part of the HEADER and the record STRUCT.
Step-by-step
- Define a UDT for the data record (example for a barcode / weight / recipe logger):
TYPE "UDT_LogRecord" : STRUCT sDate : STRING[10]; // "YYYY-MM-DD" or "DD/MM/YYYY" sTime : STRING[8]; // "HH:MM:SS" sBarcode: STRING[32]; rWeight : REAL; sRecipe : STRING[32]; END_STRUCT; END_TYPE - Define a UDT for the entire log line (only the data fields you want to log):
TYPE "UDT_LogLine" : STRUCT sBarcode : STRING[32]; rWeight : REAL; sRecipe : STRING[32]; END_STRUCT; END_TYPE - Build the HEADER string once, in static / init code:
// "date,heure,componant1,componant2,componant3" "sHeader" := 'date,heure,componant1,componant2,componant3'; - In the cyclic OB, populate the record with current local time and the data:
"udt_struct".sDate := MID(IN := DTL_TO_STRING("dtNow"), LEN := 10); "udt_struct".sTime := MID(IN := DTL_TO_STRING("dtNow"), LEN := 8); "udt_struct".sBarcode := "iBarcode"; "udt_struct".rWeight := "rWeight"; "udt_struct".sRecipe := "sRecipe"; "DataLogWrite"(ID := "dwLogID", RECORD := "udt_struct"); - Create the log with
TIMESTAMP = 0:"DataLogCreate"(REQ := TRUE, NAME := 'ProcessLog', HEADER := "sHeader", TIMESTAMP := 0, FORMAT := 0, // 0 = comma DATA := "UDT_LogLine", ID => "dwLogID", STATUS => "wStatus");
Resulting CSV row example:
2024-06-12,14:32:07,BC-12345,12.34,Recipe_A
No RECORDS column, no surrounding quotes, comma is the only separator. Excel "From Text/CSV" imports this directly with the comma as delimiter.
Workaround: Localized Timestamp on S7-1500 FW 2.6+
If you can constrain the project to S7-1500 FW 2.6+ (and the matching TIA Portal V15.1+), the firmware now renders the local time correctly:
"DataLogCreate"(REQ := TRUE,
NAME := 'ProcessLog',
HEADER := "sHeader",
TIMESTAMP := 2, // local time, classic layout
FORMAT := 0, // comma
DATA := "UDT_LogLine",
ID => "dwLogID",
STATUS => "wStatus");
For ISO-8601 output (recommended for MES systems that store the timestamp as text):
TIMESTAMP := 4; // local time, yyyy-mm-dd hh:mm:ss[.999]
Workaround: Cleaning the Output in Excel / pandas
If the log files have already been generated with the legacy format and the customer is waiting, the following pipeline is the least painful.
- Open the .csv in a plain text editor (Notepad++, VS Code). Find / replace
,with.only on lines that contain numeric data, to convert European decimal notation. - Open the file in Excel. Use Data → From Text/CSV. Choose
;as the delimiter if the wizard used semicolon,,otherwise. - Delete the first column (RECORDS) and the trailing empty column if present.
For Python / pandas consumers, the same logic is two lines:
import pandas as pd
df = pd.read_csv('ProcessLog.csv',
sep=',',
encoding='utf-8-sig',
skiprows=0,
usecols=lambda c: c != 'RECORDS') # drop the counter column
The official Siemens FAQ 87138437 documents the legacy post-processing flow for S7-1200 data logs.
Alternative: RecipeExport / Data Log on Recipe DB
When the application can accept a different export mechanism, the RecipeExport instruction family and the Data log on recipe DB feature introduced in TIA Portal V15.1 give finer control over the resulting file. RecipeExport is intended for production recipes, not high-frequency logging, and uses more load memory per write, but it does not impose the RECORDS column and does not quote STRING fields.
Reserve the technique for batch logs (recipe changes, parameter sets, audit trails) where the write rate is low and the file size overhead is acceptable.
Verification Procedure
- After
DataLogCreatereturnsSTATUS = 0, open the Web server of the CPU (or read the SD card) and download the log file. Confirm the file name matchesNAMEand the file size grows after eachDataLogWrite. - Inspect the first two lines (header + first record). Verify:
- The number of comma-separated columns equals the number of HEADER tokens.
- STRING fields are not surrounded by double quotes.
- The first column is the one named in HEADER (not "RECORDS").
- The timestamp column matches the chosen
TIMESTAMPformat and the wall-clock time of the operator's HMI.
- Import into Excel via Data → From Text/CSV. Each column should align with its header without manual cleanup.
- Import into Python via
pandas.read_csv. Inspectdf.dtypes: STRING fields areobject, REAL fields arefloat64, no extra leading column.
Error Code Reference
| STATUS (hex) | Meaning | Likely Cause | Remediation |
|---|---|---|---|
| 0000 | No error | — | Proceed |
| 8453 / W#16#2101 | Invalid timestamp / parameter | TIMESTAMP constant not supported on this CPU FW | Upgrade CPU FW to 2.6+ (S7-1500) or use TIMESTAMP = 0 / 1 |
| 80A1 / W#16#80A1 | Data log with specified name does not exist | Wrong ID or log deleted | Re-run DataLogCreate |
| 80B0 / W#16#80B0 | Log file is currently open | DataLogOpen called twice | Call DataLogClose first |
| 80B1 / W#16#80B1 | Maximum number of data logs reached | >50 logs on the CPU | Delete or download old logs |
| 80B3 / W#16#80B3 | No more free memory | SD card / load memory full | Archive, then DataLogDelete |
Full list is in the TIA Portal online help under the DataLog instruction group.
Troubleshooting Matrix
| Symptom | Most Likely Cause | Fastest Fix |
|---|---|---|
| First column is "RECORDS" | TIMESTAMP > 0 | Set TIMESTAMP = 0 and emit date / time in the record STRUCT |
| Time column is 1–2 h off | TIMESTAMP = 1 (system time, UTC) on S7-1200 | Localize the time in the application code via DTL_TO_STRING |
| STRING cells display "value" | Quoting by DataLog engine on STRING elements | Pass data inside a STRUCT; do not concat into a single STRING in DATA |
| Header contains "," but file is semicolon-separated | FORMAT set to 1 after HEADER was built with comma | Use a single separator everywhere; rebuild HEADER to match |
| STATUS = 8453 with TIMESTAMP = 2 | CPU FW < 2.6 | Upgrade CPU FW or fall back to TIMESTAMP = 0 / 1 |
| CSV is binary / unreadable in Excel | File downloaded from internal load memory as binary, not as file | Use the Web server "File browser" or pull the SD card directly |
| RECORDS column visible even with TIMESTAMP = 0 | TIA Portal V15 with English help, project language mismatch | Switch project editing language to English and re-open the block |
Field-Engineering Notes
- The TIA Portal help is partially translated. Switch the project "Editing language" to English to see the full TIMESTAMP enum and the Format / separator constants. Half-translated help is the most common reason a field engineer sees only constants 0 / 1 and concludes the rest do not exist.
- The HEADER parameter is documented as a single STRING[256] at the FB interface. A STRING array is rejected at runtime with W#16#80B0 (file format error). Build the header by concatenating tokens in the application code, with the configured separator between them.
- STRING quoting in the DATA record is a hard-coded behavior of the DataLog engine. There is no "do not quote" parameter. The only mitigation is to pre-format everything inside a STRUCT and not to pass a single concatenated STRING as the DATA element.
- Daylight-saving handling on S7-1500 FW 2.6+ with TIMESTAMP = 2 / 4 is correct only if the CPU's time zone and DST flag are set in the CPU properties under "Time of day". Without that configuration, the firmware still produces local time, but it is the local time of the unsynchronized RTC.
- For high-frequency logs (sub-second), prefer a third-party data logger (PC side, MQTT / OPC UA) and disable the S7 DataLog. The DataLog is designed for sporadic process events, not 1 kHz trace.
Why does my S7-1200 DataLog CSV have a "RECORDS" column I cannot remove?
The RECORDS counter is added by the DataLog firmware whenever TIMESTAMP > 0; it is not a separate column you can suppress. Set TIMESTAMP = 0 in the DataLogCreate call and emit your own date / time as STRING fields inside the record STRUCT.
How do I get a localized (CEST / CET) timestamp on S7-1200?
S7-1200 only supports TIMESTAMP = 0 and 1 (system time, UTC) at any firmware. Read the CPU clock as DTL, call DTL_TO_STRING, and store the formatted string inside the record STRUCT, with TIMESTAMP = 0 on DataLogCreate.
Why are my STRING fields wrapped in double-quotes in the CSV?
DataLog unconditionally quotes STRING elements to protect embedded separators. Do not pass a single concatenated STRING as the DATA element; build a STRUCT / UDT whose members are the individual fields, and the quoting is applied per cell so downstream tools can split cleanly.
Why does TIMESTAMP = 4 return error 8453 on my S7-1500?
Constants 2–5 require S7-1500 firmware 2.6 or higher and TIA Portal V15.1 or higher. Check the CPU "Online & diagnostics → CPU information" for the firmware version and either upgrade the firmware or fall back to TIMESTAMP = 0 or 1.
Can I use a semicolon as separator on a German / French Windows Excel?
Yes. Set the FORMAT / separator parameter to 1 on DataLogCreate (semicolon) and rebuild the HEADER string with semicolons as well. The DataLog engine will then produce a file that Excel's locale-specific CSV wizard will auto-split on import.