Overview
The Siemens SIMATIC TP1500 Comfort panel (6AV2 124-1QC02-0AX0, 15" widescreen TFT, 1280 x 800) running WinCC Comfort / TIA Portal V16 through V18 supports a built-in Recipe object that downloads/uploads data records between the panel's flash memory and the connected controller. In many field scenarios this built-in object is too restrictive: operators cannot freely name a new recipe, the Download to PLC button is fixed in the control, the exported binary .csv and .rdb files use a non-intuitive schema, and audit trails are difficult to embed. This article documents a fully script-driven recipe workflow that uses VBScript on the panel, an external symbolic I/O field for selection, and standard comma-separated-value (CSV) files written to the panel's removable storage. The approach works with any controller exposed to the panel through a tag interface, including the Allen-Bradley SLC 5/04 or SLC 5/05 in the source scenario.
Why a Custom Recipe Implementation?
WinCC Comfort's standard Recipe object provides automatic data record management, but the following constraints frequently push integrators toward a custom solution:
- Recipe names are bound to the engineering project and cannot be created at runtime by the operator.
- The Save, Load, Download, and Delete commands are hard-coded to toolbar buttons and cannot be hidden per user role.
- The exported record file uses a fixed binary format that shop-floor personnel cannot open in Excel without re-import through the HMI.
- Versioning, time-stamps, operator IDs, and CSV exports must be appended manually.
A VBScript-driven workflow on the TP1500 Comfort sidesteps all four constraints because the script layer is granted unrestricted access to the HMI file system, tags, and the symbolic I/O field text list.
Prerequisites
| Item | Requirement |
|---|---|
| Engineering software | TIA Portal V16, V17, or V18 with WinCC Comfort/Advanced installed |
| Runtime | TP1500 Comfort firmware V16.0.0.0 or higher (panel image package matches TIA Portal version) |
| Storage | Industrial SD card (e.g., Siemens 6AV2 181-2AA10-0AA0) inserted in the panel's X50 slot, or USB stick on X60 |
| Controller | Any PLC exposed to the panel through tags. Tested with Allen-Bradley SLC 5/05 over EtherNet/IP via the Rockwell RSLinx Classic OPC tunnel, and directly with the native Allen-Bradley Ethernet/IP driver introduced in TIA Portal V17 SP1. |
| Operator authorization | WinCC user group with rights to use VBScript (default: group "Administrator" or group with "Operating" right for the relevant screens) |
| Transfer | WinCC Project Download to the panel with "Start runtime after transfer" enabled |
System Architecture
The figure below shows the runtime data flow. Symbolic I/O fields on the TP1500 read their text list from a VBScript that enumerates files in \Storage Card SD\Recipes; pressing Save writes a CSV row built from the HMI tag values back to the same directory, and pressing Load reverses the path.
PLC Tag Structure (SLC 5/05 Side)
The SLC 500 exposes a contiguous block of integer and float registers that hold one recipe record. A common allocation for a 12-element recipe is shown in the table below. Tag names are mapped into the WinCC tag table using the Allen-Bradley Ethernet/IP driver; an alternative is to publish the same data through RSLinx Classic as OPC DA items.
| WinCC Tag | PLC Address (SLC 5/05) | Data Type | Description |
|---|---|---|---|
| Recipe_Setpoint_01 | N7:0 | INT | Process setpoint #1 |
| Recipe_Setpoint_02 | N7:1 | INT | Process setpoint #2 |
| Recipe_Setpoint_03 | N7:2 | INT | Process setpoint #3 |
| Recipe_Setpoint_04 | N7:3 | INT | Process setpoint #4 |
| Recipe_Setpoint_05 | N7:4 | INT | Process setpoint #5 |
| Recipe_Setpoint_06 | N7:5 | INT | Process setpoint #6 |
| Recipe_Flow_SP | F8:0 | REAL | Flow setpoint (liters/min) |
| Recipe_Temp_SP | F8:1 | REAL | Temperature setpoint (°C) |
| Recipe_Pressure_SP | F8:2 | REAL | Pressure setpoint (bar) |
| Recipe_Duration_SP | F8:3 | REAL | Cycle time (s) |
| Recipe_BatchID | N7:10 | DINT | Batch identifier |
| Recipe_Operator | ST14:0 (20 chars) | STRING | Operator logon name |
| Cmd_LoadRecipe | B3:0/0 | BOOL | One-shot load from CSV |
| Cmd_SaveRecipe | B3:0/1 | BOOL | One-shot save to CSV |
| Cmd_DeleteRecipe | B3:0/2 | BOOL | One-shot delete from SD |
| Status_RecipeLoaded | B3:1/0 | BOOL | Plc ack after successful load |
All recipe tags are configured in WinCC with the same acquisition cycle (1 s) and are pointed to a controller connection named "PLC_SLC5_05". Boolean commands use the Edge-triggered acquisition setting to avoid double execution on a sticky bit.
HMI Tag Configuration
Beyond the controller tags, the following local HMI tags are required. They live only on the panel and are not propagated to the SLC.
| Name | Type | Length | Use |
|---|---|---|---|
| Local_RecipeName | WSTRING | 64 | Current selected recipe name (text field input) |
| Local_NewRecipeName | WSTRING | 64 | Operator-entered name for a brand-new recipe |
| Local_FileList | WSTRING | 4096 | Multi-line string populating the symbolic I/O field |
| Local_RecipeCount | INT | 1 | Number of CSV files in the recipe folder |
| Local_StatusText | WSTRING | 128 | Display feedback ("Saved", "File exists", etc.) |
| Local_Timestamp | DATE_AND_TIME | 1 | Time-stamp written into the CSV row |
| Const_RecipeDir | WSTRING | 256 | Constant "\Storage Card SD\Recipes\" |
| Const_CsvExt | WSTRING | 8 | Constant ".csv" |
\Storage Card SD\ and /Storage Card SD/. The back-slash form is the WinCC convention used by HMIRuntime.FileSystem in V16+ projects. Substitute \USB Storage Device\ if you intend to plug a USB stick into port X60 instead of using the SD slot X50.File System Layout on the TP1500
Create the recipe directory once during commissioning. The WinCC file-system object will not auto-create nested paths, so a one-line Project initialization script on the Start event of the recipe screen ensures the directory exists:
Set fs = CreateObject("Scripting.FileSystemObject")
If Not fs.FolderExists(Const_RecipeDir) Then fs.CreateFolder(Const_RecipeDir)
After the first power-up the panel contains the following structure:
\Storage Card SD\
├─ Recipes\
│ ├─ Recipe_A_20240117_083012.csv
│ ├─ Recipe_A_20240118_142105.csv
│ ├─ Recipe_B_20240117_090014.csv
│ └─ header.txt <-- optional human-readable description
Each .csv file is a single text line terminated by CRLF, which keeps parsing trivial and survives Excel re-imports. Header definitions live in a separate header.txt to avoid duplicating the schema inside every record.
CSV File Format
Use UTF-8 encoding without BOM to maximise compatibility with other HMI tools and standard Excel. The schema is:
RecipeName;Timestamp;OpName;SP1;SP2;SP3;SP4;SP5;SP6;Flow;Temp;Pressure;Duration;BatchID
Recipe_A;2024-01-17 08:30:12;alice;120;130;140;150;160;170;42.5;78.2;3.10;90.0;77821
Use the semicolon as a separator because Excel for European locales treats a comma as the decimal symbol; the semicolon removes ambiguity in TIA Portal V17/V18 runtime exports. Each line must be terminated with vbCrLf (0x0D 0x0A) on the panel side so the file is recognized by the file system as text and not binary.
FileSystem.CreateObject with the optional Unicode flag in VBScript. In WinCC V18 the WriteFile method accepts a third parameter: HMIRuntime.FileSystem.WriteFile sPath, sContent, True writes the buffer as UTF-16 LE, which is the panel's native encoding.VBScript Core Library
Place the following functions in the project's Scripts container so they can be called from any screen:
ListRecipes() — populates the symbolic I/O field
Sub ListRecipes()
Dim fs, f, fld, lst, p
p = SmartTags("Const_RecipeDir")
Set fs = CreateObject("Scripting.FileSystemObject")
If Not fs.FolderExists(p) Then fs.CreateFolder(p)
Set fld = fs.GetFolder(p)
lst = ""
Dim cnt
cnt = 0
For Each f In fld.Files
If LCase(Right(f.Name, 4)) = ".csv" Then
lst = lst & f.Name & vbCrLf
cnt = cnt + 1
End If
Next
SmartTags("Local_FileList") = lst
SmartTags("Local_RecipeCount") = cnt
End Sub
SaveRecipe() — writes a new CSV row
Sub SaveRecipe()
Dim sName, sFile, sLine, sTs
sName = SmartTags("Local_NewRecipeName")
If Len(sName) = 0 Then
SmartTags("Local_StatusText") = "Enter a recipe name first"
Exit Sub
End If
sTs = Year(Now) & Right("0" & Month(Now),2) & Right("0" & Day(Now),2) & "_" _
& Right("0" & Hour(Now),2) & Right("0" & Minute(Now),2) & Right("0" & Second(Now),2)
sFile = SmartTags("Const_RecipeDir") & sName & "_" & sTs & ".csv"
sLine = sName & ";" & sTs & ";" & SmartTags("Recipe_Operator") & ";" _
& SmartTags("Recipe_Setpoint_01") & ";" _
& SmartTags("Recipe_Setpoint_02") & ";" _
& SmartTags("Recipe_Setpoint_03") & ";" _
& SmartTags("Recipe_Setpoint_04") & ";" _
& SmartTags("Recipe_Setpoint_05") & ";" _
& SmartTags("Recipe_Setpoint_06") & ";" _
& SmartTags("Recipe_Flow_SP") & ";" _
& SmartTags("Recipe_Temp_SP") & ";" _
& SmartTags("Recipe_Pressure_SP") & ";" _
& SmartTags("Recipe_Duration_SP") & ";" _
& SmartTags("Recipe_BatchID") & vbCrLf
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(sFile) Then
SmartTags("Local_StatusText") = "File already exists"
Exit Sub
End If
Dim ts
Set ts = fso.CreateTextFile(sFile, True, False) ' overwrite=False, unicode=False
ts.Write sLine
ts.Close
SmartTags("Local_StatusText") = "Saved " & sName
ListRecipes
End Sub
LoadRecipe() — pushes CSV values back into tags
Sub LoadRecipe()
Dim sName, sFile, sLine, p, arr
sName = SmartTags("Local_RecipeName")
If Len(sName) = 0 Then
SmartTags("Local_StatusText") = "Pick a recipe from the list"
Exit Sub
End If
sFile = SmartTags("Const_RecipeDir") & sName
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists(sFile) Then
SmartTags("Local_StatusText") = "Recipe file not found"
Exit Sub
End If
Dim ts
Set ts = fso.OpenTextFile(sFile, 1) ' 1 = ForReading
sLine = ts.ReadLine
ts.Close
arr = Split(sLine, ";")
SmartTags("Recipe_Setpoint_01") = CInt(arr(3))
SmartTags("Recipe_Setpoint_02") = CInt(arr(4))
SmartTags("Recipe_Setpoint_03") = CInt(arr(5))
SmartTags("Recipe_Setpoint_04") = CInt(arr(6))
SmartTags("Recipe_Setpoint_05") = CInt(arr(7))
SmartTags("Recipe_Setpoint_06") = CInt(arr(8))
SmartTags("Recipe_Flow_SP") = CSng(arr(9))
SmartTags("Recipe_Temp_SP") = CSng(arr(10))
SmartTags("Recipe_Pressure_SP")= CSng(arr(11))
SmartTags("Recipe_Duration_SP")= CSng(arr(12))
SmartTags("Recipe_BatchID") = CLng(arr(13))
SmartTags("Cmd_LoadRecipe") = True ' pulse to PLC
SmartTags("Local_StatusText") = "Loaded " & sName
End Sub
DeleteRecipe() — removes a file from the SD card
Sub DeleteRecipe()
Dim sName, sFile
sName = SmartTags("Local_RecipeName")
If Len(sName) = 0 Then Exit Sub
sFile = SmartTags("Const_RecipeDir") & sName
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(sFile) Then
fso.DeleteFile sFile, True
SmartTags("Local_StatusText") = "Deleted " & sName
End If
ListRecipes
End Sub
ExportToUSB() — copies all CSVs to an external USB stick
Sub ExportToUSB()
Dim fso, src, dst, f
Set fso = CreateObject("Scripting.FileSystemObject")
src = SmartTags("Const_RecipeDir")
dst = "\USB Storage Device\Recipes_" & Replace(Date, "/","-") & "\"
If Not fso.FolderExists(dst) Then fso.CreateFolder(dst)
For Each f In fso.GetFolder(src).Files
If LCase(Right(f.Name,4)) = ".csv" Then
fso.CopyFile f.Path, dst & f.Name, True
End If
Next
SmartTags("Local_StatusText") = "Exported to " & dst
End Sub
Symbolic I/O Field Configuration
On the recipe screen, drop a Symbolic I/O field configured as Output with Text list mode Variable. Bind the text list source to Local_FileList and the index value to Local_RecipeIndex. The field will display every file name on its own row; tapping a row populates Local_RecipeName via a Change value event that calls Trim(Mid(Local_FileList, (idx-1)*lineLen, lineLen)). The split/line-length helper is shown below.
Sub PickFromList()
Dim idx, lines, s
idx = SmartTags("Local_RecipeIndex")
lines = Split(SmartTags("Local_FileList"), vbCrLf)
If idx > 0 And idx - 1 <= UBound(lines) Then
SmartTags("Local_RecipeName") = lines(idx - 1)
End If
End Sub
Step-by-Step Implementation
- Open the TIA Portal project that contains the TP1500 Comfort device. Confirm the HMI device firmware matches the engineering version (e.g., 18.0.0.0 for TIA V18). Mismatched firmware is the leading cause of "Object not found" runtime errors on VBScript.
- Add the controller connection: in Devices & Networks connect the TP1500 to the SLC 5/05 CPU. For an SLC 5/05 on EtherNet/IP choose the Allen-Bradley Ethernet/IP driver (TIA V17 SP1+). For an SLC 5/04 on DF1 you must add a third-party gateway (e.g., HMS Anybus X-gateway) and a generic Modbus TCP coupling, because the Comfort panel has no native DF1 port.
- Create the local tags listed in HMI Tag Configuration. Right-click HMI Tags > Add new tag, set the data type, and tick Local tag to keep them on the panel side.
-
Map the SLC tags: open HMI Tags > Default tag table and add a tag for every row in the SLC allocation table. Use the Connection column to bind the tag to the controller connection. For Allen-Bradley addresses use the syntax
N7:0,F8:0,B3:0/0directly, or the symbolic alias exposed by RSLinx. - Create the recipe folder on the SD card by inserting the SD card in a PC, mounting it, and creating \Recipes at the root. Re-insert the card into the panel before compiling.
- Insert the VBScript functions: in the project tree select Scripts > VBScripts > Add new and paste the ListRecipes, SaveRecipe, LoadRecipe, DeleteRecipe, ExportToUSB, and PickFromList subroutines above.
- Add a new screen titled Recipe_Management. Drop a Symbolic I/O field, three text I/O fields (recipe name, new name, status), and four buttons (Refresh, Save, Load, Delete, plus an Export USB button).
-
Wire the events:
- Button Refresh → Click → VBScript
ListRecipes - Button Save → Click → VBScript
SaveRecipe - Button Load → Click → VBScript
LoadRecipe - Button Delete → Click → VBScript
DeleteRecipe - Button Export USB → Click → VBScript
ExportToUSB - Symbolic I/O field → Change → VBScript
PickFromList - Screen Loaded → VBScript that creates the directory and calls
ListRecipes
- Button Refresh → Click → VBScript
- Compile and download: click Compile > Software (rebuild all) and transfer the WinCC project to the panel over Ethernet or USB. Confirm that the HMI connection to the SLC 5/05 reports Connected in the diagnostics screen.
-
Validate the file-system permissions: WinCC Comfort V16+ requires the project to be configured with File system access enabled. In the project tree, open Runtime settings > Services > File system and tick Allow access to the SD card and Allow access to USB storage. Without this, the file-system object throws Permission denied on the first
CreateTextFilecall.
Verification
Run through the following acceptance test on the live panel:
- Touch Refresh. The symbolic I/O field lists any pre-existing CSV files. With a freshly formatted SD card the field should be empty and the status text should display "0 recipes".
- Enter Recipe_A in the new-name field, touch Save. Verify with a PC that \Storage Card SD\Recipes\Recipe_A_*.csv exists and contains exactly one CRLF-terminated line.
- Modify one setpoint (e.g., Recipe_Temp_SP), touch Load, and confirm that the value written to the SLC matches the CSV row. The SLC input image at
F8:1should update within one controller scan. - Touch Refresh again — the new file name must appear in the list.
- Insert a USB stick and touch Export USB. The destination folder on the stick must contain the same CSV files.
- Cycle the panel power. After the restart the symbolic I/O field should be repopulated automatically because the screen's Loaded event triggers
ListRecipes.
Troubleshooting Matrix
| Symptom | Likely Cause | Remediation |
|---|---|---|
| Symbolic I/O field shows nothing | Scripting event fires before tag is initialised; ListRecipes not called on screen load |
Wire the screen's Loaded event to ListRecipes; verify tag length of Local_FileList is at least 4096 chars |
| "Permission denied" on Save | File-system access disabled in runtime settings | Enable File system > Allow access to SD card in the project, recompile, redownload |
| CSV saved but values are 0 in PLC | Load path missing leading slash or trailing extension | Set Const_RecipeDir to \Storage Card SD\Recipes\ with back-slashes and the trailing separator |
| Setpoint visible on HMI but not in SLC | Tag acquisition mode is set to Cyclic continuous with a slow cycle | Switch HMI tags to Cyclic on demand and write them from the VBScript, or change the cycle to 250 ms |
| Recipe name contains non-ASCII chars and file is empty | Default text-file mode is ANSI, UTF-8 is required | Use CreateTextFile(path, True, True) to force Unicode; the operator name is preserved |
| SD card corruption after 5 000+ saves | File system uses FAT32 with no wear-levelling | Replace the SD card with an industrial SLC-grade card (Siemens 6AV2 181-2AA10-0AA0 rated 100 000 P/E cycles) and rotate monthly |
| Panel cannot reach SLC tags over EtherNet/IP | Driver requires TIA Portal V17 SP1 Update 4 or higher | Update the engineering project, or fall back to RSLinx OPC tunnel |
| Operator cannot find the saved file via FTP | FTP is disabled by default on Comfort panels | Enable Runtime settings > Services > FTP and create a read-only user for download |
Performance and Storage Notes
A typical recipe record of 14 values at 32 bytes per line occupies ~3.5 kB after FAT32 cluster allocation. The TP1500's internal flash reserves ~30 MB for the runtime, leaving the full SD capacity (up to 32 GB) for recipes. At 1 000 saves per shift, one year of operation accumulates ~3.2 GB — well below the card's endurance threshold when an industrial card is used.
VBScript execution on the panel is single-threaded; the longest call in this design is the file write at <5 ms for a 1 kB CSV. The symbolic I/O field refresh is bounded by Local_FileList size and is therefore O(n) where n is the recipe count. For n > 500, switch to a paginated list driven by a Slider widget that updates the Local_FileList slice on demand.
Security and Authorisation
Tie the Save and Delete buttons to a WinCC user group with the Manage recipes authorisation level. WinCC Comfort V18 supports per-button visibility based on the active user; the VBScript can additionally reject the call with HMIRuntime.BaseScreenName to harden the flow against script injection from a remote maintenance session. All recipes are timestamped with the operator's WinCC logon name from Recipe_Operator, which is automatically supplied by the Current user system tag.
Field-Commissioning Checklist
- ✓ Project compiles without VBScript syntax warnings
- ✓ File-system access enabled in runtime settings
- ✓ SD card formatted as FAT32 with 32 kB cluster size
- ✓ Symbolic I/O field token count matches the operator's expectation
- ✓ PLC tags confirmed as Good in Diagnostics > Connections
- ✓ Save/Load/Delete tested with two distinct recipes
- ✓ Power-cycle test: recipes reload automatically
- ✓ FTP export tested and password-protected
- ✓ Audit log reviewed and timestamp format validated
How do I create a new recipe name from the TP1500 runtime and save it to CSV?
Add a WSTRING tag Local_NewRecipeName bound to a text I/O field. Wire a Save button to a VBScript that concatenates the name, a timestamp, and the current tag values into a CRLF-terminated string, then calls CreateObject("Scripting.FileSystemObject").CreateTextFile against \Storage Card SD\Recipes\<name>_<ts>.csv. The recipe name is fully operator-defined.
How do I populate a symbolic I/O field with the list of saved recipes?
Use a VBScript that iterates GetFolder(Const_RecipeDir).Files, appends each .csv name separated by vbCrLf into Local_FileList (WSTRING 4096), and binds the symbolic I/O field's Text list to that tag. The selection index drives Local_RecipeName via a Change event script.
Can the saved CSV be opened directly in Microsoft Excel?
Yes. Use UTF-8 encoding, a semicolon as the delimiter, CRLF line termination, and a single header line stored separately. The resulting file opens in Excel as a single column-and-row table and can be re-imported into another HMI tool that supports CSV recipe import.
How do I copy recipes from the panel's SD card to a USB stick for archival?
Trigger a VBScript that uses Scripting.FileSystemObject to enumerate \Storage Card SD\Recipes, create a date-stamped folder under \USB Storage Device\, and call CopyFile for every .csv. Enable USB storage access in the runtime settings first.
Why does the SLC 5/05 not receive the loaded recipe values?
Verify the HMI connection is Connected in the panel's Diagnostics > Connections view. Confirm the tags are not marked Local in the WinCC tag table, that the acquisition cycle is at most 500 ms, and that the symbolic I/O field binds to a controller tag rather than an internal one. For DF1-connected SLC 5/04 CPUs you need a Modbus-TCP-to-DF1 gateway because the TP1500 has no native DF1 port.