Robohouse ’26 Library
Contents

Chapter 6

How a stepper driver actually works

6 sections · about 9 minutes

6.1 The H-bridge

At the bottom of every stepper driver are two H-bridges, one per phase. An H-bridge is four transistors arranged around a load in the shape of the letter H: two on the high side connecting to the supply, two on the low side connecting to ground, and the winding across the middle.

Turn on the top-left and bottom-right transistors and current flows left-to-right through the winding. Turn on top-right and bottom-left and it flows right-to-left. Turn on both low-side transistors and the winding is short-circuited to ground, which lets circulating current decay slowly. Turn everything off and the current has nowhere to go except through the body diodes back into the supply, which makes it decay very fast.

Those four states — drive forward, drive reverse, slow decay, fast decay — are the complete vocabulary of the power stage. Everything a driver does is a pattern of switching between them.

One thing an H-bridge must never do is turn on the high-side and low-side transistors of the same leg simultaneously, which shorts the supply straight to ground through the transistors. This is called shoot-through and it destroys drivers. Every real driver inserts a small dead time between turning one off and the other on. You do not have to configure it, but dead time is one of the things that limits how fine the current control can be at very low currents.

6.2 Chopper current regulation

The driver's job is to make the winding current follow a target. Since the winding is an inductor fed from a supply much higher than V = I·R, the approach is to switch rapidly.

The classic scheme, and the one the TMC2209 uses in its SpreadCycle mode, is constant off-time chopping with current comparison. The driver turns on the appropriate transistors to drive current through the winding. Current ramps up. A sense resistor in series with the low side develops a voltage proportional to that current, and a comparator watches it. When the current reaches the target, the driver switches to a decay state and holds it for a fixed off-time. During that off-time the current falls. When the off-time expires, the driver drives again, current rises to the target, and the cycle repeats. The result is a current that hovers around the target in a small sawtooth, at a chopping frequency typically in the tens of kilohertz.

The subtlety is in how it decays. Pure slow decay (shorting the winding) means current falls slowly, which is good for ripple but bad when the target current is falling rapidly — the actual current cannot follow it down and you get distortion of the sine wave. Pure fast decay tracks a falling target well but produces large ripple and more heating. Trinamic's SpreadCycle is a mixed scheme that automatically chooses fast or slow decay based on measured behaviour, which is why it does not need the decay-mode tuning that older drivers such as the A4988 and DRV8825 require.

6.3 StealthChop: a different approach

Trinamic's other mode, StealthChop, does not regulate current cycle-by-cycle at all. Instead it is a voltage-mode PWM: the driver applies a PWM voltage to the winding whose duty cycle is computed to produce the desired current, and it adjusts that duty cycle slowly based on measurements. Because the PWM runs at a fixed frequency and the current is not being chopped against a comparator threshold, the current waveform is far smoother and there is no chopper noise.

The result is a motor that is essentially silent: a stepper that whines audibly under SpreadCycle becomes inaudible under StealthChop.

The trade-off is dynamic response. Because StealthChop regulates slowly, it does not handle rapid changes in load or rapid acceleration as well as SpreadCycle does, and its high-speed torque is lower. The standard configuration is therefore to run StealthChop at low speeds where noise matters and torque demand is low, and switch automatically to SpreadCycle above a velocity threshold. The TMC2209 does this for you: set the TPWMTHRS register to a velocity threshold and the chip handles the crossover.

For a robot arm, I would start in StealthChop everywhere — desktop arm speeds are modest and the quiet is worth having — then enable the SpreadCycle crossover on any joint that struggles at speed, typically J2 and J3, which carry the most load.

6.4 Setting the current

Current is the setting most often got wrong, so it pays to be methodical.

A stepper motor's data sheet gives a rated current per phase. This is the current at which the manufacturer guarantees the motor will not exceed its temperature rating in still air at some ambient temperature. It is a thermal limit rather than a hard one: exceeding it does not cause instant failure, it makes the motor run hotter, which on a PETG-framed arm matters.

Note also whether the rating is RMS or peak. Driver current settings are usually specified in RMS, and motor ratings are often given as peak-per-phase. The ratio is 2\sqrt{2}, so confusing them puts you off by 41%.

There are two ways to set current on a TMC2209, and they interact, so both are worth understanding.

The analogue route uses the VREF pin. In standalone mode, and by default in UART mode too, the chip scales its current reference by the voltage on VREF. Breakout boards fit a small trimpot that divides the internal 5 V rail down to VREF, so turning the pot changes the current. This is the "measure VREF with a multimeter and turn the tiny screw" ritual familiar from 3D printers.

The digital route uses the IHOLD_IRUN register over UART. IRUN is a 5-bit value, 0 to 31, that scales the current while the motor is moving. IHOLD is a separate 5-bit value used when the motor has been stationary for a while. This is better than the pot: repeatable, remotely settable, and able to drop hold current automatically.

