Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions docs/src/gcode/g-code.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1073,14 +1073,19 @@ threads.

[[gcode:g33-tech-info]]
.Technical Info
At the beginning of each G33 pass, LinuxCNC uses the spindle speed and
the machine acceleration limits to calculate how long it will take Z to
accelerate after the index pulse, and determines how many degrees the
spindle will rotate during that time. It then adds that angle to the
index position and computes the Z position using the corrected spindle
angle. That means that Z will reach the correct position just as it
finishes accelerating to the proper speed, and can immediately begin
cutting a good thread.
A G33 move waits for the spindle index, then accelerates from rest to the
synchronized feed. The commanded position follows the spindle angle measured
from that index, so a given thread is cut in the same place whatever the
spindle speed.

While the axis is still accelerating it falls behind that position, by roughly
the pitch squared times the spindle speed squared over twice the axis
acceleration limit, and it makes the distance up over the rest of the move.
Allow enough lead-in for it to catch up before the cut begins, or the start of
the thread is cut with the wrong lead. LinuxCNC reports 'lead-in too short to
reach sync' when the move ends before the axis has caught up. A small lag
proportional to speed remains for the rest of the move, which is why the
spindle speed must not change while a thread is being cut.

.HAL Connections
The pin 'spindle.N.at-speed' must be set or driven true for the motion to
Expand Down
30 changes: 28 additions & 2 deletions src/emc/tp/tp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3567,6 +3567,29 @@ STATIC void tpSyncVelocityMode(TP_STRUCT * const tp, TC_STRUCT * const tc, TC_ST
}


/**
* Warn when the segment is too short to absorb the lead-in lag.
* The tracking loop below closes an error e with v = v_spindle + sqrt(e * a),
* which takes 2 * sqrt(e / a) seconds.
*/
STATIC void tpCheckSyncLeadIn(TC_STRUCT const * const tc, double pos_error)
{
double accel = tcGetTangentialMaxAccel(tc);
if (accel <= 0.0) {
return;
}
double err = fabs(pos_error);
double catchup = tc->currentvel * 2.0 * pmSqrt(err / accel) + err;
double remaining = tc->target - tc->progress;
if (catchup > remaining) {
rtapi_print_msg(RTAPI_MSG_ERR,
"spindle-synchronized move %d: lead-in too short to reach sync, "
"need %f more travel\n",
tc->id, catchup - remaining);
}
}


/**
* Run position mode synchronization.
* Updates requested velocity for a trajectory segment to track the spindle's position.
Expand Down Expand Up @@ -3603,10 +3626,13 @@ STATIC void tpSyncPositionMode(TP_STRUCT * const tp, TC_STRUCT * const tc,
target_vel = spindle_vel * tc->uu_per_rev;
if(tc->currentvel >= target_vel) {
tc_debug_print("Hit accel target in pos sync\n");
// move target so as to drive pos_error to 0 next cycle
tp->spindle.offset = tp->spindle.revs - tc->progress / tc->uu_per_rev;
// Leave the sync origin on the spindle index. The lag built up
// while ramping to sync speed is a real position error, so hand it
// to the tracking loop below; folding it into the origin instead
// shifts the thread by an amount that grows with spindle speed.
tc->sync_accel = 0;
tc->target_vel = target_vel;
tpCheckSyncLeadIn(tc, pos_error);
} else {
tc_debug_print("accelerating in pos_sync\n");
// beginning of move and we are behind: accel as fast as we can
Expand Down