Lets talk about "good enough"

Or where hold_current can actually be useful.

Lets start with something all of us can agree on. We like printing things as fast and accurate as possible. We also like our printers to not catch fire, be louder than an engine, or be extremely expensive and finicky. We often have to make a trade off between those.

However, sometimes we can have speed, accuracy, and lower volume / heat!

I have tried to find if this was discussed previously, but was unsuccessful. The idea is conceptually simple though. Klipper always needs to know where the toolhead is, but it does not always need the toolhead to be at the exact position the GCode says it should be. The easiest example is a “parked” toolhead, but I believe “drip” mode in toolhead.py is another one. However, I do not know the code well enough to say for certain.

How does this relate to hold_current? The reason I have seen for not using it is drift / jerk when the driver transitions between hold and run currents. However, that can be compensated for or eliminated in certain circumstances. Allowing hold_current or even full shutdown at certain times.

There are several ways to deal with the drift / jerk problem. The obvious is to switch to closed loop control. Klipper has support for rotary encoders,* and can use those to keep track of position even when steppers are turned off. That works for parked toolheads and possibly even extruders / AMS steppers. However, there is a second option that does not require separate hardware.

Quoting from the TMC 2209 Datasheet (rev 1.09)

3.6.1 Restart the Stepper Motor Without Position Loss

A self-locking drive allows switching off the motor completely without loss of position. Locking can result from mechanical friction and from the stepper motor cogging torque. Most stepper motors have a cogging torque in the range of a few percent of their nominal torque, which also will contribute to the motor locking in a certain position. Due to their construction, most motors lock at a fullstep position. A fullstep position is characterized by the position yielded with both coils at identical absolute current. To take advantage of this behavior, stop the motor on a fullstep position.

tl;dr: As long as the stepper is at a fullstep position, there should not be any jerk when transitioning between hold_current and the regular drive current. If Klipper can end moves on those fullstep positions, then motor power can be reduced.

This could be especially useful for printers which use lead screws for the Z-axis. Especially if a model is sliced so each layer is a multiple of the printer’s fullstep. Klipper could adjust a few early layer heights by the needed microsteps so every layer is at that height.**

As I said, let’s talk about it. I’ll admit my use for this feature is a bit different than outlined above. I realized that if I parked the linear motors of my Magneto X at exactly the right spot, relative to the 20mm magnet spacing, I could cut the idle noise of the printer in half.

* I’d like to add support for linear encoders at some point, but different topic.
** Technically, this would work for extrusion and even some motion moves, but would require slicer modification.

FWIW,
TMC will never allow a motor to be in a full-step position.
The only exception to that rule is when you are using the 256 microstepping.
(yes, even with “disabled” microstepping, it will just use the middle position between steps).

So, Klipper can’t make the motor be in the full step position.
Nor is there a simple solution to make them stay in that position.

To make it work with XY, it will only work on a simple Cartesian kinematics, also known as a bed slinger.
Because on the other kinematics, motors will be coupled in one or another way.

Making it work on Z will be really tricky. I think you made a lot of assumptions here.
With lead screw, they should be installed in same phase across all motors to make them align.
They should have a good enough reduction ratio and/or friction to stop motors from spinning without power.
Then, there are Z TILT, which most probably make them out of sync without high precision assembly.

About the concept as a whole, motors are designed to run at a specified current.
Drivers are designed to run at a specified current (There is a sense resistor value for that).

So, I’m not sure I really understand what you are trying to achieve here.
You are right, to not drive current and not make motors/drivers heat, there should be a closed loop.
But generally, during printing when everything moves, I do not see a big gain from such complications.


There is a long read about microstepping, precision, current & etc.

3 Likes

Good points on theoretical vs actual, and I appreciate the link. Thanks! Aside from MCU load, what’s the disadvantage of setting microsteps to 256?

I’m not asking for anyone to do any work. Just thinking “aloud” before doing something stupid with the code. Nothing is fleshed out enough to even be considered a feature.

