Below is the translated and polished version of your analysis, ready to be posted on the LinuxCNC forum. It retains all the technical details, observations, and context while being concise and clear for the community. I've formatted it to fit a typical forum post structure, focusing on your issue with the carousel component and the lack of reverse motion in REV_TIME.Forum Post: Lack of Reverse Motion in carousel Component (counts Mode, rev-pulse)
Title: No Reverse Motion in carousel Component with counts Mode and rev-pulse
Body:Hello everyone,Thank you for the help so far. I'm working on a toolchanger carousel with 8 pockets, driven by a stepper motor (1600 steps/rev, scale=200) in LinuxCNC (version [insert your version, e.g., 2.9.2]). I'm using the carousel component in counts mode (encoding=counts, dir=1) with a physical homing sensor on parport.0.pin-10-in. Homing works correctly, but subsequent M6 tool changes fail to perform the reverse motion (rev-pulse=2.0), even though carousel.0.motor-rev changes state. Below, I've analyzed the carousel component's source code to understand how the reverse motion (for locking) should work and why it’s not generating pulses on parport.0.pin-08-out in REV_TIME with stepgen in position mode (step_type=0).Analysis of Reverse Motion Mechanism1. Documentation on rev-pulseFrom the carousel component documentation:text
Copy
pin in float rev-pulse """The duration in seconds for which a ratchet changer (Boxford, Emco) should pulse the reverse pin to lock the holder""";
text
Copy
For tool changers which lock the carousel against a stop the \fBrev-pulse\fR pin can be set to a non-zero value. The motor-rev pin will then be set for this many seconds at the completion of the tool search and at the same time the reverse duty/cycle velocity value will be sent to the motor-vel pin.
Interpretation:
- rev-pulse defines the duration (in seconds) that the motor-rev pin is active (TRUE) to perform a reverse motion to lock the carousel (e.g., for ratchet-type changers like Boxford or Emco).
- During this time, motor-vel is set to rev-dc (reverse velocity), suggesting the reverse motion is intended for velocity control (e.g., DC motors or stepgen in velocity mode).
- The documentation does not mention updating counts-target in REV_TIME, which is critical for counts mode with stepgen in position mode.
My Configuration:
- carousel.0.rev-pulse=2.0 (2 seconds of reverse motion).
- carousel.0.rev-dc=-0.5 (reverse velocity, 50% of max velocity).
- stepgen.2.maxvel=80 (80 pulses/second).
- encoding=counts, dir=1 (unidirectional carousel).
- stepgen.2 in position mode (step_type=0), driven by carousel.0.counts-target.
Expectation:
- After reaching the target pocket (e.g., T1 M6), the carousel should perform a reverse motion for 2 seconds, generating pulses on parport.0.pin-08-out (e.g., 80 pulses, calculated as 2.0 * 80 * 0.5).
2. Source Code Analysis – How Reverse Motion is ImplementedI analyzed the carousel.comp source code to understand how reverse motion is handled, focusing on the REV_TIME state.Transition to REV_TIMEReverse motion is initiated in the MOVE state (state 2) when the carousel reaches the target pocket (current_position == mod_pocket):c
Copy
case 2: // moving if ((current_position != mod_pocket) && enable){ deb = debounce; return; } else if (deb-- > 0) { return; } if (rev_pulse > 0){ motor_fwd = 0; motor_rev = 1; motor_vel = rev_dc; timer = rev_pulse; state = 3; } else if (decel_time > 0) { // stop and prepare for alignment motor_vel = 0; timer = decel_time; state = 5; } else { motor_fwd = 0; motor_rev = 0; motor_vel = hold_dc; active = 0; if (enable && current_position == mod_pocket) ready = 1; state = 9; } break;
What happens:
- If rev_pulse > 0 (in my case, 2.0), the component:
- Sets motor-fwd=0, motor-rev=1 (activates reverse direction, seen on parport.0.pin-09-out).
- Sets motor-vel=rev-dc (in my case, -0.5 for reverse velocity).
- Initializes the timer to rev-pulse (2.0 seconds).
- Transitions to REV_TIME (state 3).
- Key Issue: It does not update counts-target, which drives stepgen.2.position-cmd in position mode.
REV_TIME StateThe REV_TIME state (state 3) handles the reverse motion:c
Copy
case 3: // timed reverse pulse timer -= fperiod; if (timer > 0) return; state = 9; motor_fwd = 0; motor_rev = 0; motor_vel = hold_dc; active = 0; if (enable) ready = 1; break;
What happens:
- The timer counts down rev-pulse (2.0 seconds) in thread cycles (fperiod, typically 1 ms in the servo thread).
- During this time, motor-rev=1 and motor-vel=rev-dc (set in the MOVE state) remain active.
- When the timer expires (timer <= 0):
- Motion stops: motor-fwd=0, motor-rev=0, motor-vel=hold-dc (likely 0 in my case).
- Sets active=0 and ready=1 (signals tool change completion).
- Transitions to WAIT_ENABLE_FALSE (state 9).
- Key Issue: There is no update to counts-target in REV_TIME, so stepgen.2 in position mode does not receive a new target position, resulting in no pulses on parport.0.pin-08-out.
counts Mode and Position HandlingIn counts mode (inst_code='C'), the position is calculated based on counts from stepgen.2.counts:c
Copy
case 'C': // encoder or stepgen counts. new_pos = current_position; if (homed){ int c; int t; int w = width / 2; c = (counts - base_counts); t = floor(((float)c + w) / scale); if (c >= (t * scale - w) && c <= (t * scale + w)) { new_pos = 1 + (t % inst_pockets); if (new_pos < 1) new_pos += inst_pockets; } align_pin = (c % scale <= 2 && c % scale >= -2); }
- counts-target is updated in the DIR_CHOOSE state (state 1) for forward motion:
c
Copycounts_target += (mod_pocket - current_position) * scale;
- In REV_TIME, counts-target remains unchanged, so stepgen.2.position-cmd equals stepgen.2.position-fb, resulting in no pulses.
Velocity vs. Position Mode
- The documentation suggests motor-vel and motor-rev are primarily for velocity control (e.g., DC motors or stepgen in velocity mode, step_type=1).
- In my setup, stepgen.2 is in position mode (step_type=0), where motion depends on the difference between position-cmd and position-fb, and motor-vel is ignored.
- This explains why motor-rev=1 and motor-vel=-0.5 do not generate pulses – stepgen.2 waits for a change in position-cmd (i.e., carousel.0.counts-target).
3. Expected Behavior of Reverse MotionBased on the code and documentation, the reverse motion (rev-pulse) is designed as:
- A timed reverse pulse: After reaching the pocket, the component sets motor-rev=1 and motor-vel=rev-dc for rev-pulse seconds (2.0 seconds).
- Intended for ratchet-type changers where reverse motion locks the carousel against a mechanical stop (e.g., a pawl).
- Assumes motion control via motor-vel and motor-rev, suitable for:
- DC motors (with PWM).
- stepgen in velocity mode (velocity-cmd).
- Carousels with position sensors where the exact number of pulses is not critical.
- In counts mode with stepgen in position mode, reverse motion does not occur because counts-target is not updated in REV_TIME.
4. Why It Fails in My SetupMy observations confirm the issue:
- carousel.0.motor-rev changes to TRUE, and carousel.0.motor-vel to -0.5 in REV_TIME.
- However, stepgen.2.position-cmd, stepgen.2.position-fb, and carousel.0.counts remain unchanged.
- No pulses are generated on parport.0.pin-08-out because stepgen.2 in position mode does not receive a new position-cmd value.
Questions for the Community
- Is the carousel component in counts mode supposed to update counts-target in REV_TIME to enable reverse motion in position mode? If not, how should reverse motion be configured?
- Has anyone used the carousel component in counts mode with rev-pulse for a stepper-driven carousel? If so, could you share your configuration?
- Would modifying the carousel component to update counts-target in REV_TIME (e.g., based on rev-pulse, rev-dc, and maxvel) be a reasonable solution, or is there a better approach?