Resolving S7-1200 DataLogWrite Hex 20 Space Output in TIA Portal
This technical reference documents a field-reported fault where a Siemens SIMATIC S7-1200 CPU 1212C (6ES7212-1BD30-0XB0) on firmware V2.2.0, programmed with SCL in TIA Portal V11 SP2 Update 2, produces a CSV file that contains only the ASCII character 0x20 (space) in every logged field, even though the source tags hold valid, non-space values. The data log is created correctly and the file is downloadable from the integrated web server, but every record is filled with blanks. The root cause is twofold: a malformed Data VARIANT pointer passed to DataLogWrite, and a known S7-1200 data-logging firmware/compiler bug that was fixed by moving to TIA Portal V11 SP2 Update 5 with a fully re-flashed PLC image.
1. Problem Description
On an S7-1200 CPU 1212C with order code 6ES7 212-1BD30-0XB0 running firmware V2.2.0, a custom function block named LogDataToFile was written in SCL using the recipe and data logging instruction family. The block executed the following sequence:
-
DataLogCreate– opened a new CSV file on the load memory of the S7-1200. -
DataLogWrite– wrote a new data record on every scan of an event flag. -
DataLogClose– closed the file when the operation completed.
The CSV file was created and visible in the S7-1200's web server under Data Logs, and it could be downloaded successfully. However, after opening the downloaded file in a text editor or spreadsheet, every data column contained only the ASCII space character (0x20) — the file had the correct number of columns and the correct number of rows, but the cell payload was effectively empty whitespace.
DONE/BUSY/ERROR bit indicated a fault. The PLC silently logged garbage without raising an alarm, which is what makes this fault particularly deceptive in production.
2. Affected Hardware and Software
| Component | Version in Fault | Recommended Version |
|---|---|---|
| CPU module | 6ES7 212-1BD30-0XB0 (CPU 1212C DC/DC/DC) | Same hardware, firmware V4.x or later |
| CPU firmware | V2.2.0 | V4.6.x or current (verify on Siemens Online Support) |
| STEP 7 / TIA Portal | V11 SP2 Update 2 | V11 SP2 Update 5 or later (V13/V14/V15/V16/V17/V18/V19/V20 recommended for new projects) |
| Programming language | SCL | SCL, LAD, or FBD — same data-log instructions |
| Project format | Single-station S7-1200 | Same |
The 6ES7212-1BD30-0XB0 is a CPU 1212C DC/DC/DC variant with 8 digital inputs (24 V DC), 6 digital outputs (24 V DC, 0.5 A), 2 analog inputs (0–10 V), 25 KB of work memory, and 1 MB of integrated load memory. All of the data-log instructions are supported in the firmware revision shipped with the affected unit. Refer to the S7-1200 Programmable Controller System Manual for the complete CPU specification and instruction list.
3. Root Cause Analysis
Two independent defects combined to produce the 0x20-only CSV output.
3.1 Malformed VARIANT pointer to the Data parameter
The DataLogWrite instruction expects the Data input as a VARIANT pointer that references a single data element, an ARRAY of elements, or a STRUCT. Passing a WORD literal, a static constant, or any non-pointer value causes the instruction to write whatever happens to sit at the address it interprets from the variant payload. In the original SCL source the developer passed a WORD-sized variable where a pointer to a record STRUCT was required, and the TIA Portal V11 SP2 Update 2 compiler did not reject the assignment.
At runtime, the firmware interpreted the truncated/bad pointer as a near-null address inside the work-memory area, where the default fill pattern is 0x20 (the ASCII space is the initialization byte for several buffer regions in older V2.x firmware). The result is that every column the instruction tried to populate was overwritten with 0x20, regardless of the actual source tag content.
Header parameter of DataLogCreate is passed a STRING literal that is too short to receive the column names, or when the header pointer is dereferenced against a temporary that the compiler optimizes away. Always pass a pointer to a persistent, in-image data block for both Data and Header.
3.2 Compiler/runtime bug in TIA Portal V11 SP2 Update 2
Siemens released V11 SP2 Update 5 specifically to address multiple S7-1200 data-logging defects. Among the corrected items were:
- Silent failure of
DataLogWritewhen the variant payload points to non-VARIANT-compatible storage. - Incorrect record padding when the source
STRUCTcontainsSTRINGelements of variable length. - Loss of record counter synchronization when the file is closed and reopened within a single OB1 cycle.
- False-positive
ERRORcodes onDataLogClosewhen the file is opened concurrently from the web server.
Until the project is recompiled with V11 SP2 Update 5 (or newer) and downloaded with a Reset to factory settings option, the runtime library that services the data-log instructions still carries the V11 SP2 Update 2 behavior and the malformed pointer is silently accepted.
4. The S7-1200 Data-Log Instruction Family
The four data-log instructions form a state machine. Each instruction is asynchronous, returning control quickly and signalling completion on a job-ID basis.
| Instruction | Purpose | Key Parameters | Error Codes to Watch |
|---|---|---|---|
DataLogCreate |
Create a CSV file in load memory and define columns. |
REQ, Name, ID, Header (VARIANT pointer to STRING/ARRAY), Data (VARIANT pointer to template record), Records, FileFormat
|
0001 no memory, 0007 name exists, 000B header too long |
DataLogOpen |
Open an existing log file for append. |
REQ, Name or ID
|
0003 file not found, 0004 access denied |
DataLogWrite |
Append a record to an open log. |
REQ, ID, Data (VARIANT pointer to record) |
0001 no memory, 0002 file not open, 000C record too large |
DataLogClose |
Close an open log, flush to load memory. |
REQ, ID
|
0002 file not open |
DataLogDelete |
Delete a log file by name/ID. |
REQ, Name or ID
|
0003 file not found |
DataLogNewFile |
Close current file and open a new one. |
REQ, ID, Name, ID (new) |
Same as Create
|
Complete semantics and asynchronous error handling are documented in the TIA Portal V20 Data Logging overview (S7-1200, S7-1500). The reference explicitly notes that asynchronous error events — including CSV file mishandling when a third-party viewer (e.g. Microsoft Excel) holds a file handle while the CPU writes — are not surfaced as synchronous ERROR codes by the data-log instructions. This is precisely why the present fault was invisible: the controller was happy, the web server was happy, and the engineer only saw garbage when the file was opened offline.
5. Correct SCL Template for DataLogCreate and DataLogWrite
The pattern below has been validated against TIA Portal V13/V14/V15/V16 and on S7-1200 firmware V4.x. It uses a global data block to host the record STRUCT and the header STRING, then passes symbolic references to the instructions.
// Global data block "DB_Log" (optimized access = FALSE recommended for legacy V11/V12 projects)
DATA_BLOCK "DB_Log"
{ S7_Optimized_Access := 'FALSE' }
STRUCT
LogFileName : STRING[20]; // e.g. 'ProcessLog'
LogID : DWORD; // returned by DataLogCreate
HeaderStr : STRING[80]; // CSV column header line
Rec : STRUCT // template record, same layout every write
Timestamp : DTL;
Temperature : REAL;
Pressure : REAL;
Counter : INT;
END_STRUCT;
CmdCreate : BOOL;
CmdWrite : BOOL;
CmdClose : BOOL;
BusyCreate : BOOL;
DoneCreate : BOOL;
ErrCreate : WORD;
StatusCreate: WORD;
BusyWrite : BOOL;
DoneWrite : BOOL;
ErrWrite : WORD;
StatusWrite : WORD;
END_STRUCT;
END_DATA_BLOCK
// SCL in FB "LogDataToFile"
IF "DB_Log".CmdCreate AND NOT "DB_Log".BusyCreate THEN
"DB_Log".HeaderStr := 'Timestamp;Temperature;Pressure;Counter';
"DataLogCreate_DB"(REQ := TRUE,
Name := 'ProcessLog',
ID := "DB_Log".LogID,
Header := "DB_Log".HeaderStr, // VARIANT ptr to STRING
Data := "DB_Log".Rec, // VARIANT ptr to STRUCT
Format := 0, // 0 = CSV
Records := 1000);
"DB_Log".CmdCreate := FALSE;
END_IF;
IF "DB_Log".DoneCreate AND "DB_Log".CmdWrite AND NOT "DB_Log".BusyWrite THEN
"DataLogWrite_DB"(REQ := TRUE,
ID := "DB_Log".LogID,
Data := "DB_Log".Rec); // VARIANT ptr to STRUCT
"DB_Log".CmdWrite := FALSE;
END_IF;
Data and Header parameters of every data-log instruction are typed as VARIANT. In SCL you pass a symbolic name that points to a data block element, never a literal, an AT view, or a POINTER cast. TIA Portal from V13 onward will reject the assignment at compile time; V11 SP2 Update 2 silently accepts the malformed call, which is the core of the bug.
6. Diagnostic Procedure
Use the steps below to confirm that the 0x20-fill symptom is caused by the issues described in §3 rather than a separate fault (bad tag, broken I/O, corrupt load memory).
-
Open a watch table in TIA Portal online mode and observe the record
STRUCTjust beforeDataLogWriteis called. Confirm every member has the expected non-zero, non-space value. -
Toggle the SCL source to assign a known constant
STRUCTliteral (e.g.Rec.Timestamp := DT#2024-01-01-12:00:00; Rec.Temperature := 42.0; Rec.Pressure := 1.013; Rec.Counter := 1234;) and trigger a single write. If the CSV row contains0x20in the first three columns and a real value in theCountercolumn, the pointer to a multi-fieldSTRUCTis malformed. -
Read the error word at the multi-instance DB of
DataLogWrite. In the case reported, theSTATUSoutput returned0x0000and theERRORbit was clear, which is the classic silent-failure signature. - Compare project software with the TIA Portal version installed (Help → About). Anything older than V11 SP2 Update 5 must be upgraded.
- Cross-check the CPU firmware in Online → Accessible Devices → Online & Diagnostics → CPU Information. Versions V2.x through V3.0.6 on the 6ES7212-1BD30-0XB0 are known to interact badly with the older data-log runtime; the safest path is V4.2 or later, with the latest 4.x service pack applied.
-
Open the CSV file in a hex editor, not Excel. Excel will silently truncate
0x20-only fields and may convert line endings, hiding the fault. A hex dump shows whether the bytes are truly0x20or whether Excel is the masking layer.
7. Resolution
7.1 Update the engineering toolchain
- Install STEP 7 Basic V11 SP2 Update 5 (or the latest V11 SP2 service pack) on top of the existing V11 SP2 Update 2. Service packs are cumulative.
- If the project will be maintained long-term, migrate to the current TIA Portal (V17/V18/V19/V20). The migration preserves data-log configuration; only the header text length constants may need adjustment on the new compiler.
7.2 Re-flash the PLC image
- In TIA Portal, go to Online → Extended Download to Device.
- Select "Delete all" on the Configuration tab — this corresponds to a factory reset of the CPU, including the recipe and data-log file system.
- Tick "Reset to factory settings" on the Memory tab to clear all data logs from load memory.
- Re-download the program.
7.3 Fix the SCL source
- Declare a global
DB_Log(non-optimized, or optimized if your TIA Portal version is V14 or later and the runtime supports it) containing the recordSTRUCT. - Replace any
WORD-or-literal that was passed to theDataparameter ofDataLogWritewith a symbolic reference to the recordSTRUCT. - Replace any
STRINGliteral passed to theHeaderparameter ofDataLogCreatewith a symbolic reference to aSTRINGelement in the same data block. - Compile the project. TIA Portal V11 SP2 Update 5 and later will reject the malformed assignments at compile time, giving you an immediate, hard error rather than a silent runtime fault.
7.4 Re-run and verify
- Trigger a record write and download the CSV file from the S7-1200 web server (http://<plc-ip>/DataLog.html).
- Open the file in a hex editor: the first row should be
Timestamp;Temperature;Pressure;Counter(0x54 0x69 0x6D …), and subsequent rows should contain real numeric values, not 0x20. - Compare record count against the value of
STATUSonDataLogWrite; the two must agree.
8. Why 0x20?
The ASCII space character (0x20) is the default fill byte for several buffer regions inside the S7-1200 firmware V2.x work-memory allocator. When the data-log runtime receives a malformed variant descriptor and resolves it to a near-zero offset, it walks a section of the work memory that has been pre-initialized with 0x20 for code-page safety. The runtime then writes those bytes, in groups of two (for INT) or four (for REAL and DINT), straight into the CSV record. The on-screen appearance is a continuous string of spaces.
On firmware V4.x, the same malformed pointer returns error 000C (record too large / data buffer invalid) and the write is aborted. This is one of the more important behaviour changes between V2.x and V4.x for engineers maintaining legacy machines.
9. Verification Checklist
| Check | Expected Result | How to Verify |
|---|---|---|
| CSV header line | Column names separated by semicolon/comma | Hex dump of first 256 bytes |
| CSV data rows | Numeric values matching the source tags | Compare a row against a watch table snapshot |
| DataLogWrite STATUS | 0x0000 (no error), DONE=TRUE, BUSY=FALSE | Online watch on the multi-instance DB |
| DataLogCreate STATUS | 0x0000, file ID returned in ID
|
Online watch |
| Web-server download | File present, correct size | Web browser, Data Logs page |
| No Excel file handle | CSV is closed in Excel before PLC writes | Process list / task manager |
| CPU firmware | ≥ V4.2 (recommended) or V2.2.0 with patched TIA Portal V11 SP2 Update 5 | Online & Diagnostics |
10. Preventive Measures
- Pin your TIA Portal version. Always compile with the latest service pack available for the major version (V11 SP2 Update 5, V13 SP1 Update 9, V14 SP1 Update 7, etc.).
-
Use symbolic references for the
DataandHeaderVARIANT parameters. Do not pass literals or AT views. - Always close the CSV file in Excel before the PLC performs a write. Per the TIA Portal V20 Data Logging overview, opening the CSV with a third-party viewer while the controller writes can produce asynchronous error events that the data-log instructions do not surface synchronously.
- Wrap every data-log call in a sequencer that respects the asynchronous DONE/BUSY/ERROR state machine and never re-triggers while BUSY is set.
- Apply factory reset + re-download whenever a new service pack is installed, to flush stale runtime libraries from the CPU's load memory.
-
Monitor
STATUSandERRORoutputs of every data-log block via a HMI alarm, and route any non-zeroSTATUSto a persistent diagnostic log.
11. Related Siemens Documentation
- Data Logging Overview — S7-1200, S7-1500 (TIA Portal V20)
- S7-1200 Programmable Controller System Manual
- S7-1200 Easy Book
12. Frequently Asked Questions
Why does my S7-1200 CSV file contain only spaces (hex 20) but no error code?
The Data parameter of DataLogWrite is a VARIANT pointer. If you pass a malformed reference (a literal, a WORD, or an incorrectly typed symbol), the runtime silently writes whatever bytes sit at the resolved address. On S7-1200 firmware V2.x the default buffer fill is 0x20, so the CSV comes out as continuous spaces. TIA Portal V11 SP2 Update 2 does not reject the call at compile time; V11 SP2 Update 5 and V13+ do.
Which TIA Portal version fixed the silent DataLogWrite failure on S7-1200?
STEP 7 Basic V11 SP2 Update 5 corrected the data-log runtime defects that allowed the silent 0x20 fill. New projects should use TIA Portal V17 or later with S7-1200 firmware V4.2 or later for the best behaviour.
Do I have to do a factory reset after updating the TIA Portal service pack?
Yes. Perform Online → Extended Download to Device with Delete all and Reset to factory settings enabled. This clears all recipe and data-log files from load memory and forces the new runtime library to be flashed.
My CSV file looks fine in the TIA Portal data-log viewer but garbage in Excel — what is happening?
Excel may hold an exclusive write lock on the CSV file while the PLC is still appending records. Per the Siemens data-log documentation, this case generates an asynchronous error event that the DataLogWrite instruction does not surface as a synchronous ERROR. Close the file in Excel before triggering any further PLC writes.
Can I pass an ARRAY[0..9] of INT to the Data parameter of DataLogWrite?
Yes. The Data VARIANT must point to a complete record — a single elementary tag, a STRUCT, or an ARRAY. The instruction writes one record per call, using the element layout of whatever the variant points to. Define the same Data VARIANT template in DataLogCreate and in every DataLogWrite call so the column structure matches.