Configuring SFB47 for Encoder Reading on CPU314C-2 PN/DP

David Krause12 min read
S7-300SiemensTroubleshooting
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

Problem Definition: Pulse Loss at Increased Shaft Speed

When an incremental rotary encoder is wired to the integrated counter inputs of a Siemens CPU 314C-2 PN/DP (e.g., 6ES7314-6EH04-0AB0) and the quadrature decoding is performed inside a cyclic OB (typically OB1) using Boolean comparisons of I0.0 and I0.1, the application will appear to work at very low shaft speeds and then drop counts as the speed increases. The first indication of the fault is a stable position value when the encoder is rotated manually, but a frozen or jumping value as soon as the shaft is turned faster than a few revolutions per minute.

The user in the field reported a Pepperl+Fuchs RVI58V-032K1A61N-02000 (2000 ppr) wired to channel 0 of the integrated counter, with the following SCL block in OB1:

IF (#b = 1) AND (#bOld = 0) AND (#aOld = 1) AND (#a = 1) THEN
    #pulsAmount := #pulsAmount + 1;
END_IF;
IF (#a = 1) AND (#aOld = 0) AND (#b = 1) AND (#bOld = 1) THEN
    #pulsAmount := #pulsAmount - 1;
END_IF;
#position := REAL_TO_INT(
    #pulsAmount * ("Global DB Parameters".encoderDiameter * #pi
                  / "Global DB Parameters".encoderPulseAmount));
#aOld := #a;
#bOld := #b;

Hardware configuration in the device configuration was set to:

  • Operating mode: Count continuously
  • Signal evaluation: Rotary encoder, double (2× quadrature)
  • Count signals / HW gate: 60 kHz
  • Latch: 10 kHz

Despite the hardware being set to 60 kHz, the actual count is lost at speed. The SCL block is the cause, not the wiring or the encoder.

Root Cause: Cyclic OB Polling vs. Hardware Counter

The CPU 314C-2 PN/DP integrates four 24 V counter channels on inputs I0.0..I0.7 (channels 0..3). These are not just fast digital inputs; they are hardware counters with their own internal up/down register, gate control, and latch. The 60 kHz rating applies to the counter front-end, not to the OB1 cycle.

When the application polls I0.0 and I0.1 once per OB1 cycle and reconstructs the quadrature transitions in software, the maximum rate it can detect is bounded by half the OB1 cycle time. For a typical CPU 314C-2 program with several FBs, OB1 runs at 5 to 50 ms. At 20 ms, the highest pulse rate the Boolean logic can see is roughly 25 Hz - i.e. less than 0.2 revolutions per second for a 2000 ppr encoder with 2× decoding (4000 increments/rev). This matches exactly the symptom: it works "only on extreme slow rotation speed".

Hardware counters, in contrast, latch the count in a register that the CPU reads with a single load instruction. Pulse rates up to 60 kHz are captured reliably regardless of OB1 timing.

Rule of thumb: Never decode quadrature in the user program on S7-300. The integrated counter or an external FM/CP module must do the incrementing; the user program must only read the hardware count value.

Affected Hardware and Firmware

Component Order Number / Variant Notes
CPU 314C-2 PN/DP 6ES7314-6EH04-0AB0 (Firmware V3.3) 4 integrated counters, 60 kHz each, 24 V
CPU 314C-2 PN/DP (older) 6ES7314-6CH04-0AB0 Identical counter architecture
CPU 314C-2 DP 6ES7314-6CF02-0AB0 3 counters, same SFB47 interface
Encoder RVI58V-032K1A61N-02000 2000 ppr, HTL/push-pull 10–30 V, cable output
STEP 7 V5.5 + SP2 or later For SFB47 in classic project
TIA Portal V13 SP1 / V14 / V15 / V16 / V17 Use "S7-300C" library for SFB47

The counter architecture is described in the S7-300 CPU 31xC technological functions manual.

Why the User's Configuration Looks Correct but Still Fails

Configuring the channel in HW Config as "rotary encoder double" tells the counter front-end to evaluate both edges of both phases (2× decoding). This setting is consumed by the counter hardware, not by OB1. Once the channel is enabled, the count register at input address PID 300 (default) is updated by the silicon every microsecond. The user program must:

  1. Start the counter via the gate control (set CTRL_DO = 1 in the control interface).
  2. Read the count register (load from PID 300 for channel 0, PID 304 for channel 1, etc.).
  3. Convert the raw count to engineering units using the diameter and PPR.

