Displaying S7-1200 TIME Remaining on HMI: Hours and Minutes

David Krause18 min read
S7-1200SiemensTutorial / 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

1. Overview: From Operator Set-Point to HMI Countdown

When a Siemens S7-1200 CPU is configured as the controller for a batch or dwell-time application, the operator enters a duration in hours through a TIA Portal HMI tag (e.g., 20 h). The CPU stores that value in a TIME tag and feeds it to an IEC timer such as TON, TP, or TONR. While the process runs, the engineer wants the same panel to display a live countdown showing how many hours and minutes remain before the timer expires.

The TIME data type on S7-1200 and S7-1500 is a 32-bit signed integer that counts milliseconds. TIA Portal's editor renders the value as T#20h0m0s0ms, but the underlying integer is just 72,000,000. A raw transfer of that integer to an HMI text field shows "72000000" — technically correct, but operationally unreadable. The conversion from the millisecond integer to a human-readable HH H MM M string must happen on the PLC side; the HMI only renders the result.

The source requirement is a string of the form "10H 43M 12S" on a TIA Portal HMI panel (KTP700, KTP1200, Comfort, or Unified). The seconds component is optional, but the hours and minutes must be readable at a glance from a 7-inch Basic panel at 2 m distance. This article covers three engineering approaches:

  1. Convert TIME to a DTL structure with T_CONV, then read the HOUR and MINUTE fields.
  2. Decompose the millisecond integer with SCL arithmetic into hours, minutes, and (optionally) seconds.
  3. Compute remaining run time from a real-time-clock source with T_DIFF, then push a formatted string to the HMI.

Each method ships with an SCL function block, an HMI tag wiring table, and a commissioning checklist that can be copied directly into a TIA Portal V17 or V18 project.

2. The TIME Data Type Internals on S7-1200/1500

Per the SIMATIC S7-1200 Programmable Controller System Manual and the SIMATIC S7-1500 System Manual, TIME occupies 4 bytes and is stored as a signed DINT in milliseconds. The range and resolution are summarized below.

Property Value
Width 32 bits (DINT)
Resolution 1 ms (sign bit + 31-bit magnitude)
Minimum T#-24d_20h_31m_23s_647ms = -2,147,483,648 ms
Maximum T#+24d_20h_31m_23s_647ms = +2,147,483,647 ms
Default literal format T#<DAYS>d_<HOURS>h_<MINUTES>m_<SECONDS>s_<MS>ms
IEC timer output type TIME (elapsed time until preset reached)
Behavior on overflow Rolls over to T#-24d_20h_31m_23s_647ms
Standard IEC 61131-3:2013, §6.4.2
Engineering note: The TIA Portal editor always displays the TIME tag in T# syntax with all five components (days/hours/minutes/seconds/ms). The PLC, however, stores the value as a plain 32-bit signed integer. Any HMI tag that points at the TIME variable will receive the raw ms count unless the data is pre-formatted on the PLC side. This is the root cause of the source-reported "Text Box didn't work" symptom: the HMI is faithfully displaying the integer, just not the human-friendly string.

3. IEC Timer Instructions: TON, TOF, TP, and TONR

The S7-1200 and S7-1500 instruction sets include the four IEC 61131-3 timers. Each has a PT (preset time) input of type TIME and an ET (elapsed time) output of type TIME. The ET value is exactly what is required to drive a remaining-time string on the HMI. The IEC 61131-3:2013 standard defines the behavior of these four function blocks in §6.4.3 (function block types TP, TON, TOF, and TONR).

Instruction Behavior ET behavior Typical use case
TON (on-delay) ET increments while IN=1; Q=1 when ET ≥ PT Counts up from 0 to PT Dwell time, batch stage
TOF (off-delay) ET increments after IN falls to 0 Counts up after falling edge Cool-down, fan run-down
TP (pulse) ET increments for fixed duration on rising edge Counts up from 0 to PT Fixed pulse length
TONR (retentive on-delay) ET accumulates; reset via R input Accumulates while IN=1 Total run hours, maintenance timer

