1. Problem Definition
A S7-1214C receives a pulse train from a process flow meter and must derive an engineering-units flow rate (L/h) for display and downstream control. The relevant signal chain is:
- Pulse source: Paddle-wheel / turbine flow meter, sinking or sourcing output, 24 V DC.
- Meter constant: K = 1000 pulses per liter (nominal).
- Maximum specified flow: Qmax = 80 L/h.
- Observed pulse rate: f = 25 Hz (period 40 ms) at the operating point.
The expected pulse frequency at the rated flow is
frated = Qmax · K = 80 L/h · 1000 pulses/L = 80 000 pulses/h = 22.22 Hz
A measured 25 Hz therefore sits roughly 12.5 % above the meter's nominal Qmax. Treat the first task on the bench as verifying that the meter is not being over-driven and that the K-factor is constant over the flow range; a paddle-wheel meter in turbulent flow can drift several percent and produce this kind of mismatch.
2. Prerequisites
2.1 Hardware
- SIMATIC S7-1214C DC/DC/DC (firmware V4.2 or later recommended for full HSC functionality; V4.5+ if you intend to use the symbolic HSC IDB fields directly).
- 24 V DC pulse output flow meter, K = 1000 pulses/L.
- Wiring: meter output → DI of the CPU; for sourcing outputs use a 24 V input; for sinking outputs add a pull-up or use an interposing relay or signal conditioner.
2.2 Software
- STEP 7 Basic / Professional in TIA Portal (V15.1 or later; V17/V18 recommended for the latest HSC application example).
- S7-1200 System Manual, edition 09/2022 or later.
2.3 Official references
- SIMATIC S7-1200 Programmable Controller System Manual (109766074)
- S7-1200: Application Examples for High-Speed Counters (109751224)
- S7-1200 Motion Control - HSC overview (109751049)
3. HSC Architecture on the CPU 1214C
The CPU 1214C exposes six independent HSC channels (HSC1-HSC6) implemented in hardware, independent of the OB1 scan. Each HSC can be configured for one of three counting modes:
| Mode | Phases | Max input frequency (CPU 1214C DC/DC/DC) | Typical use |
|---|---|---|---|
| Single-phase, internal direction control | 1 | 100 kHz | Pulse counting, simple flow |
| Two-phase (quadrature X1) | 2 | 100 kHz | Encoder position |
| Two-phase (quadrature X2/X4) | 2 | 100 kHz | Encoder with 2x/4x resolution |
| A/B counter, Z reset | 3 | 100 kHz | Encoder with index |
Default input pin assignment on the CPU 1214C (DC/DC/DC) for an unused channel is reassignable in the device configuration. The factory defaults that matter for this application are:
| HSC | Default Clock (A) | Default Direction (B) | Default Reset (Z) |
|---|---|---|---|
| HSC1 | I0.0 | I0.1 | I0.3 |
| HSC2 | I0.4 | I0.5 | I0.7 |
| HSC3 | I1.0 | I1.1 | I1.2 |
4. Engineering Units: From Pulses to Liters per Hour
Two equivalent conversions are useful. Define a sampling window W (in seconds). The number of pulses accumulated in the window is ΔN. The instantaneous volume throughput is then
V_dot [L/s] = ΔN / (K · W)
and the displayed engineering value is
Q [L/h] = V_dot · 3600 = (ΔN · 3600) / (K · W)
For K = 1000 pulses/L and W = 1 s, this simplifies to
Q [L/h] = 3.6 · ΔN [pulses in 1 s]
At the rated 22.22 Hz (Q = 80 L/h), ΔN = 22 pulses per second; at the observed 25 Hz, ΔN = 25 pulses per second, giving 90 L/h. Either the meter constant is slightly off, or the meter is being run above its specified Qmax - in either case, the FB below exposes the raw pulse count and the scaled L/h value so the mismatch is visible at commissioning.
| Flow Q [L/h] | Pulses/sec ΔN | Period T [ms] | HSC count after 1 s |
|---|---|---|---|
| 0 | 0 | ∞ | 0 |
| 10 | 2.78 | 360.0 | 3 |
| 40 | 11.11 | 90.0 | 11 |
| 80 (rated) | 22.22 | 45.0 | 22 |
| 90 (observed 25 Hz) | 25.00 | 40.0 | 25 |
4.1 Window length trade-off
- W = 100 ms: responsive but quantised - at 80 L/h only 2.2 pulses accumulate, so the displayed value jitters between 72 and 108 L/h (jumps of 36 L/h).
- W = 1 s: 22 pulses at 80 L/h, LSB ≈ 3.6 L/h, jitter 0 to 7.2 L/h - acceptable for display.
- W = 10 s: 222 pulses, LSB ≈ 0.36 L/h - excellent stability but 10 s display lag.
Pick W = 1 s for HMI display. If the value is also used in a closed-loop control loop, run a second faster loop at 100 ms with a low-pass filter.
5. TIA Portal Device Configuration
- Open the project and the CPU 1214C device view.
- Select Properties → Digital inputs and assign HSC1 to the physical input that the meter is wired to (e.g. I0.0). Set the input filter for that channel to 0.1 ms.
- Select Properties → High-Speed Counters (HSC). Enable HSC1, choose Count mode, single-phase, internal direction control (count up).
- Set initial count value, initial reference, and any preset / upper limits you need. For this application, no preset is required; just count up.
- Compile and download the hardware configuration.
After download, the HSC exposes an Instance DB (IDB) of type HSC_Count (or CTRL_HSC_EXT in older projects). The fields you will read from the SCL FB are:
-
IDB_HSC1.CurrentCount- DInt, live count value. -
IDB_HSC1.NewDirection- Bool, direction status.
6. SCL Implementation: FlowRate FB
Create a function block FB_FlowRatePulses in a new SCL source. The FB latches the HSC count on every cycle of a 1 s timer, computes the delta, and scales to L/h.
FUNCTION_BLOCK "FB_FlowRatePulses"
TITLE = 'Pulse-train flow rate'
VAR_INPUT
iRawCount : DInt; // IDB_HSC1.CurrentCount snapshot
iPulsePerL : Real := 1000.0; // K [pulses/L]
iWindow_s : Real := 1.0; // sampling window W [s]
iEnable : Bool;
END_VAR
VAR_OUTPUT
oFlow_Lph : Real; // engineering-units flow rate [L/h]
oDeltaN : DInt; // pulses accumulated in last window
oAlarmHi : Bool; // 1 = above configured high limit
oAlarmLo : Bool; // 1 = below configured low limit
END_VAR
VAR
sCountPrev : DInt; // last latched count
sFirstRun : Bool := TRUE;
sIEC_Timer : IEC_TIMER; // TP or TON, 1 s pulse
sWindow_Trig: Bool;
END_VAR
VAR CONSTANT
cHighLimit_Lph : Real := 80.0;
cLowLimit_Lph : Real := 0.0;
END_VAR
BEGIN
// Edge-triggered 1 s window
sIEC_Timer(IN := iEnable, PT := T#1s);
sWindow_Trig := sIEC_Timer.Q;
IF NOT iEnable THEN
sFirstRun := TRUE;
oFlow_Lph := 0.0;
oDeltaN := 0;
oAlarmHi := FALSE;
oAlarmLo := FALSE;
RETURN;
END_IF;
IF sFirstRun THEN
sCountPrev := iRawCount;
sFirstRun := FALSE;
oFlow_Lph := 0.0;
oDeltaN := 0;
END_IF;
IF sWindow_Trig THEN
// signed delta; flow meter is single-direction here
oDeltaN := iRawCount - sCountPrev;
sCountPrev := iRawCount;
// guard divide-by-zero
IF iWindow_s > 0.0 AND iPulsePerL > 0.0 THEN
oFlow_Lph := (DINT_TO_REAL(oDeltaN) * 3600.0)
/ (iPulsePerL * iWindow_s);
ELSE
oFlow_Lph := 0.0;
END_IF;
oAlarmHi := oFlow_Lph > cHighLimit_Lph;
oAlarmLo := oFlow_Lph < cLowLimit_Lph;
END_IF;
END_FUNCTION_BLOCK
Call the FB from OB1, supplying the HSC's CurrentCount snapshot. A clean snapshot is simply reading "HSC_1".CurrentCount into a local DInt; the HSC hardware register is updated in the background by the high-speed counter logic, so there is no race condition with OB1.
// OB1 - calling the FB
"Inst_FlowRate"(
iRawCount := "HSC_1".CurrentCount,
iPulsePerL := 1000.0,
iWindow_s := 1.0,
iEnable := TRUE
);
// Push the engineering value to the HMI tag
"HMI_Flow_Lph" := "Inst_FlowRate".oFlow_Lph;
"HMI_AlarmHi" := "Inst_FlowRate".oAlarmHi;
7. LAD/FBD Alternative (Pure Ladder)
If the project prohibits SCL (some legacy code bases), the same flow can be built in LAD/FBD without any HSC. The trade-off is that the count is taken on the OB1 scan edge rather than in hardware, so you must verify that no pulses are lost between scans. With a 6 ms OB1 and a 40 ms pulse period the worst case is one lost pulse in 7, which is tolerable for display.
- Wire the meter output to a standard DI (e.g. I0.0). Configure the input filter to 0.1 ms.
- Use a standard up-counter CTU with PV set above the maximum expected count over the window (e.g. 200 for 1 s at 25 Hz).
- Add a 1 s on-delay timer (TON) whose output resets the counter via the CTU R input.
- Capture the counter value on the timer's falling edge into a static word using a MOVE block triggered by the timer's Q output.
- Apply the scaling Q = 3.6 · ΔN as a math block or a CALCULATE instruction.
The math step uses the CALCULATE instruction in TIA Portal with the expression
OUT = (IN1 * 3.6) / 1000.0 // IN1 = delta pulses in 1 s
For a 500 ms window replace 3.6 with 7.2; for 100 ms use 36. The trade-off is a noisier display at small W, since the integer delta quantises to 1 pulse.
8. Sampling Window and Filtering
For HMI display, a single-pole exponential filter on top of the 1 s sample is usually enough to calm the visual jitter:
Qfilt(t) = α · Qraw(t) + (1 - α) · Qfilt(t - 1)
with α in [0, 1]. A 1 s sample window with α = 0.4 gives a display time constant of about 1.5 s, which is comfortable for operators. If the output is used as a PV in a PID loop, drop the filter and use the raw 1 s value; the loop's integral action provides the smoothing.
| Use case | Recommended W | Filter α | Notes |
|---|---|---|---|
| HMI display only | 1 s | 0.3 - 0.5 | Smooth visual response |
| Alarm threshold only | 1 s | 1.0 (no filter) | Detect overruns quickly |
| PID PV (slow loop, > 10 s Tc) | 1 s | 1.0 | Let loop integrate |
| PID PV (fast loop, < 5 s Tc) | 100 ms | 0.7 | Higher noise bandwidth |
| Custody transfer / billing | Totaliser | n/a | Use pulse count, never an averaged rate |
9. Edge Cases, Overflow, and Alarms
9.1 Negative delta from HSC wraparound
The HSC on the S7-1200 has a 32-bit count, so at 25 Hz it would take more than 4.8 years to roll over. If you ever change to a faster meter or remove the rollover, the difference oDeltaN must be treated as DInt, not as a Word, so the sign is correct.
9.2 Direction change
If the meter can read bi-directional flow, switch the HSC to two-phase mode and use the direction bit to gate the calculation. The SCL FB above assumes single-direction; for bi-directional, scale a positive delta by +1 and a negative delta by -1, or run two accumulators keyed off IDB_HSC1.NewDirection.
9.3 Stalled flow / wire break
A broken wire presents as zero pulses. Add a stall alarm: a TON with PT = 30 s that triggers when the HSC has not changed for 30 s, while the enable is true. This is often more useful than a low-flow alarm because it distinguishes "valve closed, no flow" from "flow at zero".
9.4 High-flow alarm
Set cHighLimit_Lph = 80 L/h. At 25 Hz the calculated 90 L/h will fire this alarm, which is the desired behaviour - it tells the operator the meter is over-driven and the K-factor should be re-verified or a smaller meter installed.
9.5 Totaliser
For totalised volume, do not average - add the unscaled count and divide by K once per minute. Store the total in a retentive LReal tag (e.g. Tot_L) and reset only on a manual command or a daily schedule.
10. Commissioning and Verification
- Disconnect the process and feed a calibration pulse generator into the meter input. Set the generator to 22.22 Hz (1 pulse every 45 ms) and verify that the displayed Q reads 80.0 L/h ± 1 L/h within 2 s.
- Repeat at 11.11 Hz (50 %) and 5.56 Hz (25 %) to confirm linearity.
- Set the generator to 0 Hz and check that the stall alarm fires after 30 s.
- Restore the process. Compare the integrated volume over 10 min against a manual draw into a calibration vessel. Aim for ± 1 %.
- Watch the HSC IDB online -
CurrentCountshould advance monotonically.
10.1 Online watch table
Add the following tags to a watch table during commissioning:
"HSC_1".CurrentCount // raw hardware count
"Inst_FlowRate".oDeltaN // pulses in last window
"Inst_FlowRate".oFlow_Lph // scaled flow rate
"Inst_FlowRate".oAlarmHi // high alarm
"Inst_FlowRate".oAlarmLo // low alarm
11. Troubleshooting Matrix
| Symptom | Likely cause | Diagnostic | Action |
|---|---|---|---|
| Display reads 0 even with flow | DI filter too long; HSC not enabled; wrong input assigned | Force HSC IDB and watch CurrentCount online |
Set input filter to 0.1 ms, enable HSC1 in device config, reassign input to the wired terminal |
| Display reads exactly half the expected value | K-factor set to 2000 instead of 1000 | Inspect iPulsePerL input |
Correct K to 1000 |
| Display jitters wildly | W too short, or meter pulses are noisy (bouncing contacts) | Capture oDeltaN over 10 s; check the rising edge on a scope |
Increase W to 1 s, fit a hardware low-pass on the input, or use a debounce filter in the FC |
| Display drifts high with no flow | Noise counts on a floating input | Disconnect meter; observe CurrentCount
|
Add 2.2 kΩ pull-down to 0 V at the input; enable the input filter at 0.4 ms |
| High alarm always on at rated flow | Meter K-factor inaccurate, or Qmax limit too low | Measure pulses/s with a hand-held counter at known flow | Re-calibrate K, or raise cHighLimit_Lph after engineering sign-off |
| HSC counts but display never updates | 1 s timer is not pulsing; OB1 not running | Watch sIEC_Timer.Q in the FB online |
Confirm iEnable is true, OB1 cycle light is on, IEC_Timer is not held by a JOG condition |
Negative oDeltaN at start-up |
sCountPrev initialised to 0 while the HSC has counted in standby |
Set sFirstRun := TRUE on a power-on or on first OB1 scan |
Initialise on first run as shown in the FB; alternatively clear the HSC on cold restart |
12. Variants and Migration
The same flow scales cleanly to other S7-1200 CPUs (CPU 1211C, 1212C, 1215C, 1217C) and to the S7-1500. On the S7-1500 the HSC is replaced by a TM Count or by a high-speed counter on the technology module, and the period measurement is built in. The scaling formula in §4 is identical, so the SCL FB body is portable verbatim. For a 1217C (DC/DC/DC) the HSC ceiling is 1 MHz and the same code is the right starting point; only the device configuration differs.
If the application is being ported from a MicroLogix or a third-party PLC, the only item that changes is the input filter default; the SCL math and the windowed scaling are the same.
Do I really need an HSC for 25 Hz on a CPU 1214C?
For pure display, no - 25 Hz is well below the digital input sampling limit of a 1214C and a standard CTU counter will work. Use the HSC when you need guaranteed lossless counting, when the loop time is unknown, or when the application may grow to higher meter rates. HSC also gives you a hardware-level snapshot that survives OB1 scan-time variation.
What is the maximum HSC input frequency on a 1214C DC/DC/DC?
100 kHz in single-phase or two-phase quadrature mode (X1, X2, X4), with the input filter set to 0.1 ms. The 1214C AC/DC/RLY is much lower (about 30 Hz) because its inputs are optocoupled with a longer filter; always check the manual for the exact model you are using.
Why does my display read 90 L/h when the meter is rated for 80 L/h?
Two likely causes. Either the meter is actually flowing above its rated Qmax (verify with a clamp-on flow reference), or the K-factor in software is wrong (check whether the meter nameplate reads 1000 pulses/L or, for example, 900 pulses/L). Recalibrate K from a measured draw if needed.
How do I totalise volume in addition to the instantaneous rate?
Read HSC_1.CurrentCount once per minute, subtract a latched previous value, and add the delta divided by 1000 to a retentive LReal tag. Do not derive total volume from the averaged rate - the integration error is unacceptable for billing.
Why does the display freeze at 0 when I turn the meter on?
The HSC needs the input filter configured for the high-speed pin. Check Device configuration → Digital inputs → Channel 0 (I0.0) → Input filter = 0.1 ms. The default 6.4 ms filter will silently drop every 25 Hz pulse. Confirm by forcing the HSC online and watching CurrentCount; if it never increments, the filter is the problem.