Transferring CSV Files from S7-1500 SIMATIC Memory Card

David Krause11 min read
SiemensTIA PortalTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Transferring CSV Files from S7-1500 SIMATIC Memory Card to IOT2040

This reference covers the end-to-end path required to move a CSV data-log file written by a SIMATIC S7-1500 CPU onto its SIMATIC Memory Card, copy it to a SIMATIC IOT2040 gateway, package the file with a ZIP utility, push it to a remote FTP server, and then perform the reverse flow so that files coming back from the server are unzipped and written back to the S7-1500. The implementation uses the open web server of the S7-1500, the Node-RED runtime on the IOT2040, and standard Linux command-line tools (wget, curl, zip, unzip) available in the IOT2000 Yocto image.

Why this architecture is common: S7-1500 CPUs do not expose the SIMATIC Memory Card over a standard SMB/NFS share. The cleanest way to read data-log CSVs externally is to enable the integrated web server, then use HTTP GET on the CPU's user-defined pages. The IOT2040 is the natural edge device because it can speak S7, host Node-RED, run curl/wget, and connect to plant networks on one side and IT networks on the other.

1. Architecture Overview

The integration consists of three logical zones:

  • OT zone — the S7-1500 CPU (for example 6ES7515-2AM02-0AB0 or 6ES7513-1AL02-0AB0) with a SIMATIC Memory Card (for example 6ES7954-8LE03-0AA0, 12 MB) hosting the active DataLog.
  • Edge zone — the SIMATIC IOT2040 (6ES7647-0AA00-1YA2), running the IOT2000 SD card image with Node-RED pre-installed. It pulls the CSV, compresses it, and forwards it.
  • IT zone — a remote FTP/HTTPS server that stores the archive and pushes new parameter or recipe CSVs back to the line.

The data path for outbound logs is:

S7-1500 DataLog (.csv) → /Memory Card/DATALOG/datalog.csv
        │
        │ (S7-1500 integrated Web Server, "User-defined Web pages")
        ▼
IOT2040 /home/root/datalog.csv  (pulled by Node-RED exec → wget)
        │
        │ (zip -j datalog.zip datalog.csv)
        ▼
IOT2040 /home/root/datalog.zip
        │
        │ (curl -T → FTP / SFTP / HTTPS)
        ▼
Remote server: /upload/<plant>/<timestamp>.zip

The inbound path is the mirror image, terminating in the S7-1500 via a user-defined web page PUT/POST or via an S7 PUT/GET trigger.

2. Prerequisites

Item Requirement Notes
S7-1500 CPU firmware V2.0 or higher (V2.6+ recommended) Required for integrated Web Server and user-defined pages
SIMATIC Memory Card 6ES7954-8LE03-0AA0 (12 MB) or larger Format is FAT32; DataLog directory is created automatically
TIA Portal V16 or higher with S7-1500 support package For programming the DataLog and web page fragments
SIMATIC IOT2040 6ES7647-0AA00-1YA2, image V2.6.0 or higher Includes Node-RED 0.20.x
Network OT and IOT2040 on same subnet; outbound to FTP server allowed Use a separate interface if DMZ is required
Credentials FTP user, password, server URL; PLC web-server user with read Avoid cleartext FTP across WAN if possible
Network port summary: S7-1500 Web Server listens on TCP 80 (HTTP) or 443 (HTTPS). FTP server typically TCP 21 plus passive-mode range 50000-50100. Node-RED default port 1880 (admin) and 1883 (MQTT, optional). S7 PUT/GET uses TCP 102.

3. S7-1500 DataLog Configuration in TIA Portal

The S7-1500 DataLog function block family writes comma-separated files onto the SIMATIC Memory Card under /<Card>/DataLog/<name>.csv. The required programming steps are:

  1. In the CPU's Properties → Web server, enable Enable Web server on the CPU, set Permit access only via HTTPS if needed, and create a user with the Read files right.
  2. Add a DataLogCreate instance (FB 1000) in your program and define the columns matching your process tags.
  3. Call DataLogOpen (FB 1001) once at startup; call DataLogWrite (FB 1002) cyclically or on event; call DataLogClose (FB 1003) on controlled shutdown.
  4. Optionally, configure DataLogNewFile (FB 1004) to roll the file on size or time.