For a process countdown the natural fit is TON: connect a Boolean run signal to IN, the operator-entered duration to PT, and read the elapsed time from ET. The remaining time is simply PT - ET and is a TIME tag that can be passed to the SCL function block in §7. The TONR variant is required when the operator's "20 h" is an accumulated requirement that must survive pause cycles.

For an S7-1200 with firmware below V4.0, the older legacy timer instructions S_PULSE, S_PEXT, S_ODT, S_ODTS, and S_OFFDT remain available. They expose a BI (binary, in seconds) and a BCD output. Use BI and then convert to TIME in SCL before formatting; the BCD output is encoded as BCD digits and is not directly compatible with the methods in this article.

4. Method 1: T_CONV from TIME to DTL

STEP 7 (TIA Portal) provides a set of Date and Time-of-Day extended instructions for the S7-1200 (firmware V4.0 and later) and S7-1500. The T_CONV block converts a TIME value into a DTL structure whose fields can be mapped individually to HMI tags. The full DTL structure is documented in the STEP 7 (TIA Portal) Programming and Operating Manual, chapter on date-and-time functions.

DTL field Data type Range Meaning
YEAR UINT 1970 to 2554 Year (offset = 1970 for TIME input)
MONTH USINT 1 to 12 Month
DAY USINT 1 to 31 Day of month
WEEKDAY USINT 1 to 7 Day of week (1 = Sunday)
HOUR USINT 0 to 23 Hour of day
MINUTE USINT 0 to 59 Minute of hour
SECOND USINT 0 to 59 Second of minute
NANOSECOND UDINT 0 to 999,999,999 Sub-second fraction

Important caveat: T_CONV treats the TIME input as an offset from 01-01-1970 00:00:00, not as a duration. The YEAR field rolls over after ~89 years, the MONTH rolls over after 30 d, the HOUR field rolls over after 24 h, and so on. The structure is convenient for displaying "5 h 23 m" but does not show a value larger than 24 h cleanly because the HOUR field resets to 0 at 24 h while the DAY field increments. For run times above one day the manual-arithmetic method (§5) is required.

4.1 Adding a Fixed Base Date

To keep the HOUR field at the same numeric value as the operator's set-point (i.e., 20 h rather than 20 h, then 0 h, then 0 h, ...), the cleanest path is to skip T_CONV entirely and use the manual arithmetic in §5. If T_CONV must be used, configure a base DTL constant (e.g., DTL#1970-01-01-00:00:00) and use T_ADD to add the TIME value to it, then read HOUR and MINUTE. This is rarely worth the effort; the arithmetic approach is shorter and faster.

5. Method 2: Manual Millisecond Decomposition in SCL

The most flexible approach is to decompose the millisecond count yourself. This method works on every S7-1200 firmware version (V1.0+) and gives full control over the display format, including values above 24 h and the option to suppress the seconds field entirely. The math is elementary:

  • TotalSeconds = TimeValue / 1000 (DINT division truncates)
  • Hours = TotalSeconds / 3600
  • Minutes = (TotalSeconds MOD 3600) / 60
  • Seconds = TotalSeconds MOD 60
  • RemainMs = TimeValue MOD 1000

The SCL implementation, written so that the result is a single concatenated STRING ready to drop into an HMI text field, is shown below.

FUNCTION_BLOCK "FB_TimeToHmiString"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
    iTimeMs : TIME;            // Raw time value, e.g. PT - ET of a TON
END_VAR
VAR_OUTPUT
    sDisplay : STRING[20];     // Output to HMI text field
END_VAR
VAR
    siTotalSec : DINT;
    siHours    : DINT;
    siMinutes  : DINT;
    siSeconds  : DINT;
END_VAR

