Long MANUAL_STEPPER moves cause "Timer too close"

've been investigating a “timer too close” error involving MANUAL_STEPPER and noticed that it only happens for some combinations of microstepping and move lengths on the stepper.

For example, this breaks for me (and all values of MOVE larger than this)

MANUAL_STEPPER STEPPER=gear_stepper ENABLE=1
MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0
MANUAL_STEPPER STEPPER=gear_stepper MOVE=1200 SPEED=400 ACCEL=2000

But this will work (and all values of MOVE smaller than this)

MANUAL_STEPPER STEPPER=gear_stepper ENABLE=1
MANUAL_STEPPER STEPPER=gear_stepper SET_POSITION=0
MANUAL_STEPPER STEPPER=gear_stepper MOVE=1000 SPEED=400 ACCEL=2000

As a quick workaround, I set my microstepping to 8 and no longer have the error. With interpolation enabled on the TMC2209 there is little change in noise level fortunately.

More specifically, I found that it related to the time it takes for the step generation to happen. Here’s a quick profile I tested:

240mm move
Total 0.078829635997, Append 2.79170053545e-05, Generate 0.0787814059877, Finalize 2.03130039154e-05

2400mm move
Total 0.520585677004, Append 2.79689993476e-05, Generate 0.520538333003, Finalize 1.93750020117e-05

I was able to generate this by adding a 1 second delay to the schedule start to avoid triggering the error :slight_smile:

I may be willing to help implement a solution, but @koconnor I’d like your input on this issue, and how you think it could maybe be solved?

I’d need to see the full Klipper log to provide any analysis.

However, I’d guess you found the cause - the ManualStepper:do_move() call is synchronous - generate all the steps and then transmit them. So, if the time it takes to generate the steps is greater than the time allotted then when the schedule finally arrives at the mcu it is already past its deadline.

Really long moves on slow host machines used to be an issue for the main Klipper toolhead code as well. The code was updated to generate and transmit moves to avoid that (see toolhead.py:_update_move_time()). That process could be extended to manual_stepper as well.

A short-term solution might be to just break up really long moves into shorter segments in your manual_stepper macros.

-Kevin

1 Like

Thanks @koconnor I used the example from toolhead and was able to get something working fairly quickly, I’ll finish testing and submit an MR in the next couple of days!

Curiously though, do you think this should also apply to FORCE_MOVE?