S5 to S7 STL Conversion Decoding SE Timer and Counter-to-MB

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

Program Overview

The six-line STEP 5 STL snippet taken from a working batching plant implements a self-restarting on-delay pulse, an up-counter, a counter-to-flag copy, and a flag-driven counter reset. The construct is the canonical SIMATIC divide-by-N sequencer used to march through recipes, dispense ingredients, advance stage bits, or generate shift-register outputs without a sequencer GRAPH package. This reference decodes each instruction, establishes the difference between German and English timer mnemonics, explains the single-cycle pulse behavior that limits one count per OB1 sweep, walks through the bit-pattern reset at value 8, documents the cold/warm restart retention of C0, and finishes with verified STEP 7 STL and SCL equivalents that run on S7-300, S7-400, ET 200S, and S7-1200/1500 CPUs. Every parameter, format word and edge case below is taken from the official Siemens Programming with STEP 7 manual and the SIMATIC S5 to S7 converter documentation, both available through the Siemens Industry Online Support portal.

Annotated Source Program

The exact S5 STL block excerpt is reproduced below with operand-level commentary. All addresses use the S5-115U/135U/155H model in which timer T127, counter C0, and flag word MW5 share the same OB1 process image.

| Network 1                                              | Code | Operand | Comment                                                   |
| ---                                                   | ---  | ---     | ---                                                       |
| 1                                                     | AN   | T 127   | Examine T127.Q as NO contact; passes when timer idle    |
| 2                                                     | L    | S5#250MS| Load 250 ms preset into ACCU1-L                          |
| 3                                                     | SE   | T 127   | Start on-delay timer (German: Setze Einschaltverzögerung)|
| 4                                                     | CU   | C0      | Count Up on rising edge of T127.Q                        |
| 5                                                     | L    | C0      | Load counter word                                         |
| 6                                                     | T    | MB 5    | Transfer to flag byte 5 (low byte of MW5)               |
| 7                                                     | A    | M 5.3   | Examine flag bit 5.3 (= value 8)                         |
| 8                                                     | R    | C 0     | Reset counter when M 5.3 = 1                             |

The block was lifted from a S5-to-S7 conversion. In STEP 7 STL the same lines translate to either IEC timers/counters (TON, CTU) or to the SIMATIC-native S_ODT/S_CU FBs. The remainder of this article covers both styles.

SE Timer Mnemonic: German vs. English Mnemonics

The SE opcode is the most frequently misread instruction in translated S5 programs because STEP 5 ships two incompatible mnemonics: the German set, which Siemens ships by default on European firmware, and the English/American set, which STEP 7 and the S7 converter expect on PLCs delivered to North America. The official mapping is documented in the Siemens STEP 7 STL/LAD/FBD Programming and Operating Manual and reproduced in the table below.

STEP 5 German mnemonic STEP 5 English mnemonic STEP 7 SIMATIC FB IEC 61131-3 FB Behavior
SI (Setze Impuls) SP S_PULSE TP Pulse — output true while input true or while time running
SV (Setze Verlängerter Impuls) SE S_PEXT —
SE (Setze Einschaltverzögerung) SS S_ODT TON On-delay — output true only after time elapses with input still true
SS (Speichernde Einschaltverzögerung) SS (retained) S_ODTS TONR Retentive on-delay
SA (Setze Ausschaltverzögerung) SF S_OFFDT TOF Off-delay

Within the source listing SE = Setze Einschaltverzögerung, i.e. a non-retentive on-delay equivalent to S_ODT / TON. The discussion thread confirmed this empirically: the digital output of T127 observed on a TRACE is a single-scan TRUE pulse generated each time the timer elapses, exactly matching TON behavior.

Mnemonic trap: When converting by hand, always confirm the project locale. Switch the STEP 7 editor options via Options → Customize → Language, or query the STL source for SI/SP, SV/SE, SE/SS, SS and SA/SF pairs. A wrong remap gives a true pulse instead of an on-delay and breaks every downstream counter that depends on a single rising edge per cycle.

The 250 ms Time Base and the S5T Format Word

The constant S5#250MS is a 16-bit SIMATIC time word laid out as follows. Resolution is fixed at 10 ms for word-oriented S5 timers; the time base is decoded automatically by the CPU from bits 13/14.

Bit 15 14 13 12 .. 0
Meaning 0 (BCD) Time base 10n s — BCD value 0..999

Setting bits 14:13 to 00 and value bits to 250 yields the time 25.0 s; setting bits to 01 and value to 025 yields 2.5 s; setting bits to 10 and value to 250 yields 25 s × 10 = 250 s; and setting bits to 11 and value to 002 yields 2 × 100 ms = 200 ms. In practice the value ladder used to configure 250 ms is:

bit 15 = 0          // BCD time
bit 14,13 = 1,0     // 1 s time base, 10 ms resolution
bits 12..0 = 025 H  // 25 in BCD

Hex encoding of T127 = 10 00 0001 1111 1001b  = W#16#10 50  
// OR (depending on BCD):  W#16#2050

Working in STEP 7, the equivalent constant is S5T#250MS or T#250ms depending on whether S5TIME or TIME is expected. STEP 7 stores the value in the same 16-bit word but the editor validates the format automatically.

Single-Cycle Pulse Behavior of T127

The combination AN T127 — L S5#250MS — SE T127 is a textbook S5 "generate-one-pulse-on-elapse" pattern. Step-by-step OB1 scan semantics:

  1. Scan n, idle state: T127.Q = 0 → AN T127 evaluates TRUE, the SE instruction starts T127 with preset 250 ms.
  2. Scan n + k (after 250 ms wall-clock): T127 internal time ≥ preset → T127.Q latches to 1.
  3. Scan n + k + 1: AN T127 now evaluates FALSE (T127.Q = 1), so the SE instruction no longer loads the timer. S5 timers without continuous loading revert to inactive within one additional scan.
  4. Scan n + k + 2: T127.Q = 0 → AN T127 TRUE again → SE restarts the timer. Cycle repeats.

Net effect: T127.Q is HIGH for exactly one OB1 scan per 250 ms, producing a clean rising edge for CU C0. The period is 250 ms plus one scan time; for OB1 at 10 ms this translates to a counter increment every 260 ms, or roughly 3.85 Hz. The waveform is:

AN T127 — drives SE — T127.Q HIGH 1 cycle 250 ms elapsed, T127.Q asserted for the next single OB1 scan. Single rising edge per 250 ms drives CU C0.

This pulse-on-elapse pattern is the preferred idiom in STEP 5 because S5 has no native one-shot (POS) edge detector. STEP 7 supplies FP (positive edge on RLO) for the same purpose, so the entire 3-line block can be replaced by a single FP against a clock bit if a cyclic OB is available.

CU Counter Instruction and the C0 Word

The CU C0 statement increments the counter only when its RLO transitions from 0 to 1. Because T127.Q is HIGH for exactly one OB1 scan, only one increment occurs per elapse. The C0 word layout is identical to a flag word — 16 bits, BCD-encoded by default in S5, signed integer in STEP 7.

Bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Weight (binary) — — — 2048 1024 512 256 128 64 32 16 8 4 2 — 1

Bits 11..0 are the actual count (BCD or INT depending on whether CU is paired with L C0 in BCD or binary mode). Because the source uses L C0 / T MW5, the counter's BCD value is copied to MW5, and the low byte MB5 exposes the binary count. Bits 15..12 always remain at zero for counts below 4096.

Counter-to-MB Transfer Mechanics

The pair L C0 — T MB 5 appears to bypass the word boundary; in fact T MB5 writes the low byte of ACCU1-L into flag byte 5, and leaves ACCU1-L untouched so that ACCU1 still holds C0. The CPU extends the byte write to the word bus automatically; if you wish to mirror MB6 as well, use T MW5 directly.

MW5 byte map Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
MB5 (low byte) M5.7 M5.6 M5.5 M5.4 M5.3 M5.2 M5.1 M5.0
MB6 (high byte) M6.7 M6.6 M6.5 M6.4 M6.3 M6.2 M6.1 M6.0

The flag-bit mapping in MB5 follows the standard binary weighting:

M5.0  = 1   (count = 1, 3, 5, 7)            <-- 250 ms toggle #1
M5.1  = 2   (count = 2, 3, 6, 7)            <-- 500 ms toggle #2
M5.2  = 4   (count = 4, 5, 6, 7)            <-- 1 s   toggle #3
M5.3  = 8   (count = 8 only)                <-- 2 s   reset / stage advance

At count 8, MB5 = 0000 1000b; A M 5.3 closes the reset contact and R C 0 clears the counter on the same scan, restoring C0 = 0 and MB5 = 0x00 for the next cycle. The thread author confirmed the original programmer's intent was "to create three 250 ms pulses (M5.0, M5.1, M5.2)". Bit M5.3 was added as the auto-reset detector — a typical S5 trick for substituting a fixed-count sequencer without writing a separate OB.

Bit-Pattern Frequency Divider

The eight-state cascade behaves as a pure divide-by-8 binary ripple counter. Below is the full state table produced as T127 fires eight times:

CU edge # C0 / MB5 (binary) M5.0 M5.1 M5.2 M5.3 Action
0 0000 0000 0 0 0 0 Initial state — no edges yet
1 0000 0001 1 0 0 0 First pulse flag
2 0000 0010 0 1 0 0 Second pulse flag
3 0000 0011 1 1 0 0 First + second
4 0000 0100 0 0 1 0 Third pulse flag
5 0000 0101 1 0 1 0 First + third
6 0000 0110 0 1 1 0 Second + third
7 0000 0111 1 1 1 0 First + second + third
8 0000 1000 0 0 0 1 Reset pulse — clears C0 in same scan

The thermal timing for each pulse is therefore:

  • M5.0: 250 ms ON, 1.75 s OFF (50% duty after averaging — actually a binary ripple)
  • M5.1: 500 ms period
  • M5.2: 1.0 s period
  • M5.3: 2.0 s period, 250 ms HIGH — perfect for advancing the next batching stage

Generalizing, the time to count from 0 to N is

T_total = N * T_timer
T_M_b.k = 2^(k+1) * T_timer        // period of flag bit M5.k
T_M_b.(n-1) = 2^n * T_timer       // reset pulse, where n = reset bit position

In a batching context M5.0, M5.1, M5.2 drive dispense valves for ingredients 1/2/3, and M5.3 resets the cup and increments the batch counter MW6.

Cold/Warm Restart Retention of C0

The thread raised a critical concern: "will Counter not be reset to 0, if CPU is switched off?" The S5 retention model is well defined per the Siemens STEP 7 Programming Manual and the legacy S5 CPU manual set:

  • Counter type 1 (CU) retains its word across power-down, restart, and STOP-RUN transitions.
  • Counter type 2 resets on power-down but keeps the value across warm restart.
  • Counter type 3 resets on every restart.

The counter retention class is configured via the S5 system data block OB100/OB101/OB102 equivalent — in STEP 7 this is the CPU Properties → Retentive Memory → Counter screen. The original S5 program likely left C0 in the default Type 1 (retentive on power-off). Therefore the assumption in the thread — that "Timer T127 will remain ON as long as CPU is not switched off after POWER ON" — is correct only for the timer, not the counter. The counter C0 retains its previously accumulated count, which is why the auto-reset on M5.3 is mandatory: without it C0 would walk over 8 and saturate at 999.

STEP 7 conversion warning: When S5 counters are migrated via the STEP 7 converter, S7-300/400 CTU/CTV/CTD blocks are non-retentive by default. You must mark the relevant counters as retentive in the CPU's hardware configuration or the count will reset on every power cycle, changing plant behavior. See the Retentive Memory section of the CPU properties in the S7 HW Config tool.

Equivalent STEP 7 STL Using TON and CTU

The canonical S7 conversion replaces the S5 SE timer with an IEC on-delay timer and the CU counter with an IEC up-counter. The MW5 target can be driven from the CV (current value) output of the CTU directly, eliminating the explicit L/T pair.

NETWORK 1    // 250 ms clock pulse
      A      M 0.0           // optional: clock bit from cyclic OB or memory bit
      L      S5T#250MS
      SD     T 1             // German mnemonic SD == SE; English SE on S7
      FP     _M0.0_Temp      // one-shot on T1.Q
      =      _Pulse_250ms    // pulse tag, drives the CTU below

NETWORK 2    // Up-counter + auto-reset at 8
      CALL   CTU     , DB1   // IEC CTU block, instance DB1
         CU  :=_Pulse_250ms  // Count Up on each 250 ms pulse
         R   :=M5.3          // Reset when MB5 bit 3 (count = 8) closes
         PV  :=7             // Preset value (7 with R from MB5.bit3 gives /8 div.)
         Q   :=Q_full        // Done bit
         CV  :=MW5            // Current value transferred automatically to MB5
       U     M 5.3
       R     C 0             // belt-and-braces explicit reset (legacy users)

Notes:

  • The CTU's CV output is of type INT in STEP 7 V5.5 and S7-1200/1500 (Tia Portal V18+). MW5 therefore reflects the binary count directly, and MB5 = low byte = exact equivalent of the S5 line T MB 5.
  • If TIA Portal is the target platform, declare a dedicated Instance DB or use a multi-instance inside a parent FB to keep the IEC counter data persistent.
  • Avoid the SIMATIC S_CU FB for new code; the IEC CTU is portable, type-safe, and matches the function-block style used elsewhere on S7-1200/1500.
  • Set Edge evaluation on the CU input if the upstream pulse is generated by a non-edge flag (e.g. = instead of FP), otherwise double-counting will occur.