BEGIN
    // Convert TIME (ms) to a seconds count
    siTotalSec := TIME_TO_DINT(iTimeMs) / 1000;

    // Decompose into hours, minutes, seconds
    siHours   := siTotalSec / 3600;
    siMinutes := (siTotalSec MOD 3600) / 60;
    siSeconds := siTotalSec MOD 60;

    // Build the "HH H MM M SS S" string
    sDisplay := INT_TO_STRING(siHours)   + 'H ' +
                INT_TO_STRING(siMinutes) + 'M ' +
                INT_TO_STRING(siSeconds) + 'S';
END_FUNCTION_BLOCK

The function block returns "20H 0M 0S" for a fresh TON with PT = T#20h and decays to "19H 59M 58S" after two seconds, exactly what the operator expects. For a no-seconds view (as in the source request, where seconds are not necessary), drop the seconds field and the trailing 'S'; the output becomes "19H 59M" and the STRING length can shrink to 12 characters.

5.1 Comparison of the Three Methods

Property T_CONV to DTL Manual SCL decomposition T_DIFF with RTC
Min CPU FW V4.0 (S7-1200) V1.0 (S7-1200) V4.0 (S7-1200)
Max display range 23 h 59 m 59 s 59,994 h (DINT limit) 24 d 20 h 31 m
Survives power cycle Yes (with retentive FB) Yes (with retentive FB) Yes (if deadline stored)
Update accuracy ±1 ms ±1 ms ±1 s (RTC resolution)
Code size 1 call (T_CONV) ~30 lines SCL 2 calls (RD_SYS_T + T_DIFF)
Edge cases HOUR saturates at 23 Handles any value Negative after deadline
Best for Short countdowns (< 1 day) Production countdown screens Shift-end deadlines
Edge case — negative values: A TIME tag can be negative (e.g., when ET > PT on a TON that has already elapsed, or when a T_DIFF deadline has passed). Wrap the result with a clamp if the HMI must not show a minus sign: IF siHours < 0 THEN siHours := 0; END_IF;

6. Method 3: T_DIFF for Real-Time-Clock Countdown

If the dwell time is measured against a real wall-clock deadline rather than a relative counter, use the CPU's real-time clock. The CPU exposes the current date and time as a DTL tag in the system clock byte (e.g., LocalTime from the RD_SYS_T instruction). Compare it against a deadline DTL using T_DIFF:

Parameter Declaration Type Description
IN1 Input DTL Earlier date/time
IN2 Input DTL Later date/time
RET_VAL Return TIME IN2 − IN1 as a TIME (ms) value

Wire the RTCDeadline to IN2 and the current LocalTime to IN1. The return value is the time remaining; feed it to the SCL function block from §5 and you have a wall-clock-based countdown that survives power cycles if the deadline is stored in a non-volatile data block.

// SCL inside FB_DeadlineCountdown
iRemainingTime := T_DIFF(IN1 := "DB_Time".LocalTime,
                         IN2 := "DB_Time".RTCDeadline);

Caution: T_DIFF returns a signed TIME. Once the deadline passes, the value goes negative; clamp it before passing to the SCL formatter to keep the HMI display tidy. The CPU's RTC drifts typically 1–2 seconds per day without synchronization; for higher accuracy, configure NTP via the CPU's PROFINET interface or use the SET_CLKSYN instruction to slave to a master clock.

7. SCL Function Block: FB_TimeToHmiString

The complete function block for Method 2 is shown below, including a "no-seconds" variant and a "lead-zero padding" option for a fixed-width HMI display.

FUNCTION_BLOCK "FB_TimeToHmiString"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.2
VAR_INPUT
    iTimeMs       : TIME;            // Raw time value
    bShowSeconds  : BOOL  := FALSE;  // TRUE = include "SS S" suffix
    bZeroPad      : BOOL  := TRUE;   // TRUE = "01H 02M" vs "1H 2M"
END_VAR
VAR_OUTPUT
    sDisplay      : STRING[20];
