Crowdfunding now!
View Purchasing OptionsProject update 5 of 6
In earlier updates, and on the main campaign page, we’ve talked about Prunt’s motion profiles, corner blending, and hardware step generation. But there is another important architectural difference between Prunt and Klipper that we have not talked about yet: how internal trajectories are converted to commands for stepper drivers. Prunt’s method completely eliminates one of the major causes of Klipper’s infamous "timer too close" errors.
To go from a trajectory to a stepper command, Klipper begins by solving for the exact time when every single step should be emitted. In Klipper’s source, this happens in klippy/chelper/itersolve.c. That function repeatedly guesses a time, evaluates the stepper position at that time, tightens the bounds, and repeats. This means that higher speed, higher microstepping, more axes moving at once, and more aggressive pressure advance will all mean more step times to calculate.
This is one of the primary reasons why Klipper users run into timing shutdowns. If the host cannot keep the MCU supplied with commands early enough, Klipper can report "timer too close". In some testing for some other benchmarks, we were trying to get a 1 MHz step rate out of Klipper with a simple G1 command on a Raspberry Pi 5 and found that we could not do so without getting an error.
Once Klipper has calculated these step timings they go through what Klipper calls "step compression". Essentially all the exact timings are thrown away and the commands are converted to large blocks of the form "emit 5000 steps 100 µs apart" or similar (these blocks can also include ramps). This is required, as it would simply require too much bandwidth to send the raw timing values to the MCU.
Prunt is designed around a different architecture. Instead of finding the exact time of each step and then squashing that back down into a smaller number of commands, we just directly solve for the position at fixed time steps. For Prunt Board 3, these time steps are 50 µs, or 20 kHz. We do not generate a ton of information and then throw it away.
The important result of this is that the computational cost is identical, no matter how fast the printer is moving or how many microsteps a stepper driver uses. A 10 mm/s move, a 100 mm/s move, or a 100,000 mm/s move all generate the exact same number of position updates per second and each of those updates has the same computational cost, despite requiring a different number of steps.
In short, as long as your printer works with one move it will work with any move, you’ll never see the equivalent of a "timer too close" error just because you tried to print a bit faster.
As an aside, the reason we were trying to generate a 1 MHz waveform from Klipper was to demonstrate how Klipper’s lack of hardware acceleration for step generation can lead to large gaps in step output. We will come back to that at another time, but for now, here’s a plot of Klipper’s step output at a much lower rate when moving at a constant velocity. This usually won’t have much impact in practice, but it’s something that simply can never occur when using Prunt on our hardware, as we use dedicated timers for all step output.
Prunt Board 3 is part of Elecrow Project Aviary