The user's SCL block does none of the above. It is essentially a slow software quadrature decoder running against a fast hardware quadrature decoder and discarding the hardware's actual count.

Solution Path A: SFB47 in STEP 7 V5.5

For STEP 7 V5.x, the integrated counter is operated through the system function block SFB 47 "COUNT" (background DB instance 0..7 per channel). SFB47 is documented in the S7-300/400 Standard and System Functions reference manual.

Hardware Configuration in HW Config

  1. Open HW Config and insert the CPU 314C-2 PN/DP.
  2. Double-click Count in the slot overview to open the counter properties.
  3. For each active channel:
    • Operating mode: Count continuously
    • Signal evaluation: Rotary encoder, double (2×) or Quadruple (4×) depending on resolution needed
    • Count signals / HW gate: 60 kHz
    • Latch: 10 kHz (used if you wire a reference pulse)
    • Input: 24 V incremental, A = I0.0 (Ch0), B = I0.1 (Ch0), N = I0.2 (Ch0, optional)
  4. Note the assigned input addresses (default: 300..307 for channel 0, 304..311 for channel 1, etc.).

SFB47 Call in OB1

Declare a multi-instance or background DB, e.g. DB200 ("Cnt0_DB"). Call SFB47 in OB1 with:

CALL "COUNT" , DB200       // SFB47, instance DB200
  LADDR   := W#16#300       // Channel 0 logical base address
  CHANNEL := 0
  SW_GATE :=                // Optional software gate (BOOL)
  CTRL_DO :=                // Optional control output (BOOL)
  SET_DO  :=                // Optional direct set (BOOL)
  JOB_REQ :=                // Job request (BOOL, edge)
  JOB_ID  :=                // Job identifier (INT) 0=read, 1=write, etc.
  JOB_VAL :=                // Job value (DINT)
  STS_GATE:=                // Status: hardware gate
  STS_CMP :=                // Status: comparator output
  STS_OFL :=                // Status: overflow
  STS_UFL :=                // Status: underflow
  STS_ZP  :=                // Status: zero mark reached
  JOB_DONE:=                // Job complete (BOOL)
  JOB_ERR :=                // Job error (BOOL)
  JOB_STAT:=                // Job status word (WORD)
  COUNTVAL:=                // Current count value (DINT) - the real result
  LATCHVAL:=                // Latch value (DINT)
END_CALL;

The relevant outputs are COUNTVAL (the live count) and LATCHVAL (the value at the last zero-pulse). For a 2000 ppr encoder in 2× mode, one mechanical revolution is 4000 increments. The user's conversion then becomes:

// "Cnt0_DB".COUNTVAL contains raw count, range -2147483648..2147483647
// Linear distance per increment = (pi * diameter) / (PPR * evaluation)
#position_mm := INT_TO_REAL("Cnt0_DB".COUNTVAL)
                * (3.14159265 * 45.0)
                / (2000.0 * 2.0);
The input address slot 300 is the default; if a different slot is configured, change LADDR to match. The status bits STS_OFL and STS_UFL indicate the counter wrapped; reset with JOB_REQ = edge and JOB_ID = 4 (set counter).

Reading the Count in OB1 (Simplified)

If the user only needs the current value, the call can be reduced to reading COUNTVAL directly; the gate remains permanently enabled by wiring the hardware gate input high. For higher determinism, the SFB47 can be called in OB35 (cyclic interrupt) instead of OB1.

Solution Path B: TIA Portal and the "S7-300C" Library

The SFB47 block does not appear under "Standard library > System function blocks" in TIA Portal. It is shipped in the S7-300C library that comes with STEP 7 V13 and later. To use it:

  1. Open the TIA Portal project and switch to the library task card (right side panel).
  2. Click Libraries > Global libraries → open the supplied S7-300C library (path: Support > S7-300C on the TIA installation media).
  3. Drag the block COUNT (SFB47) into your project tree.
  4. Add an instance DB or use multi-instance. The library version of the FB exposes the same interface as SFB47.
  5. Configure the channel in the device view of the CPU (Properties > Count > Channel 0), exactly as in HW Config.
  6. Call the block in OB1 or OB35 with the correct LADDR (the I/O address from the device configuration).

