1. Problem Overview
A four-station rotary distribution arm, driven by a single-direction direct-on-line (DOL) gearmotor, must stop with its outlet aligned over one of four receiving bins spaced 90° apart. The arm is indexed by a single-turn absolute rotary encoder connected to a SIMATIC S7 PLC through peripheral input double word PID 196. A single inductive proximity switch (I48.0) provides a once-per-revolution reference marker on the moving frame.
Two failure modes are reported in the field:
- Per-cycle position creep. Because the motor-to-arm gear ratio is non-integer with respect to the encoder's counts-per-revolution, the encoder reading accumulates a sub-LSB offset on every cycle. After several revolutions the calculated reference value drifts outside the on-target window and the controller declares a positional fault even though the mechanical alignment of the arm over the bin is correct.
- Multiple zero writes per transit. The proximity input is wired as a level-triggered signal, so as the arm dwells on the reference reflector the home value is continuously overwritten. Combined with PLC scan time, this produces a stepped, noisy home reference that itself becomes the source of drift.
This reference document describes the root cause of both failure modes, the correction to the original S7 Statement List (STL) logic, the modular arithmetic required to keep the position value bounded, and the mechanical/control changes needed to overcome the inherited DOL inertia that originally forced the four-proximity architecture.
2. Hardware Architecture
The following table summarizes the field-proven bill of materials for a 4-bin rotary carousel indexed with an absolute encoder on a SIMATIC S7 controller. Component selection and wiring follow standard Siemens SIMATIC S7-300/S7-400 encoder interfacing guidelines, available from the Siemens Industry Online Support portal.
| Item | Part / Designation | Notes |
|---|---|---|
| PLC CPU | SIMATIC S7-300 (e.g. CPU 315-2 DP) or S7-1500 (e.g. CPU 1511-1 PN) | Original platform S7-300, STL source. Equivalent OB1 in S7-1500 uses LAD/FBD or SCL with the same logic flow. |
| Encoder | Single-turn absolute rotary encoder, SSI or PROFIBUS-DP, e.g. 6FX2001-5HS12 (Siemens) or comparable Hengstler / Balluff / Sick unit | Resolution must be chosen so the gear ratio produces > 1 000 counts per revolution after integer scaling (see Section 10). |
| Encoder I/O address | Peripheral Input Double Word PID 196
|
Address is module-slot dependent. In STEP 7 hardware configuration, assign the SSI/PROFIBUS slave to input bytes 196–199 (32 bits) or scale to suit. |
| Reference sensor | Inductive proximity, PNP, NO, M12 | Wired to I48.0. Place the actuator target on the frame, not on the rotating arm, so it is sampled once per mechanical revolution. |
| Drive / Motor | DOL induction motor with integral gearbox | Single direction only. Add a VFD or soft-starter if controlled decel is required (see Section 8). |
| Brake (recommended) | Spring-applied, electrically released holding brake on motor rear shaft | Eliminates the 1–2 LSB of overrun that a coasting DOL motor exhibits past the home reflector. |
3. Encoder Read Path and Scaling
The original STL source loads the raw 32-bit encoder value from PID 196 into a temporary double-word local tag, then shifts the value right by 8 bits with the SRD 8 instruction. SRD is a 32-bit shift-right on a double word; a shift of 8 bits is equivalent to an unsigned integer division by 256, which truncates the low byte. The intent of the shift is to reduce the full 25-bit (33 554 432) absolute count to a workable 0–131 071 range.
The relevant excerpt is:
// Load raw 32-bit encoder value from input periphery
L PID 196 // peripheral input double word at slot address 196
T #Encoder_Position // store in local DWORD
// Scale to a smaller working range
L #Encoder_Position
SRD 8 // shift right 8 = divide by 256 (truncate)
T #Scaled_Position // result 0..131 071
After SRD 8, the working range of #Scaled_Position becomes 0 to 131 071 for a 25-bit encoder, and the author's quoted value of 1 804 counts per revolution is the truncated result of (counts_per_rev_native / 256) rounded down. This number is the critical rollover used in Section 6.
PID notation. In STEP 7 STL, the address format PID <n> denotes a peripheral input in the process image. The peripheral start address must be set in HW Config to match the slot the encoder module occupies. For S7-1500, the equivalent is the %ID data-block format. Reference: Siemens Industry Online Support.4. Root Cause: Why the Original Logic Drifts
The original homing block contains the following sequence:
// Set zero point
A I 48.0 // level of reference proxy
FP #Pulse // rising edge of proxy signal
JCN set // if no edge, skip write
L #Scaled_Position
T #Zero_Value // capture scaled position as home
set: NOP 0
Two defects are visible at once:
-
The
FPedge detector is fed by a level input.FPis the rising-edge (positive edge) of a Boolean. If the input is at 1 for the entire duration of the transit,FPfires exactly once on the 0→1 transition, which is correct. However, the very next instruction isJCN set: if there is no edge in this scan, jump past the write. The author was actually trying to do this correctly, but the next network re-loads#Zero_Valueonly on the cycle that contains the edge, and the rest of the program continues with the stale value. That part is acceptable. -
Subtraction overflow on a circular scale. The reference calculation is a straight 32-bit signed subtract:
L #Scaled_Position L #Zero_Value -I // signed integer subtract T #Reference_ValueOnce the arm moves past 360°,
#Scaled_Positionwraps back near zero while#Zero_Valueis still a large number. The signed subtract produces a large negative value, which the next network attempts to fix withNEGI(negate). The result is not the true arc distance; it is the 2's-complement of the difference, which is correct only when the absolute value of the difference is less than2 147 483 648 / 2 = 1 073 741 824. With small numbers (0..131 071) the negation works numerically, but it produces the wrong direction: when the arm has crossed 360°, the true reference value should reset to a small positive number, not be the absolute of a large negative number.
The combined effect is a position value that:
- Jumps at the home edge (correct once per revolution).
- Walks monotonically because the integer-truncation of the gear ratio means the four 90° targets are not exactly 1 804 / 4 = 451 counts apart. They are 451 counts ± 1 count error, and that ± 1 count is the per-cycle drift observed at the receiving bin.
5. Correcting the Zero-Latch with Edge Detection
The proxy must be sampled on a single transition and latched for exactly one PLC scan. The cleanest solution is to use the falling edge (FN) of the proxy because the reflector is approached from the outside, and the falling edge is mechanically stable (the reflector exits the inductive field perpendicular to the cam).
// One-shot capture on the falling edge of I48.0
A I 48.0
FN #Ref_Falling_Edge // 1 cycle pulse on 1->0
JCN NoLatch
L #Scaled_Position // current scaled count
T #Zero_Value // overwrite home with current position
SET // set RLO = 1
SAVE
NoLatch: NOP 0
// RLO remains 0 if no edge; #Zero_Value is preserved across scans
The FN edge flag is declared as a static BOOL tag in the same FB static section. Important:
-
Declare
#Ref_Falling_Edgeas aBOOLin the FB static area, not as a local temp. A temp is re-initialized on every FB call and the edge memory is lost. - Use the falling edge, not the rising edge. The rising edge fires as the proxy first touches the actuator, which is at a position that depends on approach speed; the falling edge fires at the trailing edge of the actuator, which is geometrically fixed to the cam.
- Move the proxy actuator to the trailing edge of the arm (i.e. the side opposite the direction of travel) so that the falling edge corresponds to the bin-1 centerline, not bin-1 lead-in.
6. Modular Mathematics for Circular Position
The correct formulation for a 0..rollover circular axis is:
Current_Position = (Encoder_Position - Zero_Position + Rollover) mod Rollover
Where Rollover = 1804 counts (the truncated per-revolution value from Section 3). The +Rollover term guarantees the dividend is non-negative before the MOD instruction, eliminating the need for the 2's-complement fix. In S7-300 STL, the MOD instruction operates on a 32-bit signed dividend in accumulator 1 by a 32-bit divisor in accumulator 2:
// Create positive, bounded circular reference value
L #Scaled_Position // 0..131 071
L #Zero_Value // home latch
-I // signed subtract (acc1 = acc1 - acc2)
L #Rollover // 1804
+I // acc1 = (Scaled - Zero) + 1804
L #Rollover // 1804
MOD // acc1 = acc1 MOD 1804
T #Reference_Value // 0..1803, never negative
The MOD instruction is documented in the Siemens SIMATIC S7-300/400 STL Programming Reference. Resulting #Reference_Value always lies in 0..1803, monotonically increasing in the direction of travel, and never crossing the 32-bit signed boundary regardless of how many revolutions the arm has executed.
6.1 Target window for a 90° station
With 1 804 counts per revolution, the ideal 90° interval is 451 counts. A practical on-target window is ± 50 counts (the author's original 400..500 window in the supplied code). The corrected comparison becomes:
L #Reference_Value
L #Target_Bin_N // 0, 451, 902, 1353 for bins 1..4
-I // signed offset from target
ABS // absolute deviation
T #Deviation
L #Deviation
L 50 // window half-width in counts
>I
= #At_Target // 1 if within +/- 50 counts of bin N
ABS. ABS is a 16-bit absolute-value operation in classic S7-300 STL. For a 32-bit deviation use ABS on the appropriate accumulator or pre-load to DINT form. On S7-1500, equivalent operations are available in the SCL / LAD instruction set.7. One-Shot Homing Sequence
The zero value should only be written during a deliberate homing cycle, not on every transit of the proxy. Add a homing-mode flag #HomingActive (BOOL) that is set by an operator pushbutton and reset at the end of the homing cycle:
// Homing request (operator button or first-run after power-up)
A "Homing_Request" // global BOOL, e.g. from HMI tag
S #HomingActive // set latching flag
// Capture home only while #HomingActive is true
A #HomingActive
A I 48.0
FN #Ref_Falling_Edge
JCN NoLatch
L #Scaled_Position
T #Zero_Value
CLR // RLO = 0
R #HomingActive // clear flag, single capture only
NoLatch: NOP 0
This guarantees that #Zero_Value is written exactly once per operator request, eliminating the level-triggered overwrite that causes the home reference to step during a single transit. The arm should be jogging or running in a slow Jog speed during homing, not at full production speed.
8. Inertia Compensation and Deceleration
The original four-proximity design was abandoned because a DOL induction motor overran each proxy by 1–2 cam widths. The overrun is not a PLC problem; it is a drive problem. The following table lists the available mitigations in order of increasing complexity and effectiveness.
| Technique | Implementation | Effect on overrun |
|---|---|---|
| Brake | Spring-applied, electrically released holding brake on motor rear shaft, 24 VDC or 400 VAC release coil, wired through a contactor that drops with the motor contactor. | Eliminates coast-down; reduces overrun to < 1 LSB of the encoder. |
| VFD with decel ramp | Replace DOL with a variable-frequency drive (e.g. Siemens SINAMICS V20, G120). Program a linear decel ramp of 0.3..0.5 s from 50 Hz to 0 Hz on a "Stop" command. Use a digital input as the source of the Stop command, triggered by the proxy. | Reduces overrun to < 0.5 cam width, predictable across product life. |
| VFD with S-curve and DC injection | Add an S-curve profile plus 0.5 s of DC injection braking at zero speed. The injection current must be sized to the motor; too much overheats, too little is ineffective. | Reduces overrun to < 1 encoder count typical, repeatable. |
| Closed-loop position on VFD | Feed encoder position into the VFD (e.g. SINAMICS G120 with CU250S). Use the drive's internal positioner (EPOS) to brake and hold the final position to ±1 count. | Eliminates overrun mechanically; PLC becomes a setpoint source only. |
For a single-direction DOL with a brake, the field-proven approach is:
- Set the proxy actuator such that the proxy trailing edge is approximately 50–100 mm before the bin-1 centerline, depending on the motor's coast-down distance at production speed.
- Issue the Stop command on the proxy rising edge; the motor brake drops on the same contactor; the arm coasts into the bin centerline.
- Trim the actuator position empirically until the arm outlet is centered over the bin within ±2 mm. Lock the actuator with a setscrew and Loctite.
This recovers the original four-proximity architecture, but it now uses the proxy only as a stop trigger; the encoder remains the primary position source. With a brake-equipped DOL the position drift is sub-LSB and the bin-1 home reference can be latched once at commissioning and then trusted for the life of the line.
9. Alternative: Encoder-Only with a Pre-Index Move
When adding a brake or VFD is not possible, the encoder can be used as the sole index source with the following changes to the original logic:
- Run the arm at a fixed production speed, not at variable speed, so the coast-down distance is constant.
- When a target bin is selected, predict the Stop command point by reading the current
#Reference_Valueand the target value, and issue Stop early by the empirical coast-down count (e.g. 25 counts earlier than the 400 lower threshold). - Use a window check after coast-down: read the encoder after a 200 ms settle time; if the value is within ± 50 counts of the target, declare success; otherwise increment a Trim offset by ± 1 count and retry on the next cycle.
The retry-and-trim loop converges in 1–2 cycles and the trim offset becomes a sticky tag that survives a power cycle. The cumulative per-cycle error from Section 4 is then absorbed by the trim instead of propagating to the next revolution.
10. Engineering Units: From Counts to Degrees
Working in degrees rather than raw counts eliminates the binary visual offset. The conversion is:
Position_deg = (Reference_Value × 360) / Rollover
With Rollover = 1804:
- Bin 1: 0° (reference)
- Bin 2: 90° → 451 counts
- Bin 3: 180° → 902 counts
- Bin 4: 270° → 1353 counts
For real-time HMI display, compute the degrees inside the PLC and expose a REAL tag, e.g. "Carousel_Position_deg". On S7-300:
L #Reference_Value // INT
ITD // to DINT
DTR // to REAL
L 3.600000e+002 // 360.0
*RI // multiply REAL * REAL? Use *R for REAL * REAL
// or use ITD then DTR and multiply
T "Carousel_Position_deg"
The S7-1500 equivalent uses the REAL_TO / MUL_REAL instruction family. Siemens STEP 7 programming references cover the full math instruction set.
11. Commissioning and Verification Procedure
Use the following sequence on first install and after any mechanical change to the gearbox, encoder, or cam.
-
Power-up check. With the motor isolated, jog the arm by hand through one full revolution. Verify that
#Scaled_Positionrises monotonically, returns to zero near the proxy, and that the proxy inputI48.0lights once per revolution. Monitor on a STEP 7 VAT or HMI trend. -
Raw rollover count. Record the value of
#Scaled_Positionat the proxy falling edge for ten consecutive revolutions. Compute the average and the range. The average is the true rollover, not the truncated 1 804. Update#Rolloverwith the average. If the range exceeds 1 LSB, the encoder coupling has backlash and must be tightened. -
Homing cycle. Trigger the homing request from the HMI. Verify that
#Zero_Valueis written exactly once, that the#HomingActiveflag clears, and that#Reference_Valuereads 0 immediately after the homing event. -
Single-bin test. Command bin 2, allow the arm to rotate at production speed, and verify that
#At_Targetasserts for at least 200 ms once the arm settles. Log the deviation value on the HMI. -
24-hour soak. Run continuous cycling between all four bins for 24 hours, logging the deviation value of each stop. The deviation must remain within the target window for every stop. If the deviation walks monotonically, the homing logic is still writing multiple times per revolution; check the
FNflag and the#HomingActivelatch. - Inertia audit. With the production load in place, measure the distance the arm coasts past the proxy after the Stop command. If the coast exceeds 100 mm, fit a brake or change the VFD decel ramp.
12. Troubleshooting Matrix
| Symptom | Likely root cause | Corrective action |
|---|---|---|
#Reference_Value jumps erratically between 0 and a large number near the home proxy. |
Subtract producing signed overflow; NEGI produces wrong arc distance. |
Replace -I / NEGI pair with the +Rollover / MOD formulation in Section 6. |
| Reference value walks upward by 1 count per revolution. | Gear ratio not integer with respect to encoder resolution; 1 LSB truncation per cycle. | Use the average rollover count (Section 11, step 2); implement retry-and-trim (Section 9). |
| Arm stops past the proxy by 50–150 mm every cycle. | DOL motor coast-down; no brake or VFD decel. | Fit a holding brake; or replace DOL with a VFD and program a decel ramp (Section 8). |
| PLC declares "off position" fault even though the bin is full and the alignment is correct. | On-target window too tight; position creep has pushed the value outside the window. | Widen the window to ± 50 counts; recompute target values as integer multiples of 451; engage retry-and-trim. |
Home value #Zero_Value changes on every transit of the proxy. |
Edge detector is fed from a level signal and writes continuously. | Switch to FN falling-edge on a static BOOL; add #HomingActive latch (Section 7). |
| Reference value goes negative and stays negative. | Subtraction result was never bounded; NEGI applied unconditionally. |
Use the +Rollover / MOD formulation; remove the NEGI block. |
| Position is correct on first cycle after power-up, drifts within 10 cycles. | Zero latch writes multiple times during first homing, and one of the writes captured a level rather than a stable edge. | Reduce homing speed to < 5 % of production speed; use falling edge; verify with VAT that #Zero_Value changes only once per Homing_Request. |
13. Notes on Encoder Selection
The discussion above uses a single-turn absolute encoder. For a 4-bin 90° application, a single-turn unit is sufficient because the position is bounded to a single 360° window. The choice between incremental and absolute encoders — and the operational consequences of each — is summarized in the Balluff rotary encoder guide. The relevant points:
- Incremental encoders require a homing cycle on every power-up; the PLC must know where the arm is before it can move. In a single-direction, no-brake installation, a missed homing is a catastrophic fault.
- Absolute single-turn encoders (SSI, PROFIBUS, PROFINET, EtherNet/IP) report the true position on every scan with no homing required. They are the correct choice for this application.
- Absolute multi-turn encoders are required only if the arm translates more than one revolution during the process. For a 4-bin fixed carousel, single-turn is enough.
14. Standards and Reference Material
The encoder, wiring, and grounding practices for a SIMATIC installation should conform to the SIMATIC S7-300/S7-400 installation manual and the encoder manufacturer's EMC installation guide. Encoder cable shielding must be terminated at the encoder module end only, with the shield bonded to the cabinet ground bar at the cable entry. Encoder signal cables must be routed at least 200 mm from VFD power cables, or in a dedicated grounded cable tray, to meet the EN 61800-3 EMC requirements applicable to industrial drive environments.
FAQ
Why does the reference value drift when the gear ratio is non-integer?
Each revolution the encoder returns an integer count; the gearbox divides a non-integer number of motor revolutions per carousel revolution, so the per-cycle truncation accumulates a 1-LSB residual. The fix is to (a) use the true average rollover measured at commissioning and (b) implement a sticky ±1-count trim offset that is updated only when the on-target check fails.
Should I use the rising edge (FP) or falling edge (FN) of the reference proxy?
Use the falling edge of the proxy on a static BOOL. The falling edge is mechanically fixed to the trailing face of the actuator cam and is not affected by approach speed; the rising edge fires at a position that depends on the approach dynamics and produces inconsistent home values.
Can I avoid the VFD and still get repeatable stopping?
Yes — fit a spring-applied, electrically released holding brake on the motor rear shaft and drop the brake coil on the same contactor as the motor. With a brake-equipped DOL the coast-down distance is sub-LSB and the four-proximity architecture is fully recoverable. A VFD with a programmed decel ramp is the more flexible solution if product mix requires variable index speed.
Why is the original NEGI / 2's-complement logic wrong?
Signed 32-bit subtraction across a circular scale wraps to a large negative number as the arm crosses 360°. The 2's-complement fix returns the absolute of that negative number, which equals the arc distance only when the arm has moved less than half a revolution from home. For multi-revolution operation the result is wrong, and the only correct formulation is the (Encoder − Zero + Rollover) mod Rollover form documented in Section 6.
How do I display the position in degrees on the HMI?
Convert #Reference_Value (INT) to DINT with ITD, to REAL with DTR, then multiply by 360.0 and divide by the rollover value. Expose the result as a REAL tag. On S7-1500 the equivalent is a single SCL expression: "Carousel_Position_deg" := INT_TO_REAL(#Reference_Value) * 360.0 / #Rollover;.