END_VAR
VAR
    siTotalSec : DINT;
    siHours    : DINT;
    siMinutes  : DINT;
    siSeconds  : DINT;
    sHours     : STRING[4];
    sMinutes   : STRING[4];
    sSeconds   : STRING[4];
END_VAR

BEGIN
    siTotalSec := TIME_TO_DINT(iTimeMs) / 1000;

    // Clamp negative values to zero
    IF siTotalSec < 0 THEN
        siTotalSec := 0;
    END_IF;

    siHours   := siTotalSec / 3600;
    siMinutes := (siTotalSec MOD 3600) / 60;
    siSeconds := siTotalSec MOD 60;

    IF bZeroPad THEN
        sHours   := INT_TO_STRING(siHours);
        sMinutes := INT_TO_STRING(siMinutes);
        sSeconds := INT_TO_STRING(siSeconds);
        WHILE LEN(sHours)   < 2 DO sHours   := '0' + sHours;   END_WHILE;
        WHILE LEN(sMinutes) < 2 DO sMinutes := '0' + sMinutes; END_WHILE;
        WHILE LEN(sSeconds) < 2 DO sSeconds := '0' + sSeconds; END_WHILE;
    ELSE
        sHours   := INT_TO_STRING(siHours);
        sMinutes := INT_TO_STRING(siMinutes);
        sSeconds := INT_TO_STRING(siSeconds);
    END_IF;

    sDisplay := sHours + 'H ' + sMinutes + 'M';
    IF bShowSeconds THEN
        sDisplay := sDisplay + ' ' + sSeconds + 'S';
    END_IF;
END_FUNCTION_BLOCK

The bShowSeconds and bZeroPad inputs give the integrator two common HMI formatting choices without needing a second FB. Place the FB call in a cyclic OB (e.g., OB1 main program) so the output is refreshed every PLC scan. The PLC scan time on a CPU 1214C with this FB is approximately 0.3 ms per call, well within the 1 ms budget of a 1 kHz process image update.

8. HMI Tag Configuration in TIA Portal / WinCC

The function block in §7 outputs a 20-character STRING. Connect that tag to an HMI text field as follows.

  1. Open the HMI device in the project tree and double-click HMI Tags.
  2. Add a new tag named RemainingTime with the PLC connection set to the S7-1200 and the DB path set to the sDisplay element of the FB_TimeToHmiString instance.
  3. Set Data type to String[20] and Length to 20 characters.
  4. Set Acquisition mode to Cyclic continuous with a 1-s update cycle.
  5. Drop a Text field onto the screen, open its properties, and bind the Text property to RemainingTime.
  6. In the Appearance tab set a monospaced font (e.g., Consolas) so the column alignment stays stable as digits change.

The procedure is identical for the SIMATIC HMI panels KTP700 Basic (6AV2123-2GB03-0AX0), KTP1200 Basic (6AV2123-2MA03-0AX0), Comfort panels TP700/TP1200/TP1500/TP1900 (6AV2 1xx series), and Unified Comfort panels (6AV2 1xx-2xx). For Unified panels, the Text field can be replaced by an Output element with a property binding to the same tag. For panels running WinCC RT V16 or later, the STRING tag is read at the configured cycle; for V14/V15 the maximum STRING length is 16 characters, so reduce the FB output to 16.

9. Output Field and String Formatting Choices

WinCC (TIA Portal) lets you use either a numeric I/O field or a text field. The trade-off is summarized in the table below.

Approach PLC tag type PLC CPU load HMI flexibility Best for
Raw numeric (ms) TIME None Display "72000000" Diagnostic only
Pre-formatted STRING STRING[20] Low (one FB cycle) Display "20H 0M" Operator HMI
Three numeric I/O fields (HH, MM, SS) 3× DINT Low Display separate fields Recipe screens
Multiplexed symbolic I/O field DINT Medium Bar/indicator with text overlay Progress display