Equivalent SCL / Structured Text

The same logic in SCL — currently the preferred entry for TIA Portal — is shown below. It removes the need for the FP helper and exploits the IEC CTU instance directly.

FUNCTION_BLOCK FB_BatchSequence
VAR
    tPulse    : TON;          // IEC on-delay
    ctUp      : CTU;          // IEC up-counter
    tTick250  : BOOL;         // public pulse tag
END_VAR
VAR CONSTANT
    CYCLE_MS  : TIME := T#250ms;
END_VAR

BEGIN
    // 250 ms one-shot
    tPulse(IN := NOT tPulse.Q, PT := CYCLE_MS);
    tTick250 := tPulse.Q;

    // Counter with auto-reset at 8
    ctUp(CU := tTick250 AND tPulse.Q,    // rising edge only
         R  := ("MB".5).3 OR ctUp.CV = 8,
         PV := 7);

    // Mirror CV into flag word for legacy devices
    "MW5" := INT_TO_WORD(ctUp.CV);

    // Batching outputs (M5.0..M5.2 are pulse flags, M5.3 advances stage)
    Valve1 := ("MB".5).0;
    Valve2 := ("MB".5).1;
    Valve3 := ("MB".5).2;
    StageAdv := ("MB".5).3;
END_FUNCTION_BLOCK

The SCL version makes the reset condition explicit (ctUp.CV = 8) rather than relying on a flag-bit read; both implementations run identically, but the explicit CV comparison is faster to scan in code review and immune to unintended writes to M5.3 from elsewhere in the program.

Edge Cases and Common Pitfalls

1. Scan-Time Drift

The S5 single-cycle pulse generator is a function of OB1 scan time. If a longer cyclic interrupt OB (OB35, OB36, …) executes the same network, the count will double. Always execute this block in OB1 only, or migrate to a hardware-timed OB35 tick.

2. Wrong Timer Mnemonic

If the locale is flipped (German ↔ English), SE becomes SV / SP. The result is a continuously-held output, not a one-cycle pulse. C0 increments every OB1 scan and saturates within tens of milliseconds.

3. Counter Retention Loss During Conversion

S5-115U defaults to Retentive = ON for counters and timers in the system data words 0..127. STEP 7 turns this off for CTU/CTD by default. Open HW Config → CPU Properties → Retentive Memory and tick the Counter byte addresses that were retentive in the S5 project. Without this, the batching recipe loses its current step on every power failure.

4. BCD vs. Binary Word

S5 CU C0 stores BCD counts with four-decade range; the IEC CTU stores INT. After migration MW5 can be read directly in INT but not in BCD. Use WORD_TO_INT only if the source word is suspected to be BCD; otherwise the binary reading is correct.

5. Flag-Byte Overlap with Other FB Data

Flag bytes MB0..MB7 are the default scratch area for S5 system software and STEP 7 system blocks (e.g. OB1 step counter, error bits). If another FB writes to M5.3, the counter reset fires prematurely and the divider only counts to 7. Move the workspace to MB20..MB40 or into an instance DB.

6. Two Counters Resetting Each Other

If a different counter C1 sets a bit that is then read by A M 5.3, race conditions may clear C0 before the next OB1 cycle and trap the count at zero. Use a read-only instance data block instead of flag-bit comparison.

7. Cycle Skips in Online Force

Using the S7 debug tools "Force" / "Modify" can hold M5.x in an arbitrary state, breaking the divider. Always release forces after commissioning and watchdog-test the recipe.

Verification and Commissioning Procedure

  1. Pre-energize: Open the STEP 7 hardware configuration, confirm Retentive Memory → Counter bit for C0 (address 0) is set, save and download to the CPU.
  2. Energize with T127 forced TRUE: In OB1 place a SET then = T127 (force reload) and verify with an online watch table that T127.Q pulses HIGH once every 250 ms ± scan time. Use STATUS VAR to capture a TRC trace at 100 ms sample rate.
  3. Counter cycle test: Insert a breakpoint on R C0 and confirm the counter word walks 1, 2, 3, 4, 5, 6, 7, 8, then resets to 0. The MB5 bits should follow the state table above exactly.
  4. Power-loss test: Toggle CPU from RUN to STOP, remove power for 30 s, restore, switch back to RUN. C0 should retain its last value, but if the bit-flag reset already fired it will be 0. If it is not 0, confirm that M5.3 was correctly latched at the moment of power-down (a TRC trace during the test is recommended).
  5. Long-run stability: Run the recipe for 24 h and verify that C0 cycles predictably. Calculate expected_counts = 24*60*60 / (8 * 0.25) = 4320; the downstream batch counter should match within ±0.5 % once drift is accounted for.
  6. Replace flag bytes: Once the recipe proves stable, move the workspace from MB5 to a typed instance DB to remove risk of cross-talk from other FCs.