The interaction is where it catches people. GCONF bit 0, i_scale_analog, selects whether VREF scales the current. On the TMC2209 this bit defaults to 1, meaning VREF is in play. So you can set IRUN to 31 over UART and still get a fraction of the current you expected, because the pot on the board is turned down. Either set i_scale_analog = 0, so the internal reference is used and IRUN alone determines current, or turn the pot to maximum and control everything digitally. I would do the former; it removes an analogue variable from the system.

The formula relating IRUN to actual current, from the datasheet, is:

IRMS=CS+132×VFSRsense+0.02Ω×12I_{\text{RMS}} = \frac{CS + 1}{32} \times \frac{V_{\text{FS}}}{R_{\text{sense}} + 0.02\,\Omega} \times \frac{1}{\sqrt{2}}

where CS is the current-scale value (i.e. IRUN while moving, IHOLD at rest), R_sense is the sense resistor on your breakout board, and V_FS is the full-scale sense voltage: 0.325 V when the vsense bit in CHOPCONF is 0, or 0.180 V when it is 1. The + 0.02 Ω accounts for internal resistance in the chip.

Most common breakout boards — BigTreeTech, Fysetc, and similar — use a 0.11 Ω sense resistor. Plugging that in with vsense = 0 and CS = 31 gives a maximum of about 1.77 A RMS, which is above the chip's 1.4 A RMS continuous rating, so you will not be using the top of the range. With vsense = 1 the full-scale drops to about 0.98 A RMS, giving finer resolution over a lower range, which usually suits the smaller joints.

The practical procedure: work out your motor's RMS rating, decide on 60–80% of it as a starting point (you can always raise it), pick vsense so that your target lands in the upper half of the available range for best resolution, solve the formula for CS, and set IRUN to that. Set IHOLD to somewhere between a third and a half of IRUN. Then run the arm and put your hand on the motors after ten minutes.

6.5 Hold current, standstill, and heat

TPOWERDOWN sets how long after the last step the driver waits before ramping the current down from IRUN to IHOLD. IHOLDDELAY sets how gradually that ramp happens — a smooth ramp avoids the small position shift you get if the current drops abruptly.

For a robot arm, think about which joints actually need holding torque at rest. J2 and J3 are carrying the weight of the arm and will backdrive if you cut their current — they need meaningful hold current, or a mechanical brake, or a parked position where gravity is not fighting them. J1 rotates about a vertical axis and has essentially no gravity load, so it can hold at very low current. J4, J5, and J6 carry only the wrist and tool.

Tune this per joint rather than applying one global number — every watt you do not dissipate is a watt not heating a plastic bracket.

6.6 Power, wiring, and the mistakes that kill drivers

These are the failure modes that destroy hardware, in rough order of how often they happen.

Disconnecting a motor while powered. The winding is an inductor carrying current. Break that circuit and the inductor generates whatever voltage it takes to keep current flowing, which is a very large voltage, and it appears across the driver's output transistors. This kills drivers instantly and reliably, so do not unplug a stepper with the supply on.

Insufficient bulk capacitance. Each driver needs a substantial electrolytic capacitor across its VM and GND pins, physically close to the chip — 100 µF or more per driver is a sensible target, and the breakout board's own tiny capacitor is not sufficient. Without it, the switching currents the driver draws cause the local supply to sag and ring, and the resulting voltage spikes exceed the chip's rating. Observe the polarity — a reversed electrolytic vents.

Regenerative overvoltage. When a loaded joint decelerates, the motor acts as a generator and pumps energy back into the supply. On an unloaded bench supply this raises the rail voltage, sometimes dramatically. A 24 V supply against a 29 V driver rating leaves some margin, but a heavily loaded J2 doing a fast stop can use it up. Large bulk capacitance absorbs most of this; if the problem persists, a transient voltage suppressor across the rail is cheap.

Powering the logic before the motor supply, or vice versa. Some drivers dislike having VIO present with VM absent, or the reverse. The TMC2209 is reasonably tolerant, but the safe arrangement is to bring both up together from one supply arrangement, and to make sure the Teensy is not trying to drive STEP/DIR/EN into an unpowered driver.

Ground layout. Subtler, and behind most intermittent problems. Motor currents are large and they switch fast. If those currents share a ground path with your logic signals, the voltage drops they create appear as noise on your logic. The rule is star grounding: power ground and logic ground meet at exactly one point, ideally at the power supply. Keep motor wires physically away from signal wires, and if they must run together, use twisted pairs and consider shielding. A single ground loop through the USB cable back to your computer can inject enough noise to corrupt UART traffic to the drivers.

Missing EN control. Wire the drivers' enable pins to a Teensy output, and make sure the Teensy drives them to the disabled state at reset. The EN pin on the TMC2209 is active-low, meaning low enables the driver. A Teensy pin at reset is an input with no pull, so it floats — and a floating EN pin is a coin flip. Fit a pull-up resistor from EN to VIO so that the drivers are disabled by default, and only enable them once the firmware has decided everything is ready.