For a clean "10H 43M" string the pre-formatted STRING approach is preferred. For screens that need separate spinner inputs (e.g., operator adjusts minutes only), the three-DINT approach is easier to wire to the WinCC I/O field configuration. To minimize the HMI-side update lag, see §11.4 below.

10. Ladder (LAD) and FBD Implementation

If the project does not allow SCL, the same logic is achievable in LADDER using the CALCULATE (CALC) and the String + Concatenate (S+) instructions. The decomposition is implemented as four CALC boxes:

CALC # Expression Output
1 (DINT)iTimeMs / 1000 TotalSec (DINT)
2 TotalSec / 3600 Hours (DINT)
3 (TotalSec MOD 3600) / 60 Minutes (DINT)
4 TotalSec MOD 60 Seconds (DINT)

Append three String + Concatenate (S+) boxes that build Hours + 'H ' + Minutes + 'M ' + Seconds + 'S'. The S+ box is documented in the STEP 7 (TIA Portal) Programming Manual and is available on S7-1200 from firmware V4.2 onward; on S7-1500 it is available in all firmware versions.

Watch the execution order: The four CALC boxes must run in the same cycle. Place them in a single network and ensure the S+ chain reads the outputs from the same cycle. The TotalSec intermediate tag must be declared in a static data block or as a temp variable, not as a local stack variable, otherwise the S+ boxes will read stale data on subsequent networks.

11. Commissioning and Verification Procedure

The procedure below assumes TIA Portal V18, an S7-1200 CPU 1214C DC/DC/DC (catalog number 6ES7214-1AG40-0XB0) with firmware V4.4, and a KTP1200 Basic (6AV2123-2MA03-0AX0) HMI panel.

  1. Compile the SCL function block and download the program to the CPU.
  2. Open Online & Diagnostics, force the input iTimeMs := T#20h, and confirm that the sDisplay tag reads "20H 0M 0S".
  3. Set iTimeMs := T#1h_2m_3s_456ms and verify that sDisplay = "1H 2M 3S". The millisecond component is intentionally dropped.
  4. Force iTimeMs := T#0ms and confirm the output is "0H 0M 0S", not an empty string. (This catches bugs in which the INT_TO_STRING output is padded with leading blanks.)
  5. Force iTimeMs := T#-1m and confirm the clamp returns "0H 0M 0S".
  6. Force iTimeMs := T#100h and confirm the output is "100H 0M 0S", not "4H 4M 0S". (This catches the T_CONV saturation bug if Method 1 was used.)
  7. On the HMI, navigate to the countdown screen, verify that the text field updates at exactly 1 Hz, and confirm the cycle counter in the PLC diagnostic buffer does not exceed +5 ms drift per minute.
  8. Cycle power to the CPU and confirm the countdown continues from the last value if the TON instance is in a retentive data block, or restarts from PT if it is not.
  9. Disconnect the HMI Ethernet cable and confirm the PLC continues updating sDisplay in the DB. (This catches a project bug where the FB sits in the HMI's cyclic interrupt OB instead of the PLC's OB1.)
  10. Force the PLC to STOP and back to RUN. The TON instance should reset; verify the HMI display returns to the operator's preset value, not to a stale "0".
  11. Enable the clock_1Hz memory bit on the CPU and use it to gate the FB call once per second. This drops the PLC CPU load by 90 % when the FB is the only one running every scan.

12. Common Errors, Edge Cases, and Cross-Platform Notes

The errors encountered most often when commissioning the function block are listed below.

