Problem Overview
On SIMATIC WinCC Unified panels (Comfort/MTP Unified, Unified PC, and WinCC Unified SCADA) the default behavior of an IO field bound to a PLC tag of TIME / LTime data type is to invoke a date/time selection control on touch focus. For many operator entries — particularly cycle times, timeouts, delays, recipe dwell seconds, and motion dwell timers — engineers want the field to behave like an integer input expressed in seconds with optional leading zeros. Legacy Comfort Panels allowed scaling a TIME tag to a DINT at a 1000:1 ratio through the old IO field "Scaling" property; that property no longer exists in the Unified screen object in the same form.
This article documents three engineered approaches that work on TIA Portal V17, V18, V19, and V20 Unified screen engineering:
- Shift decimal places property on the IO field (the documented method, no scripting).
-
Script dynamization on the Process value plus a
propertyChangedevent handler (works on every V17+ version). -
Duration output format prefix
Pwith thesspecifier (display-only / read-back via keypad with caveats).
Background: TIME Is a DINT Subtype
Internally the IEC 61131-3 TIME data type is stored as a 32-bit signed integer (DINT) representing milliseconds. The same is true for PLC tags exposed to WinCC Unified via the HMI tag — the engineering value transferred between the controller and the HMI is the raw DINT in milliseconds. This is the same convention that the old Comfort Panel "Scaling 1000:1" property exploited: divide by 1000 for display, multiply by 1000 for write-back.
Important equivalences:
| IEC value | DINT (ms) | Seconds (integer) |
|---|---|---|
T#1ms |
1 | 0 |
T#1s |
1000 | 1 |
T#1m |
60000 | 60 |
T#1h |
3,600,000 | 3600 |
T#-1s |
-1000 | -1 |
The WinCC Unified runtime inherits the same DINT representation. The IO field's "Process value" can therefore be assigned a TIME HMI tag (which is a DINT in the runtime model) and the engineer has full freedom over how it is formatted on the screen — provided the engineer bypasses the built-in time-picker user control.
Prerequisites
- TIA Portal V17 / V18 / V19 / V20 with WinCC Unified option installed (article verified against the V20 documentation set; V17/V18/V19 behavior is functionally equivalent for the properties described).
- A configured Unified Comfort Panel, Unified PC Runtime, or WinCC Unified SCADA station with a loaded project.
- PLC tag of type
TIME,S5TIME, or plainDINTexposed to the HMI as an HMI tag. - For the script-based approach: User-defined scripts enabled under Runtime settings → Script runtime → Allowed script languages = JavaScript.
- For the Shift decimal places approach: HMI tag must be numeric (INT/DINT/WORD/TIME) — see Siemens Support entry 109816808.
DINT tag first. Writing 0 ms to a TIME tag that controls a running timer (e.g. PLC timer coil reset) will stop the timer. Add a confirmation step in the operator dialog or use an Output mode IO field while commissioning.Method 1 — Shift Decimal Places (Recommended)
The Shift decimal places property of the WinCC Unified IO field is the documented, scripting-free way to rescale an integer process tag by a power of ten. It is described in the official engineering documentation under IO field (RT Unified) — TIA Portal V20 docs and the underlying use case (integer value with decimal places, with round-trip back to the PLC) in Siemens Support entry 109816808.
Configuration Steps
- Drag an IO field onto the screen.
- Under Properties → General, set Process value to the
TIMEHMI tag (the runtime sees it as DINT, so the binding is valid). - Set Mode to Input/output if operators must change the value; Output for read-only displays.
- Set Output format to
{I5}for a five-digit zero-padded integer (allows up to 99999 seconds ≈ 27 h). Use{I7}if you want sub-millisecond precision when the underlying tag is LTime. - Set Shift decimal places to
-3. The runtime divides the incoming DINT by 103 = 1000 for display (ms → s) and multiplies the operator's integer input by 1000 before writing it back to the tag. - Set Decimal places to
0to keep a pure integer field (no decimal point is shown when decimal places = 0). - Disable the time picker. In TIA V20 the picker is suppressed automatically when an explicit Output format containing
{I…}is used; if it still appears, set Display of time = No in the IO field properties (where available) or change the connected tag type to plainDINTwhile keeping the same scaling logic on the PLC side.
Numerical Behaviour
| Tag value (ms) | Shift decimal places | Field shows | Operator writes | Tag becomes (ms) |
|---|---|---|---|---|
| 0 | -3 | 0 | 0 | 0 |
| 1000 | -3 | 1 | — | — |
| 60000 | -3 | 60 | — | — |
| 12345 | -3 | 12 (truncated) | — | — |
| — | — | — | 30 | 30000 |
| — | — | — | 99999 | 99999000 |
{F6.3} format — but operators will see a decimal point and lose the integer-only UX.Why This Beats the Old Comfort Scaling
The Comfort Panel (V13/V14/V15/V16) screen object "IO field → Properties → Scaling" had explicit Linear scaling with arbitrary slope/intercept. In Unified, that property was removed and replaced by the more restrictive Shift decimal places. For 1000:1 (ms ↔ s) — the dominant case — Shift decimal places is functionally identical and lighter on runtime CPU because the runtime uses a single bit-shift rather than an FPU multiply.
Method 2 — Script Dynamization + PropertyChanged Event
Use this method when (a) the tag is not a pure power-of-ten multiple of seconds, (b) you want clamping or range adaptation, or (c) you need a DINT tag (not TIME) on the PLC side while the field still reads in seconds. The technique is to add a dynamization script to the IO field's Process value property and a propertyChanged event script that writes the operator entry back to the tag scaled by 1000.
Step-by-Step
- Create an internal HMI tag of type
DINT, name it e.g.HMI_seconds. (A real PLCTIMEtag can also be used; the scaling still applies.) - Place an IO field. Set Process value to
HMI_seconds, set Output format to{I5}. - In the screen's Scripts editor create two new scripts:
Script 1 — iof_seconds_dynamization (assigned to Process value via dynamization):
// Read DINT milliseconds from PLC, expose as integer seconds to the field.
// Triggered every cycle the source value changes.
export function iof_seconds_dynamization() {
let ms = Tags("PLC_timer_ms").Read();
let s = ms / 1000; // implicit float → integer division because output format is {I}
return s;
}
Script 2 — iof_seconds_writeback (assigned to IO field event "Process value → propertyChanged"):
// User has entered an integer-seconds value. Multiply by 1000 and push to PLC.
// Context.EventPropertyValue carries the post-dynamization value the operator confirmed.
export function iof_seconds_writeback() {
let s = Context.EventPropertyValue;
let ms = s * 1000;
Tags("PLC_timer_ms").Write(ms);
}
- On the IO field, in Events → Process value → propertyChanged, assign Script 2.
- On the IO field, in Properties → Process value → Dynamization, assign Script 1.
Edge Case — Mutually Triggering Loops
If the dynamization script and the propertyChanged event are wired to the same tag without any guard, the following loop occurs:
- Tag changes (e.g. from PLC) → dynamization fires → returns 30.
- Runtime writes 30 to the IO field, fires propertyChanged → Script 2 writes 30000 ms back to the tag.
- If
PLC_timer_ms≠ 30000, the tag value changes again → goto 1.
The loop converges when the displayed value times 1000 equals the tag value (i.e. when the tag is already an exact multiple of 1000 ms). It will not bounce in steady state, but it does cause two script invocations per operator action. Two ways to avoid it:
-
Switch the event to Input finished instead of
propertyChanged.Input finishedfires only when the operator presses Enter / the confirm button — it does not fire when the dynamization script updates the field, so the round-trip runs exactly once per operator entry. -
Add an idempotency guard in Script 2 by comparing
Context.EventPropertyValueto the current displayed seconds and skipping the write when they are equal.
Recommended: Input-finished wiring
// Same scaling math, but fires only on operator confirmation — no loop.
export function iof_seconds_writeback() {
let s = Context.EventPropertyValue;
let ms = s * 1000;
Tags("PLC_timer_ms").Write(ms);
}
Assign this script to IO field → Events → Process value → Input finished. The dynamization script (Script 1) remains on the Process value property.
Method 3 — Duration Output Format Prefix
If the operator only needs to read the value as duration, or accept input via a custom keypad that you control through a separate integer field, the Duration formatter prefix P offers a compact display without any scaling math.
| Format string | Meaning | Example output for t#3675s |
|---|---|---|
{P,h} |
Hours, integer, no leading zero | 1 |
{P,m} |
Minutes, integer, no leading zero | 1 |
{P,s} |
Seconds, integer, no leading zero | 15 |
{P,ss} |
Seconds, integer, one leading zero | 15 (no change because value > 9) |
{P,S} |
Milliseconds (uppercase S!) |
0 |
{P,h:m:s} |
Composite h:m:s
|
1:1:15 |
{P,hh:mm:ss} |
Composite with leading zeros | 01:01:15 |
Caveats
- Entering a value via touch still invokes the time picker — the Duration format is display-only for input. Pair it with Method 1 or Method 2 for true integer input.
- The leading-zero behaviour of
{P,ss}is asymmetric:{P,ss}for 5 seconds shows05, but the runtime will not allow a single-digit hour specifier like{P,h}to render as5with a leading zero — use composite{P,hh:mm:ss}if you need zero-paddedh. - Values larger than the formatter's natural range render up to the next unit. A
{P,s}field with 90061 s shows90061; the field does not roll into minutes automatically — that requires the composite format{P,h:m:s}.
Choosing Among the Three Methods
| Criterion | Shift decimal places | Script dynamization | Duration format {P,s} |
|---|---|---|---|
| Scales by exactly 1000 (ms ↔ s) | Yes | Yes (configurable) | No (display only) |
| Integer-only input on touch | Yes | Yes | No (opens time picker) |
| No JavaScript knowledge required | Yes | No | Yes |
| Supports non-power-of-10 scaling | No | Yes (any ratio) | No |
| Supports LTime / nanoseconds | Only with negative shift | Yes (full script) | Format-dependent |
| RPM impact on screen refresh | Negligible | Two script calls/event | Negligible |
| Recommended for production screens | Yes | Yes (when scaling ≠ 1000) | No (input UX is wrong) |
Verification Procedure
- Compile and download the project to the Unified panel / PC Runtime.
- Start Runtime. Open the screen containing the IO field.
- Force the PLC tag from the watch table to
1000ms. Verify the IO field shows1. - Force
60000ms. Verify60. - Force
-30000ms. Verify-30(negative values are valid forTIME). - Touch the field. Confirm the numeric keypad opens (not the time picker).
- Enter
45, confirm. In the watch table verify the PLC tag is now45000. - Enter a value exceeding the format width (e.g.
999999for a{I5}field). The runtime should clamp to the maximum representable value for the format width; document this clamp in your operator instructions. - If using the script approach: open Runtime → Diagnostic → Script trace and verify each script fires exactly once per operator action (after switching to the Input finished event).
Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
| Field still shows the time picker on touch | Output format left blank; runtime defaults to time UI | Enter {I5} in Output format (or use Duration prefix {P,s}) |
| Field shows the value times 1000 instead of divided | Shift decimal places sign is wrong | Use -3, not +3, for ms → s conversion |
| Field shows the value correctly but write-back multiplies by 1000 twice | Both dynamization script AND IO field scaling enabled | Use only one method — either Shift decimal places OR script scaling |
| Warning triangle on the field at engineering time | Format string does not match the underlying data type | Use {I…} for DINT/INT, {F…} for REAL; never combine |
| Script fires twice per operator entry | propertyChanged event wired, dynamization active | Switch to Input finished event |
| Sub-second value lost on display | Decimal places = 0 truncates | Set Decimal places = 3 for fractional visibility, or accept truncation by design |
| Operator can type letters | IO field Mode set to Output in error, or data type permissive | Set Mode = Input/output and bind to DINT/TIME |
| Value flashes / oscillates between two readings | Round-trip loop with non-multiple-of-1000 ms source | Pre-scale on PLC side or accept truncation via Shift decimal places |
Field-Proven Caveats
-
Format width and overflow: A
{I5}field saturates at ±99999. For ranges exceeding 27 hours use{I7}(up to 9,999,999 s ≈ 115 days) or composite Duration format{P,d:h:m:s}for day-level displays. -
LTime tags: When the source PLC tag is
LTime(64-bit, nanoseconds), Shift decimal places still works but use-9for nanosecond → second conversion. The output format must accommodate the resulting magnitude — usually{I10}or larger. -
Negative durations: IEC 61131-3 permits negative
TIMEvalues.Shift decimal placeshandles them correctly. The Duration formatter{P,s}shows negative values with a leading minus sign. -
Panel class differences: The Unified Comfort Panel V20 firmware (≥ V20.0.0.0) supports all three methods. Earlier Unified Comfort firmware (V17) has known bugs where Shift decimal places is ignored on
TIMEtags; if you encounter this, fall back to the script method. - Browser-based Unified PC Runtime resolves the same scripts through V8, but the script IDE does not syntax-highlight legacy VB-style scripts — stick with JavaScript.
Frequently Asked Questions
How do I display a WinCC Unified IO field bound to a TIME tag as integer seconds without the time picker?
Set the IO field's Output format to {I5} (or any {I…} width), set Decimal places = 0, and set Shift decimal places = -3. The runtime divides the underlying DINT (milliseconds) by 1000 for display and multiplies the operator's input by 1000 on write-back.
Why does the time picker still appear even after I configure Output format?
The runtime falls back to the time picker when Output format is empty or does not match the data type. Ensure the format string is present, contains a valid {I…} token, and that the Process value is bound to a numeric (INT/DINT/WORD/TIME) tag. Verify with the Siemens Support entry 109816808.
What is the difference between the Duration formats {P,s} and {P,S}?
Lowercase s renders seconds; uppercase S renders milliseconds. For the value t#1500ms, {P,s} displays 1 and {P,S} displays 500.
Can I bind the IO field directly to a DINT tag instead of TIME and still use seconds?
Yes. Either scale the value to/from seconds in the PLC program and use the IO field at 1:1, or use a script dynamization that multiplies/divides by 1000 inside the HMI script — the latter avoids PLC scan-time overhead.
My script fires twice for every operator change. How do I stop it?
Switch the event handler from propertyChanged to Input finished. Input finished fires only when the operator explicitly confirms the entry, so it does not chain with the dynamization script.
Does Shift decimal places work for LTime tags in nanoseconds?
Yes. Use -9 to convert nanoseconds to seconds. The output format width must be large enough (typically {I10}) to display the full LTime range converted to seconds.