Reviving this from the dead, as I once again ran into this same issue in my tool changer routine. Clearly, my original "fix" of just not running the spindle in my M6 remap was just a workaround, not an actual solution. In my tool changer routine, I was (of course) stopping the spindle via M5 prior to changing tools, and this was causing it to wait on the first G1 move. I'm not willing to change that to a G0 because I don't want the machine slamming tools in and out of their pockets at full speed.
I haven't been able to easily find a crystal clear definition of this in the official docs, but numerous sources have led me to understand that
after each commanded spindle speed change (including stop/start), upon encountering the next feed-rate move (e.g. G1, G2, G3 and probably others) the motion controller will wait for spindle at-speed to become true. This wait will only occur once after each spindle speed change (i.e. subsequent G1/G2/G3's won't wait) and does not apply to rapid moves (G0).
One aspect that made this issue more insidious and
appear to be more elusive during troubleshooting is that it doesn't behave the same when commanding things manually via GUI or MDI, versus when running an actual program in Auto mode which contained tool changes. I'm guessing that whatever internal flag is associated with this one-time wait gets reset each time execution stops after a manual command.
This behavior is logical enough in the context that G1/G2/G3 are meant to be "cutting" moves whereas G0 rapids moves are not. However in the context of a tool change or probing or similar, a controlled feed rate while NOT cutting is desired, and there is no such thing as a non-cutting controlled-feedrate g-code command in linuxcnc to my knowledge.
Fortunately, I found a way to fake it out:
G91 (incremental distance mode)
G1 X0 F1 ("move" 0 distance at an arbitrary non-zero feed rate - this consumes the one-time wait after a spindle speed change)
G90 (optional - restore absolute distance mode if needed)Thankfully, based on my testing, a zero-distance G1 move seems to be interpreted as a no-op but still consumes the one-time wait.
Adding this before the first "real" G1 move in my tool changer routine has eliminated this issue - at long last!
Other thoughts I had on alternative ways to work around this include:
1) add side-channel logic between the motion and spindle controllers that can stop the spindle without actually changing the commanded spindle speed via G-code (M3/M5 or S commands), so the one-time wait doesn't get triggered in the first place. This could still be sensitive to this issue if the user g-code program happened to trigger the one-time wait just before triggering the remap subroutine(s).
2) add side-channel logic to fake out spindle at-speed (hold it true) for the duration of the subroutine even when the spindle is stopped.
Both of these options seem more risky to me because of the possibility of getting into a bad state in the event of an error in the subroutine and returning to the user program with the normal spindle control still bypassed in some way, but just throwing them out as food for thought...