Overview
A zero speed switch (ZSS) is a safety-critical feedback element on conveyors, mixers, crushers, rotary valves, bucket elevators, and any rotating machine where a stopped shaft must be detected even though the motor contactor is closed. The most common field implementation is an inductive proximity sensor aimed at a target disc, cam, or bolt on the shaft. While the shaft rotates, the sensor produces a clean pulse train (typically 1 pulse per revolution, or N pulses per revolution when a multi-tooth target is used). When the shaft is stationary, the sensor output settles to either a hard 0 V or a hard 24 V depending on the last tooth position. A stuck-ON or stuck-OFF sensor is therefore indistinguishable from a real stop unless the logic watches for pulse activity.
This article documents three working implementations of ZSS logic in SIMATIC Manager for the S7-300 and S7-400 families:
- A classic two-timer (S_ODT + S_OFFDT) method, the easiest to read during commissioning.
- A one-timer edge-triggered method that halves the timer footprint when the CPU is constrained.
- A system function block method (SFC4 TON / SFC5 TOF) suitable for the IEC 61131-3 timer model.
All three are valid; the choice depends on available timer resources, cycle time, and operator visibility requirements.
Prerequisites
| Item | Requirement |
|---|---|
| Engineering software | SIMATIC Manager V5.5 SPx or higher, with STEP 7 V5.5+ installed |
| CPU family | S7-31x, S7-31xT, S7-31xF, S7-41x, or S7-400 (any FW that supports the standard library) |
| Hardware | One digital input module (SM 321 / SM 421) for the 24 V PNP proximity, one digital output (SM 322 / SM 422) for the ZSS relay output |
| Library | Standard Library > System Function Blocks (for SFC4/SFC5) and Program Elements > Timers (for S_ODT / S_OFFDT) |
| Sensor | 3-wire PNP NO inductive proximity, 10–30 V DC, < 5 mA off-state leakage, switching frequency ≥ 100 Hz |
| Mechanical | Target disc / cam with 1–4 actuations per revolution, mounted within sensor rated switching distance |
Zero Speed Switch Operating Principle
The block diagram below shows the complete ZSS feedback path.
The pulse train arriving at the digital input has a frequency proportional to shaft RPM:
f (Hz) = RPM × N / 60
where N is the number of actuations per revolution. The ZSS logic must declare the shaft as running only when the input transitions (both rising and falling) occur within a configurable window. Missing transitions inside that window are interpreted as zero speed.
Timer Function Blocks Available in Simatic Manager
SIMATIC Manager exposes two timer models. Choosing the right one is the first engineering decision.
| Block | Location | Type | Behaviour | Footprint |
|---|---|---|---|---|
| S_ODT | Program Elements > Timers | On-delay (hardware timer) | Output TRUE after TV of continuous TRUE at input |
2 bytes in T memory per instance |
| S_OFFDT | Program Elements > Timers | Off-delay (hardware timer) | Output stays TRUE for TV after a falling edge |
2 bytes in T memory per instance |
| S_PULSE | Program Elements > Timers | Pulse | Output TRUE for TV on rising edge |
2 bytes in T memory per instance |
| S_PEXT | Program Elements > Timers | Extended pulse | Output TRUE for TV on rising edge, retriggerable |
2 bytes in T memory per instance |
| SFC4 (TON) | Standard Library > System Function Blocks | IEC on-delay | Instance DB required | 16 bytes DB per instance |
| SFC5 (TOF) | Standard Library > System Function Blocks | IEC off-delay | Instance DB required | 16 bytes DB per instance |
The classic hardware timers (S_ODT, S_OFFDT) are bit-addressed in the T area (for example, T0, T1) and use a single 16-bit word in the system memory. They execute in the 100 ms / 10 ms / 1 ms time base set during configuration, with no instance DB required. They are fast and easy to wire, and they remain the most popular choice for ZSS logic on the S7-300.
The IEC timers (SFC4, SFC5) require a dedicated instance DB and use the IEC 61131-3 timing model. They are slightly more flexible (PT/ET words) but consume more memory and execute via SFC call in OB1.
Refer to the SIMATIC S7-300 CPU 31xC and CPU 31x Manual and the STEP 7 Standard Library reference for the full timer table and base-time selection rules.
Method 1: Two-Timer Implementation (S_ODT + S_OFFDT)
This is the clearest and most common ZSS pattern. The output is the OR of an on-delay and an off-delay driven from the same proximity input. As long as pulses keep arriving within the delay window, the output stays TRUE. When pulses stop (shaft stationary, sensor failed, or cable broken) the output decays to FALSE within TV.
Symbol table:
// I/O addressing
i_ZSS_Pulse I 0.0 // PNP proximity from target disc
q_ZSS_OK Q 4.0 // ZSS feedback to conveyor sequencer / contactor interlock
t_ZSS_OnDelay T 0 // On-delay timer (S_ODT)
t_ZSS_OffDelay T 1 // Off-delay timer (S_OFFDT)
// Time base / preset
t_ZSS_OnDelay.TV W#16#0200 // 200 * 100 ms = 20.0 s
t_ZSS_OffDelay.TV W#16#0200 // 200 * 100 ms = 20.0 s
Ladder (FBD view in Simatic Manager):
Network 1 — On-delay arm (T0):
A i_ZSS_Pulse
L S5T#20S // 20 second on-delay
SD T0 // Start on-delay T0
A T0
= q_ZSS_OK_part1 // Internal flag, network 3
Network 2 — Off-delay hold (T1):
A i_ZSS_Pulse
L S5T#20S // 20 second off-delay
SF T1 // Start off-delay T1
A T1
= q_ZSS_OK_part2 // Internal flag, network 3
Network 3 — OR combine and energise output:
O q_ZSS_OK_part1
O q_ZSS_OK_part2
= q_ZSS_OK
Why it works:
- While
i_ZSS_Pulsetoggles (any duty cycle, both rising and falling edges counted), the SD timer (T0) is held in continuous-run because the input restarts the time accumulator each cycle. The SF timer (T1) is also continuously retriggered because each pulse is a fresh rising edge. - The moment pulses stop, SD sees a falling edge and stops timing; SF continues timing from the last edge and expires after
TV. - If pulses resume before
TVelapses, both timers restart andq_ZSS_OKremains TRUE. There is no latching or debounce logic — the timers themselves provide the deadband.
TV to at least 1.5 × the longest expected gap between pulses. A 1 PPR target at 3 RPM gives one edge every 20 seconds, so the on/off delay must be longer than 20 s to avoid false zero-speed trips during slow rotation. Always include the safety margin.Method 2: Single-Timer Edge-Triggered Implementation
When the CPU timer resource is constrained (S7-312C with only 256 hardware timers, for example), the same ZSS function can be implemented with one timer and one static bit in a function block.
Approach: Treat every transition — rising or falling — of i_ZSS_Pulse as a rearm event. The timer is started on every edge; if no new edge arrives within TV, the output drops.
FC10 — ZSS_SingleTimer (declarations):
FUNCTION FC 10 : VOID
VAR_INPUT
i_Pulse : BOOL; // Proximity input
i_TV_ms : INT; // Timeout in milliseconds (e.g. 20000)
END_VAR
VAR_OUTPUT
q_Running : BOOL; // TRUE = shaft turning
END_VAR
VAR
s_Prev : BOOL; // Static: previous input state
s_TON : TON; // IEC on-delay instance
END_VAR
BEGIN
// Edge detection: positive or negative transition
IF (i_Pulse XOR s_Prev) THEN
s_TON(IN := TRUE, PT := INT_TO_TIME(i_TV_ms));
END_IF;
s_Prev := i_Pulse;
// When timer expires, no new edge arrived
IF s_TON.Q THEN
q_Running := TRUE;
s_TON(IN := FALSE, PT := T#0ms); // reset for next start
ELSE
q_Running := FALSE;
END_IF;
END_FUNCTION
ST alternative (called from OB1):
CALL FC 10
i_Pulse := I0.0
i_TV_ms := 20000
q_Running := Q4.0
Behaviour trace:
| Time | Input | Edge detected? | Timer state | q_Running |
|---|---|---|---|---|
| 0.0 s | FALSE | Initial | Idle | FALSE |
| 1.0 s | TRUE | Yes (rising) | Run (PT = 20 s) | TRUE |
| 1.5 s | FALSE | Yes (falling) | Restart (PT = 20 s) | TRUE |
| 5.0 s | TRUE | Yes (rising) | Restart (PT = 20 s) | TRUE |
| 22.0 s | TRUE (last pulse) | Yes | Run | TRUE |
| 42.0 s | TRUE (stuck) | No (no edge) | Expired | FALSE |
IF s_TON.Q). Because the timer is started every edge, it never reaches Q in steady-state motion. Q only becomes TRUE during the off-time between pulses — the correct inversion. Make sure the assignment is to q_Running as the negative of Q, or restructure the function so Q TRUE means timed out and is then negated.Method 3: SFC4 / SFC5 System Function Blocks
For projects that already use IEC timers everywhere, calling SFC4 (TON) and SFC5 (TOF) keeps the ZSS consistent with the rest of the program. Each SFC call needs an instance DB.
Data block DB20 (ZSS_Timers):
DATA_BLOCK DB20
STRUCT
TON_inst : SFB4; // SFC4 mapped to instance
TOF_inst : SFB5; // SFC5 mapped to instance
END_STRUCT
END_DATA_BLOCK
OB1 network 12 — ZSS using SFC4 / SFC5:
CALL SFC4 // IEC on-delay
IN := I0.0
PT := T#20S
Q := M50.0
ET := MW52
CALL SFC5 // IEC off-delay
IN := I0.0
PT := T#20S
Q := M50.1
ET := MW54
O M50.0
O M50.1
= Q4.0 // ZSS_OK output
The SFC parameters IN, PT, Q, and ET are mandatory. ET returns the elapsed time as a TIME value, which is useful for HMI diagnostics showing the live timeout countdown.
Refer to the STEP 7 Standard Library System Function Blocks manual for the complete signature, error codes (BIE, BR), and timing diagram.
Pulse-Width and Frequency Sizing
Choosing the right timer preset requires understanding the actual pulse frequency at the slowest expected operating speed. The table below lists common application ranges.
| Application | Min RPM | Typical RPM | PPR | Min frequency | Recommended ZSS_TV |
|---|---|---|---|---|---|
| Belt conveyor (drive pulley) | 10 | 90 | 1 | 0.17 Hz | 15 s |
| Screw conveyor | 5 | 30 | 1 | 0.08 Hz | 30 s |
| Rotary valve | 3 | 15 | 6 | 0.30 Hz | 10 s |
| Bucket elevator (head pulley) | 20 | 80 | 1 | 0.33 Hz | 10 s |
| Crusher (eccentric shaft) | 100 | 300 | 1 | 1.67 Hz | 3 s |
| Centrifuge | 200 | 1500 | 1 | 3.33 Hz | 2 s |
| Mixer (low-speed agitator) | 2 | 20 | 1 | 0.03 Hz | 60 s |
Formula: Maximum allowed gap between pulses for a 50% duty cycle disc:
T_gap_max (s) = 60 / (RPM_min × PPR)
Set ZSS_TV ≥ 1.5 × T_gap_max to ride out mechanical jitter, belt slip, and load-induced speed sag without false zero-speed trips.
Complete Working Ladder Example
The network below is a drop-in FC15 that engineers can paste into any S7-300/400 project. It includes a power-up reset, a runtime indicator, and a fault bit for the HMI.
FUNCTION FC 15 : VOID
TITLE = 'Zero Speed Switch Logic'
VAR_INPUT
i_Pulse : BOOL; // Proximity input (SM 321)
i_Enable : BOOL; // Master enable from sequencer
i_TV_s : INT; // Timer preset in seconds
END_VAR
VAR_OUTPUT
q_Running : BOOL; // ZSS_OK to interlock
q_Fault : BOOL; // ZSS timeout (HMI alarm)
q_PulseLED : BOOL; // Diagnostic LED on HMI
END_VAR
VAR_TEMP
s_Prev : BOOL; // Previous input state
s_TON : TON; // On-delay for OR-merge
s_TOF : TOF; // Off-delay for OR-merge
s_PulseCount : INT; // Edge counter (1 s window)
s_Second : BOOL; // 1 Hz blink from CPU clock bit
END_VAR
BEGIN
// 1 Hz blink generator from OB1 cycle (use CPU clock memory, e.g. M100.5)
s_Second := M100.5;
// Pulse indicator for HMI / panel
q_PulseLED := i_Pulse;
// On-delay timer: any TRUE level > TV confirms motion (catches stuck-OFF)
s_TON(IN := i_Pulse, PT := INT_TO_TIME(i_TV_s * 1000));
// Off-delay timer: hold Q for TV after last edge (catches stuck-ON)
s_TOF(IN := i_Pulse, PT := INT_TO_TIME(i_TV_s * 1000));
// OR-merge the two timer outputs
q_Running := (s_TON.Q OR s_TOF.Q) AND i_Enable;
// Latched fault: rising edge of NOT-Running during operation
q_Fault := (NOT q_Running) AND i_Enable AND (s_Second);
END_FUNCTION
Wire it from OB1:
CALL FC 15
i_Pulse := I0.0
i_Enable := I0.7 // Conveyor run request
i_TV_s := 20
q_Running := Q4.0
q_Fault := M51.0
q_PulseLED := Q4.1
STL Equivalent for S7-300/400
For engineers who still maintain legacy STL code, the same logic expressed in Statement List is below.
NETWORK 1 // On-delay arm
A I0.0 // i_ZSS_Pulse
L S5T#20S // 20 second time base
SD T0 // Start on-delay timer 0
A T0
S M50.0 // Latch running flag, part A
NETWORK 2 // Off-delay hold
A I0.0
L S5T#20S
SF T1 // Start off-delay timer 1
A T1
O M50.0 // OR with on-delay result
S M50.0 // Self-hold running flag
NETWORK 3 // Reset running flag when both timers off
AN T0
AN T1
R M50.0
NETWORK 4 // Output
A M50.0
= Q4.0 // q_ZSS_OK
NETWORK 5 // Fault bit to HMI
AN M50.0
A I0.7 // Run request present
S M51.0 // Latched ZSS fault
Verification and Commissioning Procedure
- Wire the proximity sensor and verify input LED on the SM 321 illuminates when a metal target is within range. Use Monitor/Modify in SIMATIC Manager (Online > Monitor/Modify) to confirm
I 0.0toggles when the target is swept past. - Force the input to TRUE for 30 s with the shaft stationary.
q_ZSS_OKmust stay FALSE (the on-delay never expires, the off-delay holds briefly, then drops). - Force the input to FALSE for 30 s with the shaft stationary.
q_ZSS_OKmust stay FALSE (no edges, both timers idle). - Hand-spin the shaft at ≥ 30 RPM.
q_ZSS_OKmust transition to TRUE within one pulse cycle. - Stop the shaft by removing the run command. After
ZSS_TVelapses,q_ZSS_OKmust fall to FALSE. - Test the stuck-ON failure mode: with the motor running, disconnect the proximity cable. If the sensor type latches its last state, the ZSS must trip within
ZSS_TV— this is the critical safety check. - Test the stuck-OFF failure mode: short the input to 24 V at the terminal block. The ZSS must trip in the same way.
- Capture a VAT trace (Variable Table) over 60 s and verify the pulse train count matches the expected PPR × RPM.
Common Faults and Diagnostics
| Symptom | Likely Root Cause | Diagnostic Step | Fix |
|---|---|---|---|
| ZSS drops out during slow-speed run | TV shorter than pulse gap | Recalculate from min RPM / PPR; check VAT pulse gap | Increase TV to 1.5× calculated gap |
| ZSS never picks up on first start | On-delay TV too long for startup ramp | Watch T0 in VAT; confirm rising edge arrives within TV | Shorten TV or use a separate startup timer |
| ZSS chatters (TRUE/FALSE every few seconds) | Target disc loose, sensor distance wrong, vibration | Mechanical inspection; check SCAN/PSF with VAT | Re-shim sensor, replace target, add hysteresis |
| ZSS OK while shaft is clearly stopped | Stuck-ON sensor; off-delay only, no on-delay | Watch raw input only; check wiring | Implement BOTH S_ODT and S_OFFDT in OR (Method 1) |
| SFU 0170 (timer overflow) in CPU diagnostic buffer | TV exceeds 2 h 46 m 30 s; S5TIME limit | Check TV literal type | Use S5T#9H900M_900MS or split into cascaded timers |
| Output Q4.0 stays TRUE on CPU restart | M50.0 retentive, no power-up reset | Inspect VAT on cold restart | Add OB100 / OB101 reset network for running flag |
Edge Cases and Field-Proven Caveats
- Mechanical slip: On V-belt drives, a slipped belt can stop the driven shaft while the motor continues. The proximity on the driven shaft (not the motor) is mandatory. Mounting the sensor on the motor pulley defeats the purpose.
- Reverse rotation: A proximity on a single tooth does not distinguish forward from reverse. If direction matters, use a quadrature target (two sensors at 90°) and feed the ZSS from an edge detector on either channel.
-
Vibration-induced false pulses: Heavy vibrating equipment can cause the sensor to re-trigger on a stationary target. Add a minimum pulse width filter of ≥ 5 ms using
OB35(interrupt OB) or a hardware debounce input module. - Wire break vs. logic zero: A broken cable presents as open-circuit, which is FALSE for a PNP sensor — identical to a stopped shaft at a gap position. The on-delay will hold q_Running FALSE for the long-term case, so the logic still flags zero speed correctly, but the operator cannot tell whether the cause is real stop or a wire break. Consider adding a 1 Hz square-wave diagnostic pulse on the cable and watching for it at the input.
- CPU STOP during operation: If the CPU goes to STOP while the conveyor is mechanically running, all outputs drop. After a STOP-to-RUN transition, q_ZSS_OK must rebuild from real pulses — never from a latched flag. Avoid the latched running flag in the STL example above unless you also add a startup inhibit.
- Retentive behaviour on warm restart: M50.0 default scope is non-retentive. To force a clean reset, add the following in OB100 (warm restart) and OB101 (hot restart):
NETWORK 1
CLR
= M50.0 // ZSS running flag
= M51.0 // ZSS fault flag
= T0 // Reset timer accumulator
= T1
Migration to TIA Portal
All three methods port directly to TIA Portal V15+. The differences are:
- Timer blocks are in the Instructions task card under Timer operations.
- IEC timers (TON, TOF) are now first-class FBs in the standard library and can be declared as multi-instance inside a parent FB without separate DBs.
- Hardware timers no longer exist in the S7-1200/1500 families — the S7-300/400 remains the only supported platform for
SD/SFinstructions. - Diagnose the timer state from the Watch table with online monitoring; the same VAT format applies.
For new projects on S7-1500, prefer the single-timer edge-triggered method (Method 2) with multi-instance TON inside an FB; it is the most portable and easiest to reuse.
FAQ
Which timer should I use in Simatic Manager for a zero speed switch — hardware (S_ODT) or IEC (SFC4)?
For S7-300/400, use hardware timers S_ODT and S_OFFDT when you want minimal memory use (2 bytes per timer in T memory, no instance DB) and direct bit addressing. Use SFC4 / SFC5 (IEC TON / TOF) when you need the elapsed-time value for HMI display, or when the program is otherwise already IEC-timer based. Both are functionally equivalent for ZSS duty.
How do I size the on-delay and off-delay TV value for a 1 PPR proximity at low speed?
Calculate the maximum gap between pulses: T_gap = 60 / (RPM_min × PPR). For a 3 RPM, 1 PPR disc that is 20 s. Set both TV to 1.5 × 20 s = 30 s. This rides out belt slip, mechanical jitter, and load-induced sag without false zero-speed trips.
Can a single proximity failure (stuck-ON or stuck-OFF) be detected reliably?
Yes, but only if the logic contains both an on-delay and an off-delay OR-merged, as in Method 1 of this article. A stuck-OFF sensor is caught by the on-delay: the input never goes TRUE long enough to assert. A stuck-ON sensor is caught by the off-delay: after the last real falling edge, the timer expires. Using only one timer leaves one failure mode undetected.
Why does my ZSS output stay TRUE after a CPU STOP/RUN transition even though the shaft is stopped?
Because the running flag (for example M50.0) is latched and never reset on restart. Add a reset network in OB100 / OB101 that clears the flag and resets the timer accumulators on every warm or hot restart. Never rely on a latched ZSS_OK bit across a CPU restart.
What is the fastest way to verify a ZSS in the field without spinning the motor?
Use the Monitor/Modify function in SIMATIC Manager to force I 0.0 TRUE and FALSE manually and watch the timer bits in a VAT. The on-delay T0 should never reach Q under forced-TRUE-only, the off-delay T1 should never reach Q under forced-FALSE-only, and q_ZSS_OK should stay FALSE for both. Then force a 1 Hz square wave (toggle every 500 ms) to simulate motion; q_ZSS_OK must transition TRUE within two TV cycles.