Reference: S7-300C library description in TIA Portal.

Removing the Software Quadrature Decoder

After SFB47 is in place, the original SCL block is no longer needed. The Boolean variables aOld, bOld and the cyclic edge detection on I0.0/I0.1 should be deleted. Reading the count through SFB47 yields a 32-bit signed count that is updated every microsecond by the counter hardware. The OB1 cycle no longer limits pulse capture.

Example final code (SCL):

// One-time initialization, e.g. in OB100 (warm restart)
IF "FirstRun" THEN
    "FirstRun" := FALSE;
    "Cnt0".SW_GATE := TRUE;          // open software gate
END_IF;

// Cyclic in OB1
IF "Cnt0".STS_OFL OR "Cnt0".STS_UFL THEN
    "Cnt0_DB".JOB_REQ := TRUE;
    "Cnt0_DB".JOB_ID  := 4;            // set counter
    "Cnt0_DB".JOB_VAL := 0;
END_IF;

// Engineering units conversion
#position_mm := INT_TO_REAL("Cnt0".COUNTVAL)
                * 3.14159265 * 45.0 / 4000.0;

Wiring Considerations for the RVI58V-032K1A61N-02000

The RVI58V is a 58 mm housing incremental encoder from Pepperl+Fuchs with HTL/push-pull output, 10–30 V supply, and 2000 pulses per revolution. With cable output (-K1) the cable is shielded and should be routed separately from VFD and power cables.

Wire (cable colour per P+F convention) Signal CPU 314C-2 terminal
Brown +V (10–30 V) 24 V supply
Blue 0 V (GND) 24 V ground
Black Channel A I0.0 (Ch0 A)
White Channel B I0.1 (Ch0 B)
Pink Channel N (zero, optional) I0.2 (Ch0 N)
Shield — Grounded at cabinet entry only

The user reported using only A, B, +, GND. This is acceptable for HTL single-ended wiring if the cable is short (typically < 10 m) and electrically quiet. For longer distances, EMI coupling between the phases causes the comparator to switch on noise spikes and produce extra counts. If the encoder also provides /A and /B (the inverse signals), wire them to the CPU's differential input pins if available; the CPU 314C-2 has hardware comparators that benefit from differential drive.

Field-proven pitfall: Many HTL encoders can be reconfigured for TTL/RS422 by changing a pin or a solder jumper. If yours supports it, switch to RS422 and use a twisted pair per phase. RS422 has 200 mV hysteresis versus ~2 V for HTL, which is decisive above 30 kHz.

Maximum Speed Calculation

For the user's hardware configuration, the maximum allowable shaft speed is determined by the 60 kHz count frequency and the chosen evaluation mode:

Signal evaluation Counts / rev Max RPM (60 kHz limit)
Single (1×) 2 000 1 800
Double (2×) 4 000 900
Quadruple (4×) 8 000 450

Recommended setting for the 2000 ppr RVI58V: keep double evaluation. This gives 4000 increments/rev, well above the user's mechanical positioning requirement, and a 900 RPM ceiling. The user's original SCL block could never have served this; the SFB47 path makes the 900 RPM limit the actual constraint.

Verification Procedure

  1. Download the new program to the CPU. Connect online in TIA Portal or STEP 7.
  2. Open the instance DB of the SFB47 in monitor mode. Confirm STS_GATE = 1 (gate open) and STS_CMP is following the encoder.
  3. Rotate the encoder shaft slowly by hand. COUNTVAL should increment/decrement smoothly and STS_OFL / STS_UFL should remain FALSE.
  4. Spin the shaft at the intended operating speed using a drill or motor. COUNTVAL should track the rotation without freezing.
  5. Trigger a known number of revolutions (e.g. 10) and compare COUNTVAL with 10 × 4000 = 40000. Allow ±1 increment for hysteresis.
  6. Force a stop, then resume. Verify that the count does not jump on the start edge (debounce the first sample if necessary by reading twice).

Troubleshooting Matrix