For this discussion I am interested in noise/power minimization. Especially during idling, but ideally wherever possible. We don’t run the hot-end cooling fan at 100% all the time, and I don’t see a reason we need to run steppers full tilt at idle. The only reason we currently do so is because it’s easier when running in an open loop control mode.

In practice this would be:

  1. Determining when the printer is idling, or in a mode where precision is not critical.
  2. Move to the nearest fullstep.
  3. Move by fullstep increments.
  4. Dynamically setting hold_current on the TMC drivers.

The first and fourth I can do with G-Code. It’s the second and third that I’m trying to figure out how I want to handle. Do you have any thoughts on how to achieve them? As much as anything could be a “feature” they would be the missing piece.

To clarify something. There are more Cartesian printers than just bed slingers. For example, the Mangeto X has the X-axis motor as part of the toolhead.* It also uses a 4x Z lead screw configuration which does not move when powered off. Said linear motors also produce an electrical hiss that’s probably 10db louder when not at a fullstep position. So moving them to a full step position would reduce idling noise significantly.

I believe what you are looking for is the INDEX output pin available on some Stepper Drivers - like the TMC2209:

While it comes out in some modules like the BTT TMC2209:

I do not believe there are any main controller boards out there that can pass the signal back to the MCU so you’re going to have to do some wiring on your own.

Like @nefelim4ag I have a have a hard time seeing how moving to the step start position will improve the 3D printing experience or model quality. I’m not sure that the Magneto X uses basic Trinimac stepper drivers (and, if they do, I am skeptical that moving to the index position will reduce their idling noise without intimately understanding the circuitry used in the printer and what is the cause of the noise).

This is an interesting philosophical discussion but I really don’t think there will be any practical benefits that come from moving to the nearest full step position.

1 Like

Mostly, no difference, maybe it is slightly more silent for someone.
Torque is purely dependent on the next target position, max torque should be when the next position is different by 256 microsteps (one full step), so there is a phase angle of 90 degrees.

I suggest that you calculate how much power they dissipate. Under hold, a motor with 2A current and 1Ω resistance will have 2V coil voltage and 4W power dissipation.

Drivers ensure that the specified current is runs though the motor, resistance is “constant”. Stealth (Pure PWM) is a voltage regulation mode, Spread is current regulation, both in the end ensures target current, regardless of motor power voltage, but limited by it and back EMF.

Under rotations it is more complicated, and it is generally better to measure the power draw from power supply in your setup.
For Nema17 there will be probably <20W at 24V.

They will lose the position on the current change, that is it.
How much depends on the specific circumstances, you can test it by enabling holding current.
On Z it will cause some layer height artifacts.
You probably want to attach an encoder to play with steppers and measure them.

Step driver register MSCNT is enough to determine the position.
There is also Klippy’s internal stepper phase, which is a derivative of that.

Yes, but there are linear servos, so it is a bad example.
But yes, X and Y are decoupled on Magneto X.

That purely depends on the control circuit and electrical frequency in the coils.
TMC has SpreadCycle registers to play around that (they are not all mighty).
Stealth, on the other hand, run most of the time with PWM in inaudible frequency, so it is silent for you.

1 Like

Thanks for the info, and being willing to discuss it.

There are two ways I see to save power/noise using full steps.

  1. While the toolhead is still. Eg. While waiting for the hotend to come up to temperature.
  2. For the Z axes, while waiting for a layer at a specific height to print.

I’m actually more interested in the 1st compared to the 2nd, which is where the title came from. With the thought being to change the hold current and associated register when still. Then disable hold current when actually printing.

As long as the steppers re-gain their position, it’s “free” power savings. Which is where the title comes from.

Hey, 20W is 20W. Good point about measuring what it really is though.

When I get a chance, I’ll dig into Klippy’s internals more.

Right! Need to check if they re-gain their position when going back to full current. No layer lines if they’re only in low power mode while the toolhead is still.

Don’t I know it. Unfortunately, the Magneto X doesn’t use TMC for the X/Y motors. Since they’re not steppers. Instead it uses a pair of these to control the 48V 3 phase linear motors.

Which I’m going to have to write a Klippy modbus extension for before I can do more than just sort of choose parked coordinates that are sort of close. :frowning: