Fix spindle position-sync jitter and catch infeasible thread pitches - #4441
Open
grandixximo wants to merge 4 commits into
Open
Fix spindle position-sync jitter and catch infeasible thread pitches#4441grandixximo wants to merge 4 commits into
grandixximo wants to merge 4 commits into
Conversation
The error correction added sqrt(x_err * a_max) to the tracking velocity. That is the velocity needed to close the error from a standstill, so it is only right when the tracking velocity is zero, which during spindle tracking it never is. It over-corrected, and its gain diverged as the error went to zero, so the loop limit-cycled at the servo rate: the axis chattered and the acceleration slammed between its limits every cycle even with a noise-free encoder. Use v_p = sqrt(v_0^2 + x_err * a_max), which accounts for the non-zero tracking velocity. In simulation the jitter goes away entirely with an ideal encoder; at 256 count/rev the acceleration standard deviation drops from 38.3 to 7.4 and the RMS tracking error from 1.25e-4 to 7.7e-5 in. Formula by Robert W. Ellenberg, from the unmerged PR LinuxCNC#581. Fixes LinuxCNC#164
G33, G33.1 and G76 take the axis feed from pitch times spindle speed, and nothing rejected a feed the machine cannot deliver: the planner clamped the velocity, the axis fell behind, and the thread was cut wrong with no message. Check the pitch against the per-axis maximum velocity at interpret time, so the offending line is named before it cuts. The feed is projected onto each axis by its share of the move length, as the planner distributes it. The bound is the per-axis limit rather than the traj maximum because tpGetMaxTargetVel exempts position-synced moves from the max velocity slider, so the traj value would reject valid programs with the slider down. G33.1 uses K times I, since I multiplies the retract speed. Needs a new GET_EXTERNAL_AXIS_MAX_VELOCITY canon call. The standalone interpreter has no machine and reports zero, which skips the check. Refs LinuxCNC#4391, LinuxCNC#167
The interpreter check only sees the commanded S word. The spindle can still outrun the axis at run time through the spindle override, constant surface speed, or a drive that overshoots, and the planner has no answer but to clamp and cut a wrong thread in silence. Raise an error and abort instead. Demand is measured as revolutions turned across a 0.25 s window times the pitch, the one quantity here with no transient in it: the tracking error carries the v^2/2a lag every G33 picks up while the axis ramps up from rest, and a single-cycle spindle velocity is buried in encoder quantization noise. The axis must also be pinned at its ceiling, which excludes the ramp at the start and the stop on the endpoint at the end. The planner is a separate module and can neither report to the operator nor abort re-entrantly from its own cycle, so it records the fault in emcmotStatus and the controller raises it. Refs LinuxCNC#4391
A thread is cut in several passes over the same helix, so moving the spindle speed part way through shifts the lead. Suspend the override for the duration of a G33 move and a G76 cycle, restoring whatever M48, M49 or M51 last selected. Commercial controls inhibit it during thread cutting too. G33.1 is deliberately left alone, as it is on at least one commercial control: a tap is self-guiding in its own hole, so there is no lead to spoil, and slowing the spindle while it is in the work is useful.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four fixes to spindle-synchronized motion, one per commit.
tp: fix velocity jitter in spindle position sync (fixes #164)
The error correction added
sqrt(x_err * a_max)to the tracking velocity. That is the velocity needed to close the error from a standstill, so it is only right when the tracking velocity is zero, which during tracking it never is. It over-corrected, and its gain diverged as the error went to zero, so the loop limit-cycled at the servo rate. This is the acceleration jitter in the plot on #4391.v_p = sqrt(v_0^2 + x_err * a_max)accounts for the non-zero tracking velocity. The formula and derivation are Robert W. Ellenberg's, from PR #581, which has been open since 2019 and carries 283 files; this is the part that fixes #164, on its own.Measured on a G33 pass with a 256 count/rev encoder, the acceleration standard deviation drops from 38.3 to 7.4 and the RMS tracking error from 1.25e-4 to 7.7e-5 in. With an ideal encoder the jitter goes to zero exactly. The residual at 256 count/rev is the one-cycle backward difference of a quantized position, which no correction formula fixes; see below.
interp: reject a thread pitch the axes cannot follow (refs #4391, #167)
Nothing rejected a feed the machine cannot deliver: the planner clamped the velocity, the axis fell behind, and the thread was cut wrong with no message. The check runs at interpret time so the offending line is named before it cuts.
Two points for review:
tpGetMaxTargetVelexempts position-synced moves from the max velocity slider, so the traj value would reject valid programs with the slider down.Needs a new
GET_EXTERNAL_AXIS_MAX_VELOCITYcanon call. The standalone interpreter has no machine and reports zero, which skips the check.motion: fault when the spindle outruns a synchronized move (refs #4391)
The interpreter check only sees the commanded S word. The spindle can still outrun the axis at run time through the override, constant surface speed, or a drive that overshoots. This raises an error and aborts instead of clamping in silence.
Demand is measured as revolutions turned across a 0.25 s window times the pitch, the one quantity with no transient in it: the tracking error carries the
v^2/2alag every G33 picks up while the axis ramps up from rest, which is several pitches on a coarse thread or a slow axis, and a single-cycle spindle velocity is buried in encoder quantization noise. The axis must also be pinned at its ceiling, which excludes the ramp at the start and the stop on the endpoint at the end.interp: suspend the spindle override during G33 and G76
A thread is cut in several passes over the same helix, so moving the spindle speed part way through shifts the lead. The override is suspended for a G33 move and a G76 cycle, restoring whatever M48, M49 or M51 last selected. Commercial controls inhibit it during thread cutting too.
G33.1 is deliberately left alone, as it is on at least one commercial control: a tap is self-guiding in its own hole, so there is no lead to spoil, and slowing the spindle while it is in the work is useful. That is also why the run-time fault still matters, since G33.1 is where the override stays live.
Testing
Simulation only.
runtestspasses.The two checks were swept over both unit systems, machine velocities from 0.05 to 100 units/s, and encoder resolutions from 16 counts/rev to ideal. No false positives on valid threads running at the axis limit, which is the case that arms the check; a single fault and abort on every spindle runaway. Also verified that an override requested during a G33 has no effect and is restored afterwards, and that G33.1 keeps the override and still faults if that override outruns the axis.
I have no lathe. @Sigma1912 offered real hardware on #4391; that is the test that matters here, particularly for the residual jitter at coarse encoder resolutions, which simulation cannot speak to honestly. Holding for those results.
Not included
PR #581 also adds a spindle velocity estimator and switches the planner to
spindle.N.speed-in. The second half is the interesting one: a real encoder component derives velocity from time between edges rather than counts per period, and the planner already trustsspeed-infor G95 while computing its own difference for G33.It needs a way to know whether
speed-inis connected. The dummysig aliasing used for that in #581, copied frompid.c, writes into a HAL IN pin and clobbers the signal if a user has netted it, and per #4382 the HAL query API must not be called from realtime. An explicit opt-in is the way to do it, in its own change.#167 looks like a duplicate of #4391 and is not auto-closed here.