Exporting CTRL_HSC_EXT SCL Code from TIA Portal V14 to V13 with RPM Calculation
Engineers maintaining S7-1200/S7-1500 fleets that span multiple TIA Portal versions routinely hit a binary compatibility wall: a project saved in V14 cannot be opened in V13 SP1. When the offending block is a single FB in SCL that wraps the high-speed counter instruction CTRL_HSC_EXT, the cleanest path is to export the source text, recompile it in the older environment, and fix the small set of implicit-conversion issues that the older compiler reports. This reference walks through that procedure, then deepens it with the period-measurement math required to derive RPM from a quadrature or pulse encoder.
numPulsePerRot calculation, is the basis for the code shown below.1. What CTRL_HSC_EXT Does
CTRL_HSC_EXT is the SCL/ST/FBD wrapper around the S7-1200/S7-1500 high-speed counter (HSC) technology object. It complements CTRL_HSC by exposing the extended parameter set of the Period measurement and Edge-to-edge measurement operating modes introduced with the S7-1500 and back-ported to S7-1200 firmware V4.x and later.
| Parameter | Direction | Data type | Purpose |
|---|---|---|---|
HSC |
IN | HW_HSC | Hardware identifier of the HSC technology object (assigned in Device Configuration) |
DIR |
IN | BOOL | Count direction (TRUE = reverse) |
CV |
IN | BOOL | Enable new counter value via NEW_CV
|
RV |
IN | BOOL | Enable reference value via NEW_RV
|
PERIOD |
IN | BOOL | Enable period measurement (period / edge-to-edge) |
NEW_PERIOD |
IN/OUT | DINT | New measurement window / period mode selector |
ELAPSED_TIME |
OUT | DINT | Accumulated time of the last measurement window in nanoseconds |
EDGE_COUNT |
OUT | DINT | Number of edges captured during the window |
STATUS |
OUT | WORD | Function result / error code |
The combination of ELAPSED_TIME and EDGE_COUNT is what enables period-based speed measurement. The HSC hardware latches the elapsed time between a configurable number of edges and reports both values through the function block interface, letting the SCL code calculate RPM in software rather than counting pulses over a PLC cycle.
2. The V14-to-V13 Compatibility Problem
TIA Portal project files are forward-only: a V13 SP1/SP2 project opens in V14, but a V14 project refuses to open in V13. The compiler error is typically "The project was created with a newer version of TIA Portal and cannot be opened." The reverse workflow — exporting a single block as plain SCL source — is supported, and that is what we exploit here.
| TIA Portal version | Can open V13 project? | Can open V14 project? | Compiles CTRL_HSC_EXT? |
|---|---|---|---|
| V13 SP1 / SP2 | Yes | No | Yes (HSC ≥ V4.0) |
| V14 | Yes | Yes | Yes |
| V14 SP1 | Yes | Yes | Yes |
| V15 / V15.1 / V16 / V17 / V18 | Yes (backward read) | Yes (backward read) | Yes (firmware dependent) |
Because the CTRL_HSC_EXT instruction itself exists in both V13 SP1 (with S7-1200 CPU firmware ≥ V4.0) and V14, the only thing that prevents reuse is the project file format, not the language element.
3. Prerequisites
-
Source project in TIA Portal V14 (or later) containing the example
CTRL_HSC_EXTFB. - Target environment: TIA Portal V13 SP1 (Update 4 minimum) or V13 SP2 with an S7-1200 CPU that supports the HSC technology object (CPU 1211C/1212C/1214C/1215C/1217C, firmware V4.0 or newer) or any S7-1500 CPU.
- HSC technology object configured in Device Configuration: Counting mode = Period measurement or Edge-to-edge measurement; Input = onboard HSC input (e.g., I0.0 / I0.1 for HSC1 on CPU 1214C).
- Encoder wired to the HSC input with the correct Encoder type (A/B quadrature, A/B quadrature four-fold, or single-channel pulse) selected in the technology object.
- OB1 (or cyclic OB) with the SCL FB called every cycle, plus the instance DB for the FB.
4. Step-by-Step: Export the SCL Block from V14
- In the V14 project tree, expand Program blocks and select the
FBthat contains theCTRL_HSC_EXTcall (default name in the Siemens example:CTRL_HSC_EXT_RPM). - Right-click the block and choose Export block > Export block to external file… (or, for the source text only, Source files > Generate source from blocks).
- Save the resulting
.scl(or.dbfor instance DBs) text file to a folder accessible from the V13 environment. - Optionally right-click the Technology objects > HSC_1 entry and choose Export if you also need to share the technology object configuration; a plain SCL export does not include the technology object.
5. Step-by-Step: Import the SCL Block into V13
- Open the target project in TIA Portal V13 SP1/SP2.
- Right-click the CPU under Program blocks and choose Add new block > Function block with language SCL. Give it the same name and number as the source FB.
- Open the new (empty) FB, click in the code editor, then drag-and-drop the exported
.sclfile into the editor — or use External source files > Add new external file and compile. - Recreate the In, Out, InOut, Static, and Temp interface sections to match the source. The V13 compiler will not infer them from pasted code.
- Place an instance DB for the FB (right-click > Add new block > Data block > Instance DB > select the FB).
- Call the FB from OB1 and download hardware + software to the CPU.
6. The Reference SCL Block
The Siemens example exports a single SCL FB named CTRL_HSC_EXT_RPM. The interface and the relevant calculation logic are reproduced below. Comments mark the lines that must be edited when porting from V14 to V13.
6.1 Block Interface
FUNCTION_BLOCK "CTRL_HSC_EXT_RPM"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
startHSC : BOOL; // TRUE = arm period measurement
numPulsePerRot : REAL; // encoder pulses per mechanical revolution
tCycle : REAL; // optional measurement window [s]; 0.0 = HSC default
END_VAR
VAR_OUTPUT
actualRPM : REAL; // rotational speed [1/min]
actualPeriod_s : REAL; // last measured period [s]
statStatus : WORD; // HSC status word
statError : BOOL; // TRUE on STATUS <> 0
END_VAR
VAR
statHscId : HW_HSC; // assigned in HW configuration, e.g. %I0.0
statEnablePeriod : BOOL;
statNewPeriod : DINT;
statElapsedTime : DINT; // [ns]
statEdgeCount : DINT;
statPeriod : REAL;
statRPM : REAL;
END_VAR
CONST
BILLION : REAL := 1.0e9;
END_CONST
BEGIN
// --- 1. Drive the HSC extended control ----------------------------
#statEnablePeriod := #startHSC;
#statNewPeriod := REAL_TO_DINT(#tCycle * 1.0E9); // window [ns]
"CTRL_HSC_EXT_DB".CTRL_HSC_EXT_Instance( // (use the IEC instance syntax if optimized)
HSC := #statHscId,
PERIOD := #statEnablePeriod,
NEW_PERIOD := #statNewPeriod,
ELAPSED_TIME := #statElapsedTime,
EDGE_COUNT := #statEdgeCount,
STATUS := #statStatus );
// --- 2. Convert elapsed ns to seconds and divide by edges ---------
IF #statEdgeCount > 0 THEN
// Port-fix: explicit DINT_TO_REAL for V13 compilation.
#statPeriod := DINT_TO_REAL(#statElapsedTime)
/ DINT_TO_REAL(#statEdgeCount)
/ #BILLION; // [s / edge]
// --- 3. Apply pulses-per-revolution to get period [s/rev] ------
IF #numPulsePerRot > 0.0 THEN
#statPeriod := #statPeriod * #numPulsePerRot;
// --- 4. Convert period [s/rev] to RPM [1/min] --------------
IF #statPeriod > 0.0 THEN
#statRPM := 60.0 / #statPeriod;
ELSE
#statRPM := 0.0;
END_IF;
ELSE
#statRPM := 0.0;
END_IF;
ELSE
#statRPM := 0.0;
END_IF;
#actualRPM := #statRPM;
#actualPeriod_s := #statPeriod;
#statError := (#statStatus <> 16#0000);
END_FUNCTION_BLOCK
6.2 What numPulsePerRot Means
numPulsePerRot is the rated pulse count of the encoder per mechanical revolution, not the number of edges the HSC hardware sees. The relationship between encoder PPR and HSC edges is set by the technology object's Counting mode and Signal evaluation:
| Encoder signal | Signal evaluation | Edges per revolution seen by HSC | numPulsePerRot to use |
|---|---|---|---|
| Single-channel pulse | 1× | 1 × PPR | Encoder PPR |
| A/B quadrature | 1× | 2 × PPR | Encoder PPR × 2 |
| A/B quadrature | 2× (two-fold) | 4 × PPR | Encoder PPR × 4 |
| A/B quadrature | 4× (four-fold) | 4 × PPR | Encoder PPR × 4 |
A common field error is to set numPulsePerRot to the catalog PPR of the encoder (e.g. 1024) while the HSC is in 4× quadrature evaluation, so the HSC actually counts 4096 edges per revolution. The result is an RPM reading that is low by a factor of four. The fix is to feed the FB the effective PPR — i.e. encoder PPR multiplied by the configured edge count — and leave the technology object on its current setting. An alternative, used in the Siemens example, is to feed encoder PPR and compensate inside the FB by the same factor the HSC is using; the example keeps the factor explicit so that reconfiguration of the technology object does not silently change the result.
7. The DINT-to-REAL Conversion Fix
The Siemens example as published in entry 109742346 performs the division #statElapsedTime / #edgeCount directly. In V14, the compiler accepts the implicit promotion of DINT to REAL because #statPeriod is REAL. In V13 SP1, the same line fails to compile with:
Line 26: Cannot implicitly convert type 'DINT' to 'REAL'.
Two equivalent fixes are valid:
7.1 Option A — Wrap with explicit conversions
#statPeriod := DINT_TO_REAL(#statElapsedTime)
/ DINT_TO_REAL(#statEdgeCount)
/ 1.0E9;
This is the safest port-fix because it does not change the data types of the interface and works on both V13 and V14. DINT_TO_REAL is a standard IEC conversion function available in all TIA Portal versions from V11 onward.
7.2 Option B — Promote the temporaries to REAL
VAR_TEMP
tElapsedReal : REAL;
tEdgeReal : REAL;
END_VAR
tElapsedReal := DINT_TO_REAL(#statElapsedTime);
tEdgeReal := DINT_TO_REAL(#statEdgeCount);
#statPeriod := tElapsedReal / tEdgeReal / 1.0E9;
Use this form when the rest of the block is going to be refactored for clarity anyway. It avoids long expressions that exceed the line-length print margin in V13.
1.0E9 is REAL; 1E9 (no decimal) is interpreted as a time literal and will not compile inside a numeric expression. Always use the decimal form for the BILLION divisor.8. Verification Procedure
- Online compile the V13 project and download hardware and software to the CPU in STOP, then run it.
- Open the instance DB online and watch the
statElapsedTime,statEdgeCount,statPeriod, andstatRPMvalues with a VAT. - Confirm that
statStatusreturns16#0000(no error). The most common non-zero status codes are16#80A0(HSC not configured) and16#80A1(invalidNEW_PERIOD). - Drive the encoder at a known reference speed (a stroboscope or a second tachometer is ideal) and compare the FB's
actualRPMto the reference. Tolerate a few percent, since the HSC's period window quantises the result. - Stop the encoder (0 RPM). Confirm that
actualRPMdrops to 0.0 within one period window, not at a frozen non-zero value. A frozen value usually meansstatEdgeCountstayed at its last value and the new period measurement never started; check thatPERIODis being re-asserted each cycle or that the technology object is set to Continuous measurement. - Reverse the encoder direction. Confirm that
actualRPMgoes negative. The HSC counts up only; direction is signalled by the B-channel phase. If the sign is wrong, swap the A and B encoder wires (do not swap power and ground).
9. Common Faults and Remedies
| Symptom | Likely cause | Remedy |
|---|---|---|
| Compile error "Cannot implicitly convert type 'DINT' to 'REAL'" | V13 stricter type checking | Wrap with DINT_TO_REAL() (Section 7) |
actualRPM stuck at 0 with HSC in RUN |
PERIOD input is one-shot, not held |
Hold #statEnablePeriod := TRUE in the VAR section; re-assign each cycle |
actualRPM low by factor of 2 or 4 |
Mismatch between numPulsePerRot and HSC signal evaluation |
Use effective PPR (encoder PPR × evaluation factor) |
statStatus = 16#80A0 |
HSC technology object not downloaded or wrong HW ID | Recompile hardware; verify statHscId in Device Configuration |
statStatus = 16#80A1 |
NEW_PERIOD out of range |
Check the technology object's Min/Max period values; NEW_PERIOD in nanoseconds must lie inside |
actualRPM noisy at low speeds |
Measurement window too short for the speed | Increase tCycle (the period window) so more edges are integrated |
| Direction sign inverted | A/B encoder wiring reversed | Swap the two signal wires at the encoder side, not the supply |
| No HSC interrupts in V13 SP1 | CPU firmware < V4.0 | Update S7-1200 CPU to firmware V4.0 or later; HSC extended parameters require it |
10. Period Measurement Math in One Screen
The block derives RPM in four algebraic steps. Engineers reading the code in a hurry will want the formulas spelled out:
tElapsed_ns // raw HSC output: time of window
f_s = ------------- // period in seconds PER EDGE
N_edges * 1.0E9
T_rev = f_s * PPR_eff // period per revolution [s]
RPM = 60 / T_rev // revolutions per minute [1/min]
Where PPR_eff = encoder PPR × signal-evaluation factor (1, 2, or 4). A worked example: a 1024-PPR encoder in 4× quadrature (PPR_eff = 4096) turning at 1500 RPM:
- Period per revolution: 60 / 1500 = 0.040 s
- Period per edge: 0.040 / 4096 = 9.766 µs/edge
- Period window needed for 10 edges: 97.66 µs — well within the HSC's sub-microsecond resolution.
At very low speeds (long T_rev) the period window itself becomes the bottleneck; the FB then needs to be re-engineered to use a fixed wall-clock window and count edges, which is the inverse of the algorithm above.
11. Differences from the V14 Original
Aside from the DINT_TO_REAL() wrappers, the ported block is functionally identical to the V14 example. The single material difference is the absence of optimised access on the instance DB in V13 SP1 — the block above uses the default (non-optimised) interface so the instance DB appears in the V13 watch table. If you want optimised access in V13 SP1, mark the FB with { S7_Optimized_Access := 'TRUE' } and accept that the instance DB no longer has symbolic slot addresses.
The V14 example also uses know-how protection in some shipping projects. The Generate source from blocks export strips that protection. The Export block to external file export preserves it. Choose the export mode that matches the project IP policy before sending the file to a V13 site.
12. FAQ
Why will TIA Portal V13 not open a V14 project file?
TIA Portal uses a forward-only project schema. V14 introduced new block types, technology object revisions, and compiler metadata that the V13 schema cannot read. The fix is to export the individual SCL source files (Section 4) and re-import them into a V13 project; the project schema is the only thing that changed, not the SCL language itself.
What does CTRL_HSC_EXT add beyond CTRL_HSC?
CTRL_HSC_EXT extends the high-speed counter with the PERIOD, NEW_PERIOD, ELAPSED_TIME, and EDGE_COUNT parameters. These allow the HSC hardware to perform period or edge-to-edge measurement natively, which is essential for accurate RPM/period calculations on slow-turning shafts where pulse counting over a PLC scan is too coarse.
How do I fix the DINT to REAL conversion error in V13?
Wrap the operands with the IEC conversion function: statPeriod := DINT_TO_REAL(#statElapsedTime) / DINT_TO_REAL(#statEdgeCount) / 1.0E9;. V13 SCL will not promote DINT to REAL implicitly the way V14 does. See Section 7 for the two equivalent fix patterns.
What value should I assign to numPulsePerRot?
Assign the effective pulses-per-revolution seen by the HSC hardware, not the encoder's catalog PPR. Multiply the encoder's rated PPR by the HSC signal-evaluation factor (1, 2, or 4) configured in the technology object. For a 1024-PPR encoder in 4× quadrature the value is 4096.
Why is the RPM reading low or noisy at low speeds?
At low speeds the period per edge becomes large and the HSC's internal period window can quantise the result. Increase the measurement window (the tCycle input, mapped to NEW_PERIOD in nanoseconds) so that more edges are integrated per window. If the period exceeds the technology object's maximum allowed NEW_PERIOD, switch the FB to the inverse algorithm: a fixed wall-clock window and a count of edges.