Reference Parameter Table

Operand Symbol Type Default value / range Notes
T127 TimerOneShot TIMER 0 s..3 h 16 m, 250 ms target S5 SE / S7 S_ODT — non-retentive
C0 StageCtr COUNTER 0..999 (S5 BCD), 0..32 767 (S7 INT) Default retentive in S5-115U; configure retentive in STEP 7
MB5 BitMirror BYTE 0x00..0xFF Low byte of MW5; bit-pattern driven by C0
M5.0 Valve1Pulse BOOL 250 ms period Dispense actuator 1
M5.1 Valve2Pulse BOOL 500 ms period Dispense actuator 2
M5.2 Valve3Pulse BOOL 1.0 s period Dispense actuator 3
M5.3 StageAdvance BOOL 2.0 s period, 250 ms HIGH Resets C0, advances downstream counter MW6
Documentation source: All timer/counter semantics cited in this article match the S7-300/400 Programming with STEP 7 V5.5 manual, the S5 to S7 converter README, and the IEC 61131-3 third edition timer/counter model. Always confirm against the live firmware help (F1) inside STEP 7 or TIA Portal for the exact CPU in use.

Troubleshooting Matrix

Symptom Likely root cause Verification step Fix
Counter increments every scan, not every 250 ms SE/SS mnemonic mismatch in STL source Toggle locale in STEP 7 editor and rebuild Convert SE → S_ODT / SS / TON
Counter resets immediately to 0 after every increment Another block writes M5.3 = 1 Force M5.3 = 0 from watch table Move divider logic to instance DB
Counter never resets, saturates at 999 Bit M5.3 never reaches 1 — wrong transfer target Watch MB5 online; expect 0x08 at count 8 Use T MW5 not T MB5 if counter is INT
Counter resets on every CPU restart Retentive bit not configured HW Config → CPU → Retentive → Counter Tick C0 / CTU instance byte
Flag bits 5.4..5.7 also toggle Counter is BCD, T MW5 mirrors decade 1,2 Set decimal display and confirm Use INT counter and CTU CV output
Pulse period doubles after OB35 added Same network runs in two OBs Cross-reference and remove duplicates Limit execution to OB1

FAQ

What does the S5 opcode SE actually do?

SE is the German STEP 5 mnemonic for an on-delay timer (Setze Einschaltverzögerung). It is equivalent to S_ODT in STEP 7 STL and to the IEC TON block. The English STEP 5 mnemonic for the same instruction is SS; the English STEP 5 SE means "Extended Pulse" (Setze Verlängerter Impuls) and behaves like a TP. Confirm the locale before reading the source.

Why does T127 only generate a single-cycle pulse even though it is set to 250 ms?

The combination AN T127 — L S5T#250MS — SE T127 loads the timer only while T127.Q = 0. As soon as the 250 ms elapse and T127.Q latches to 1, the AN T127 contact opens, the SE instruction stops driving the timer, and T127.Q reverts to 0 on the next scan. The pattern therefore produces one 1-cycle HIGH every 250 ms and nothing else.

Is the counter C0 retained across a power-off / power-on cycle?

By default, S5-115U CU counters are retentive; the value is held in the S5 system data area and survives power-down. In STEP 7 the equivalent IEC CTU is non-retentive unless the byte address is enabled in HW Config → CPU Properties → Retentive Memory → Counter. Without this setting, the batch count is lost every restart and the sequencing drifts.

How does the line T MB 5 transfer a 16-bit counter to a byte?

The CPU always operates on a 16-bit accumulator, so L C0 loads the full word into ACCU1-L. T MB 5 writes ACCU1-L-L (the low byte) into flag byte 5; ACCU1 is unaffected and the high byte is also written to MB6. The same line in STEP 7 is most cleanly replaced by driving MW5 := CTU.CV directly, which is type-safe and avoids the implicit byte aliasing.

What is the cleanest STEP 7 replacement for the S5 SE timer + CU counter block?

Use an IEC TON with PT = T#250 ms, then a CTU with PV = 7 and R bound to a flag bit that fires when CV = 8. Declare a single Instance DB for both blocks, and route the CTU's CV output to MW5. This eliminates the manual L/T pair and the legacy FP helper, and the entire divider becomes single-scan, non-blocking, and portable to S7-1200/1500.

Back to blog