Minimal ladder snippet for the open + header cycle:

// STL / SCL equivalent
IF "FirstScan" THEN
    DataLogCreate_Instance(MODE := 1,    // create new file
                           NAME := 'datalog',
                           HEADER := 'Timestamp;Pressure;Temp;Flow',
                           DATA   := 'MyData',
                           ID     := "LogID");
END_IF;

IF "StartLog" AND NOT "LogBusy" THEN
    DataLogOpen_Instance(MODE := 1, NAME := 'datalog', ID := "LogID");
END_IF;

// Write trigger every 1 s
IF "Tick1s" THEN
    DataLogWrite_Instance(ID := "LogID", DATA := "MyData");
END_IF;

After compiling and downloading, verify the file by going to the S7-1500 Web Server (browser: http://<plc-ip>/), logging in, and drilling into Files → DataLog → datalog.csv. A valid session token is required for any non-browser HTTP client.

Card retention: The S7-1500 only retains user DataLog files when the card is configured as Program card or Firmware update card with sufficient free space. The card should be monitored using CardStatus to prevent write errors. See the SIMATIC Memory Card data transfer page for the official procedure.

4. SIMATIC IOT2040 Setup

On the IOT2040, confirm Node-RED and the Linux utilities are present:

root@iot2040:~# opkg list-installed | grep -E 'wget|curl|zip|node-red'
root@iot2040:~# node-red --version
Node-RED 0.20.x
root@iot2040:~# which wget curl zip unzip
/usr/bin/wget
/usr/bin/curl
/usr/bin/zip
/usr/bin/unzip

If a package is missing, install it with opkg update && opkg install <name>. Create a working directory with predictable permissions:

mkdir -p /home/root/iot/queue /home/root/iot/archive
chmod 755 /home/root/iot

5. Pulling the CSV from the S7-1500 Web Server

The S7-1500's web server presents the DataLog directory under a hashed URL once you are logged in. Capture the file with a Node-RED exec node that calls wget. The trick is two-step authentication: first POST credentials, then GET the file with the resulting cookie.

Step 1 — obtain a session cookie and write it to a file:

curl -c /home/root/iot/cookies.txt \
     -d 'Login=<user>&Password=<pass>' \
     http://<plc-ip>/FormLogin

Step 2 — fetch the CSV with the cookie. The exact path on the web server for a DataLog file looks like:

wget --load-cookies /home/root/iot/cookies.txt \
     -O /home/root/iot/datalog.csv \
     'http://<plc-ip>/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'

A clean Node-RED flow using the exec node looks like this in JSON form (paste via Import → Clipboard):

[{"id":"f1","type":"inject","name":"Hourly tick","topic":"","payload":"","payloadType":"date","repeat":"3600","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":140,"wires":[["f2"]]},
 {"id":"f2","type":"exec","name":"wget datalog.csv","command":"wget --load-cookies /home/root/iot/cookies.txt -O /home/root/iot/datalog.csv 'http://<plc-ip>/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"x":360,"y":140,"wires":[["f3"],[],[]]},
 {"id":"f3","type":"exec","name":"zip archive","command":"cd /home/root/iot && zip -j /home/root/iot/datalog.zip datalog.csv","x":580,"y":140,"wires":[["f4"],[],[]]},
 {"id":"f4","type":"exec","name":"curl -T to FTP","command":"curl -T /home/root/iot/datalog.zip ftp://user:pass@server/plant1/ --ftp-create-dirs","x":800,"y":140,"wires":[[],[],[]]}]

Key flags in the above flow:

  • --load-cookies reuses the session that the PLC returned in step 1; without it the CSV responds with HTTP 401.
  • -O writes to a known local path; never use -P here because the IOT2040's home partition is small.
  • zip -j strips the directory prefix so the archive contains only datalog.csv.
  • curl -T performs an FTP upload, creating remote directories with --ftp-create-dirs.
Why wget worked but curl did not initially: When you only need to read a file with cookies already in place, wget is more forgiving about redirect chains and stale tokens than curl. For the outbound path you have to use curl -T because wget cannot PUT files by design. Make sure to pass the explicit ftp:// scheme and credentials, and that the server accepts passive mode on TCP 50000-50100.

6. Compression and FTP Upload

Although ZIP is convenient, tar.gz is smaller and avoids licensing noise. A typical production script does the following each cycle:

  1. Rotate the previous local archive into /home/root/iot/archive/<timestamp>.zip.
  2. Refresh datalog.csv from the PLC.
  3. Compress and upload with a unique remote name.
  4. Remove the local copy after a 200/226 server response.

Bash equivalent run from a exec node:

#!/bin/sh
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
LOG=/home/root/iot/datalog.csv
OUT=/home/root/iot/datalog_${STAMP}.zip

# 1. refresh session
curl -s -c /home/root/iot/cookies.txt \
     -d 'Login=plcuser&Password=plcpass' \
     http://10.0.0.10/FormLogin > /dev/null

# 2. download latest csv
wget -q --load-cookies /home/root/iot/cookies.txt \
     -O $LOG \
     'http://10.0.0.10/DataLog/datalog.csv?Action=DownloadFile&FileName=datalog.csv'

# 3. zip
zip -j -q $OUT $LOG

# 4. upload
curl -s -T $OUT ftp://ftpuser:ftppass@ftpsrv/plant1/$STAMP/ --ftp-create-dirs
RC=$?

# 5. archive locally if upload ok
[ $RC -eq 0 ] && mv $OUT /home/root/iot/archive/ || echo "FTP fail rc=$RC" >> /home/root/iot/log.txt

For SFTP instead of FTP, swap the last step for:

sftp -o StrictHostKeyChecking=no ftpuser@ftpsrv <<EOF
put $OUT /plant1/$STAMP/${STAMP}.zip
bye
EOF

For HTTPS REST endpoints use curl -F "file=@$OUT" https://api.example.com/upload with a bearer token in -H "Authorization: Bearer ...".

7. Receiving Files from the FTP Server (Inbound Path)

The reverse path is symmetrical. A second Node-RED flow polls the FTP server, downloads new ZIP files into /home/root/iot/inbox/, unzips them, and writes the resulting CSV back to the S7-1500. The trickiest part is writing the file back to the PLC because the S7-1500's web server does not support generic PUT on DataLog files. Use one of two supported mechanisms:

7.1 Method A — S7 PUT/GET

Enable Permit access with PUT/GET communication from remote partner in the CPU's Properties → Communication. The IOT2040 can use the open-source snap7 library or a Node-RED node-red-contrib-s7 node to write the CSV contents to a data block on the S7-1500. The PLC then re-creates the file with DataLogNewFile on the next scan.

7.2 Method B — User-defined web page with file upload

From TIA Portal, create a user-defined web page (Web server → User-defined pages) with a small HTML form that posts a file. Then call it with curl -F:

curl -F "file=@/home/root/iot/inbox/recipe.csv" \
     -b /home/root/iot/cookies.txt \
     http://<plc-ip>/<UserDefinedPage>/upload.html

The S7-1500 web page invokes a custom WWW instruction in the user program to copy the file into a configured DataLog directory or to a recipe DB.

8. End-to-End Flow Summary

Step Tool Command / Action Direction
1. Authenticate curl POST /FormLogin with user/password IOT2040 → S7-1500
2. Download CSV wget GET /DataLog/datalog.csv with cookies S7-1500 → IOT2040
3. Compress zip zip -j datalog.zip datalog.csv local
4. Upload curl / sftp PUT to FTP server / SFTP server / HTTPS API IOT2040 → IT
5. Poll inbound curl / sftp GET list, download new ZIPs IT → IOT2040
6. Decompress unzip unzip -o inbound.zip -d inbox/ local
7. Write to PLC curl PUT or S7 PUT POST user-defined page or write DB IOT2040 → S7-1500

9. Verification and Diagnostics

Use this checklist before going into production:

  1. File size sanity — confirm ls -l /home/root/iot/datalog.csv shows a non-zero file that grows after each tick.
  2. CSV header check — head -1 /home/root/iot/datalog.csv should match the HEADER string from DataLogCreate.
  3. Cookie validity — the S7-1500 default session is 30 minutes. If the cycle is longer, re-authenticate each iteration.
  4. FTP return code — curl -v on the first run; expect 226 Transfer complete.
  5. Round trip — download a file you uploaded, unzip, diff the CSV against the local source with diff -q local.csv remote.csv.

Common Failure Matrix

Symptom Likely Cause Fix
wget returns 401 Unauthorized Stale cookie or wrong user right Re-run FormLogin, confirm user has Read files in TIA Portal
wget returns 404 on DataLog path DataLog not created yet Trigger DataLogCreate once, then DataLogOpen
curl -T connection refused FTP passive ports blocked on firewall Open 50000-50100, or use SFTP/FTPS explicit
curl -T hangs after login Server requires explicit FTPS (TLS) Use curl --ssl-reqd -T and ftps://
Empty CSV (0 bytes) DataLog was closed between cycles Re-open on every cycle, or check shutdown logic
Unzip fails on IOT2040 unzip not installed opkg install unzip
PUT to PLC returns 405 User-defined page not enabled Enable User-defined web pages in TIA Portal, download HTML
Security: Never expose the S7-1500 web server to the internet. Terminate the FTP path behind a jump host or VPN, and at minimum force HTTPS and use a non-default PLC user. Restrict the PLC user to Read files only on the outbound path and Write files only on the inbound path.

10. Performance and Timing Notes

Typical timings on an IOT2040 (single-core 600 MHz ARM, 1 GB RAM):

  • FormLogin round trip: 50–120 ms on the same VLAN.
  • 100 kB CSV download: 200–400 ms.
  • zip -j of 100 kB: < 30 ms.
  • curl -T of 100 kB: 300–800 ms depending on WAN RTT.

For larger files (multiple MB) raise the exec node timeout to 60 s and avoid concurrent transfers — the IOT2040 has a single NIC and limited CPU.

11. Field-Proven Caveats

  • The S7-1500 file system path for DataLog is case-sensitive on newer firmware; use lowercase datalog.csv consistently.
  • When the PLC is in STOP, the web server still serves files but the DataLog is not updated; your script will keep reading the same file.
  • Avoid rm on the SIMATIC Memory Card from the IOT2040; the PLC manages its own retention.
  • Node-RED flows persist at /home/root/.node-red/flows_<host>.json; back this up before firmware updates.

What SIMATIC Memory Card size do I need for S7-1500 data logging?

For most CSV data logs, a 12 MB card (6ES7954-8LE03-0AA0) is sufficient. If you log high-frequency process values without rollover, step up to 32 MB (6ES7954-8LL03-0AA0). Always retain at least 30% free space to avoid write errors.

Why does wget work for downloading the CSV from the S7-1500 but curl fails?

Wget transparently follows the S7-1500 web server's session redirects and accepts self-signed certificates with --no-check-certificate. Curl needs the cookie jar, a fixed user-agent, and proper handling of the 30-minute session expiry. Re-authenticate before every download for long-running scripts.

How do I push a ZIP file from the IOT2040 to an FTP server from Node-RED?

Use an exec node running curl -T /home/root/iot/file.zip ftp://user:pass@server/path/ --ftp-create-dirs. Add --ssl-reqd and switch the scheme to ftps:// if the server requires TLS, and open passive-mode ports 50000-50100 on the firewall.

Can the S7-1500 directly write a file received from the IOT2040?

Yes, through a user-defined web page with a file-upload form. The page calls a WWW instruction in your STEP 7 program that copies the uploaded file to a configured directory or to a DataLog buffer. The IOT2040 uses curl -F "file=@path" -b cookies.txt to post to the page.

What is the difference between a Program card and a Firmware card for storing CSVs?

A Program card holds the STEP 7 project and user DataLogs; this is the typical configuration. A Firmware update card is for CPU firmware only and should not be used as a data-log destination. Set the card type in TIA Portal under CPU → Properties → SIMATIC Memory Card and use a SIMATIC Memory Card of the recommended size for your log volume.

Back to blog