Symptom Likely cause Fix
HMI shows "72000000" instead of "20H 0M" Tag bound to raw TIME tag, not the SCL output sDisplay Re-bind the HMI text field to the STRING output of the FB
HMI shows empty field STRING length mismatch between PLC and HMI Match the HMI tag Length to the FB output (e.g., 20 characters)
HMI shows the right value for 1 s, then freezes Acquisition mode set to On change; PLC writes the same STRING repeatedly Set acquisition to Cyclic continuous with 1-s cycle, or toggle a Boolean the HMI watches
Hours reset to 0 at 24 h Using T_CONV with DTL, HOUR field saturates at 23 Use Method 2 (manual arithmetic)
Negative numbers on HMI TON continues to count after PT, or T_DIFF deadline has passed Clamp the result with MAX(0, iTimeMs) before formatting
"STRING error" online Source string longer than declared length (e.g., 1000 h > 12 chars) Either widen the STRING or use a multiplier field (display "999+ H" if overflow)
Display updates but lags by 2 s HMI update cycle set to 2 s; PLC SCL FB runs every 100 ms Lower the HMI cycle to 500 ms; or accept the lag and document it
HMI display flickers every scan PLC writes a new STRING every 10 ms; HMI re-renders too often Gate the FB with a 1-Hz clock bit (e.g., clock_1Hz from the CPU system clock)
TONR shows wrong time after power cycle TONR instance DB not configured as retentive Set Retentive = true in the DB properties; add ET and IN to the retentive list

The TIME-to-HMI pattern is portable across SIMATIC controllers. The differences between the most common CPUs are summarized below.

Controller TIME width T_CONV support S+ concat support Notes
S7-1200 (CPU 1211C … 1217C, FW V4.0+) 32 bits, signed ms Yes Yes (FW V4.2+) Recommended target
S7-1200 (CPU 1212C, FW < 4.0) 32 bits, signed ms No No Use CALC + manual string build
S7-1500 (CPU 1511 … 1518) 32 bits, signed ms in IEC timers; ns in LTime All FW All FW Higher resolution; HOUR field still saturates at 23
ET 200SP CPU Same as S7-1500 All FW All FW Identical methodology
S7-300 / S7-400 (legacy STEP 7 V5.x) 32 bits, signed ms Yes (FC/FB 3, 4, 5) Yes Same SCL code works; import via STEP 7 migration tool

For non-Siemens controllers the algorithm is identical. On Allen-Bradley Logix, use the MOD and DIV instructions on a DINT and concatenate in structured text. On Modicon M340, the DWORD_TO_STRING function plus a similar decomposition works; the HMI side (EcoStruxure Operator Terminal Expert) accepts the same STRING tag.

13. FAQ

Why does the HMI show the raw millisecond integer instead of the formatted string?

Because the HMI tag is bound to the TIME variable (raw ms) rather than the STRING output of the SCL function block. Re-bind the text field to the sDisplay tag of the FB and reload the HMI project.

Can I display times greater than 24 hours without the HOUR field rolling over?

Yes. Do not use the T_CONV instruction for the HOUR field — it saturates at 23. Use the manual SCL decomposition in §5: Hours = TotalSeconds / 3600 returns the correct value up to 59,994 h before the DINT overflows.

What is the maximum value I can store in a TIME tag on an S7-1200?

±2,147,483,647 ms, which is approximately ±24 d 20 h 31 m 23 s. Above that the value overflows. If you need longer run times, store the deadline as a DTL (year-month-day-hour-min-sec) instead of a TIME.

Do I need TIA Portal V18 or is V16 sufficient?

The SCL function block in §5 compiles in TIA Portal V14 SP1 and later. The S+ concatenation box is from FW V4.2 of the S7-1200 (CPU firmware, not TIA Portal version) and STEP 7 V15.1. The S7-1500 S+ box is available in every TIA Portal version from V12 onward.

How do I avoid the HMI display lagging by one update cycle?

Use the Change acquisition mode in WinCC, not Cyclic continuous, and increment a hidden BYTE tag in the same network as the SCL FB. The HMI then re-reads the STRING on every byte change and the lag drops from one second to one PLC scan (1–10 ms).

Why does my TONR show the wrong time after a power cycle?

Because the TONR instance data block is not configured as retentive. In the DB properties, set Retentive = true and add the ET and IN tags to the retentive list. Without this, the timer resets to 0 on every cold start.

Back to blog