Symptom Likely cause Fix
Count stable at low speed, frozen at high speed Software decoding in OB1 (this case) Replace with SFB47; use hardware counter
Count drifts by ±1 increment at stand-still Noise on HTL single-ended inputs Use shielded cable, separate from power; switch to RS422 if available
Count always 0, no increments Software gate closed or wrong channel address Check SW_GATE = TRUE; verify LADDR matches HW config
STS_OFL asserted after short run Count exceeded +2 147 483 647 Reset on overflow with JOB_ID = 4
Count goes one direction only A and B wires swapped Swap black/white at terminal or invert JOB_VAL sign
JOB_ERR = 1 after writing Job ID invalid or wrong channel Refer to SFB47 status word JOB_STAT; valid IDs: 0 (read), 1..5 (write jobs)
Counts random / high value spikes Reference pulse N connected to wrong input or floating Leave N unconnected if not used; or wire to I0.2 with shielding
SFB47 not found in TIA Wrong library Install/open S7-300C global library and copy COUNT block

Field-Commissioning Notes

When commissioning on a real machine, perform the verification procedure with the motor drive disconnected first - drive a bench motor at 50 %, 75 % and 100 % of rated RPM. Watch COUNTVAL on a trend in TIA. The trend should be a clean ramp; any step discontinuity indicates a missed or extra pulse, which can be tracked to:

  • Mechanical slip (loose coupling).
  • Encoder bearing failure (signal amplitude drop, edge timing jitter).
  • EMI from a VFD - add a ferrite on the encoder cable at the cabinet entry and ensure the shield is bonded to the cabinet ground bar with 360° contact.

For high-precision applications where the 60 kHz limit is too low, migrate the counter to an FM 350-1 or FM 350-2 counter module. The FM 350-1 supports up to 500 kHz per channel; the FM 350-2 supports 8 channels at 20 kHz each. Both are accessed through dedicated FBs that follow the same read-pattern as SFB47.

Frequently Asked Questions

Why does the encoder read correctly at low speed but lose pulses at high speed on a CPU 314C-2?

The integrated counter is a 60 kHz hardware counter, but if the user program polls the raw digital inputs and reconstructs the quadrature in OB1, the OB1 cycle (typically 10–50 ms) limits the resolvable pulse rate to a few tens of hertz. Use SFB47 to read the hardware count register instead, which is updated every microsecond regardless of OB1.

Where is SFB47 in TIA Portal?

SFB47 "COUNT" is shipped in the S7-300C global library that comes with STEP 7 V13 SP1 and later. Open the library task card, copy the COUNT block into your project, and add an instance DB. The interface (LADDR, CHANNEL, COUNTVAL, JOB_ID, JOB_VAL) is identical to STEP 7 V5.x.

What is the maximum RPM my 2000 ppr encoder can reach on the CPU 314C-2?

With "rotary encoder double" evaluation the count is 4000 increments/rev. The 60 kHz counter limit gives a maximum of 60000 / 4000 = 15 rev/s = 900 RPM. Switch to single evaluation for 1800 RPM, or to an FM 350-1 module for up to 7500 RPM with this PPR.

Do I have to wire /A and /B on the RVI58V encoder?

For HTL single-ended wiring at cable lengths under 10 m, A/B/+24 V/GND is sufficient. For longer runs or noisy environments, switching the encoder to RS422 (TTL) and using /A and /B is recommended; the CPU 314C-2 supports differential inputs through the same terminal pairs.

What is the meaning of SFB47 status bits STS_OFL and STS_UFL?

STS_OFL = TRUE indicates the counter has passed the upper limit (+2 147 483 647) and wrapped; STS_UFL signals the lower limit (-2 147 483 648). Both are latched until reset. Send a write job with JOB_ID = 4 and JOB_VAL = 0 to reset the counter, or wrap-around to a smaller range by using JOB_ID = 1 (set upper limit) and JOB_ID = 2 (set lower limit).

Can I call SFB47 in OB35 instead of OB1?

Yes. OB35 is a cyclic interrupt OB that runs at a configurable interval (default 100 ms). Calling SFB47 in OB35 gives a deterministic read cadence independent of OB1 cycle time. For high-speed applications where you need a fresh count every 1 ms, set OB35 to 1 ms - subject to the CPU's minimum OB35 interval (1 ms for CPU 314C-2).

Back to blog