The more I dig into stepper/driver theory, the more I realize how insanely complex the system-level behavior can be.
The big problem with steppers is the fact that the PWM current choppers in the drivers are quirky and interact with the motor specs and PSU voltage in some non-obvious ways. Specifically, the low-end driver chips we tend to use for 3DP (eg A4988, DRV8825) have current chopper duty cycle constraints that often keep them from hitting particular current levels.
First, some basics.
To regulate current, the current chopper can do three things:
- Apply full PSU voltage to the coil to try to raise the current -- equilibrium current calculated via V=IR
- Recirculate coil current through a low resistance to brake the motor and decrease the current (slow decay) -- equilibrium current is 0
- Apply opposite PSU voltage to the coil to reverse-drive the motor and decrease the current (fast decay) -- equilibrium current from V=IR again but in the opposite direction
From the DRV8825 datasheet:
When you do any of the above, the current through the coil will gradually shift in the direction of the equilibrium current for those conditions. How fast the coil current changes depends on:
- Motor inductance
- Motor resistance
- PSU voltage
- Fast vs slow decay mode
- What the instantaneous current is at that moment
The rate of current change is a typical first-order charge/decay curve. The farther the current is away from equilibrium, the faster it changes. After a long enough time, it settles out at the equilibrium value. (Asymptotically approaches it, anyway.) So all the driver's PWM current chopper has to do to regulate current is alternate between on/off modes to switch between different equilibrium currents, and the actual current will be maintained in an intermediate band near the setpoint.
"Slow decay" mode looks like a typical PWM waveform:
"Mixed decay" mode is a little more interesting:
Note that these PWM waveforms look like a series of straight lines, but are actually very short segments of first-order curves. The current is always asymptotically approaching an equilibrium, but slows down its rate of change the closer it gets.
So that's all well and good. In theory, the driver modulates the currents, and the stepper can be microstepped by feeding the coils a roughly sinusoidal series of currents, 90 degrees out of phase. Like this:
You can see how the current must be controlled to a pretty fine resolution -- very small error as a percent of full scale -- for this microstepping pattern to come out right. 1/32 stepping requires sub-0.1% current regulating precision to hit the peak current targets. If the currents are too high or too low, the stepper will have the wrong torque and/or rotate slightly out of the proper position.
The problem is, there are constraints on how long the driver can be in any of those three chopper modes. That affects the range and precision of current regulation. For the Pololu A4988, you have:
- Minimum on time: ~1 µs
- No maximum on time: current will rise until it hits the target
- Fixed off time on rising current microsteps: ~12 µs slow decay
- Fixed off time on falling current microsteps: ~4 µs fast decay and then ~8 µs slow decay (mixed decay mode)
Those parameters are set by the driver chip and the carrier board configuration. Based on these limits and the motor characteristics, there are a variety of reasons you might have trouble hitting particular current targets:
- If motor coil resistance is too high for the voltage, you can't exceed the V=IR current and will not hit high-current microsteps. (See Ed Nisley's blog post)
- If the PSU voltage is too low for the motor inductance and resistance, current might not rise fast enough to hit rising current targets within the time allotted for each microstep
- If the PSU voltage is too high for the motor inductance, the minimum on-time will make the current tend to overshoot the target and skip low-current microsteps
- Slow decay mode might not drag down the current fast enough to hit falling current targets within the time allotted for each microstep
- Fast decay mode might drag down the current too fast, so the average output is way below the target
All of these things cause banding/ripple patterns on prints (usually called "stepper clipping") and generally cause louder/harsher stepper noise. Sometimes you get excess heat production, sometimes you get reduced torque.
Unfortunately, all of these issues vary greatly with the motor speed. Back-emf reduces the effective voltage at higher RPMs. Faster microstepping gives less time for the current to settle towards its equilibrium value, which can help or hurt depending on various system parameters.
High-resistance, high-inductance steppers are simply unsuitable for high-step-rate precision motion applications. You just can't push enough current, and the top part of the sine wave gets cut off. Here's a diagram from Ed's blog post (linked above):
The grey line is the desired microstepping current, the red line is the actual current (limited by high resistance or low voltage), and the pink bands are sections where step commands cause no stepper rotation whatsoever because both coil currents are maxed out. In this case, there are several possible fixes:
- Switch to a lower-resistance stepper
- Raise the supply voltage
- Reduce the driver current setting, so the peak of the current curve is below the limit (reducing the target below the max eliminates the clipping distortion)
This specific issue has promoted a general rule of thumb in the 3DP community: low-inductance steppers are better. That's good advice, but very much over-simplified.
Another common issue is missed low-current microsteps. The stock Pololu A4988 uses slow decay mode on rising-current microsteps. (The parts of the cycle where current targets are rising up the sine curve with each microstep.) And slow decay is really bad at dropping low currents -- they're already so close to zero that the current drops slowly. Whereas the PWM-on period is quite far from the equilibrium +V current, so the current rises very quickly. With high supply voltage and low inductance motors, this means current rises too much during the 1 µs minimum on-time for the 12 µs fixed off-time to drop it back down. When the motor is stationary, this means the driver simply can't keep the current from rising above the target.
The A4988 datasheet even has a specific note about this. Here's the oscilloscope waveform:
That chart makes it look like the current goes straight past the low current targets on rising microsteps. But that's because their demo stepper is turning very slowly. In fact, the stepper cannot stop on the microsteps where the current is not properly limited by the PWM chopper. It will sit a little ahead of the desired microstep position. But with more realistic step rates for 3D printing, the rise time for the "uncontrolled" current is only a little faster than the stepping rate changes the target current. So it looks more like this simulator output:
Note how the PWM chopper is running at minimum duty cycle in slow decay mode, but can't help but let the current slowly rise. Then for falling microsteps where mixed decay mode is used, it works just fine. Only the low-current rising microsteps are getting excess current, and even then, only when the microstepping rate is slower than the current rise. This problem should only happen at low stepping speeds.
Having some excess current on one coil produces position error. Specifically, the rotor runs slightly ahead of the desired position for a while, which generates a ripple pattern in the print. The error my simulator is predicting is small, but would be visible in perimeters:
And you can see this effect in people's prints when they run their printer at extremely low speeds. Here's a low-speed UM2 print with visible stepper ripple (zoom in):
Print photo courtesy of Joel Mongeon in
this thread. Here's another, from my CoreXY at about 40mm/s or so (zoom in):
You can tell it's stepper ripple because, if you flattened the print down to a 2D contour map, you could see the ripples are aligned along a grid pattern with the XY stepper full step positions. Normally, that's around a 0.2mm spacing, but when the print has surface contours oblique to the XY motor axes, the ripples gets spaced out to be quite visible.
To fix this, you can do a few different things:
- Drop the supply voltage
- Get a motor with higher inductance and/or resistance
- Run the stepper faster
- Switch the stepper driver to "low current microstepping" mode by solder blobbing across a resistor on the carrier, so you get mixed decay on rising current microsteps
Running the printer faster is probably the easiest solution. Low current microsteps won't be exactly right, but they'll be close enough. Here's what that same set of parameters looks like at 60mm/s:
Whereas if you switch to low-current microstepping mode, the PWM off-time gets longer and mixed decay mode is always used. That decreases average currents quite a bit below the target:
Ok, that's not too bad, but let's stick with the normal decay settings and look at other possible issues. What happens if we run the steppers REALLY fast? Rising current microsteps won't be an issue. But new and exciting problems start to appear. Let's look at 250mm/s on my CoreXY. It's perfectly capable of that speed, but I don't want to print that fast, because the A4988's PWM chopper REALLY struggles to keep up with the step rate. You start to see some nasty phase lag:
At these high speeds, my simulator starts to get grumpy, because the currents aren't being properly regulated by the driver. There are some minor display and chopper logic glitches in the curves above if you look closely. But it's pretty close to what you should theoretically see. The biggest simulator shortcoming is probably the fact that I'm not showing how Sailfish, Marlin, and other 8bit firmwares go into double-stepping and quad-stepping mode at higher speeds. 250mm/s is 22khz microstepping frequency for my CoreXY. So it's actually quad-stepping, and my simulator doesn't show that.
What's quad-stepping? Well, for example, when Marlin passes 10khz microstepping frequency, it fires two step pulses per interrupt tick. That cuts the clock cycles needed for the stepper interrupt roughly in half so firing the steppers doesn't squeeze out all the non-interrupt processes like motion planning and heater control. When it double-steps, two step pulses are sent to the driver in rapid succession. This ticks up the current target by two microsteps. So in effect, this drops the de facto microstepping level from 1/16 to 1/8 -- via firmware. Then at 20khz microstepping frequency, it quad-steps. So that effectively means dropping to 1/4 stepping. The driver is still running in 1/16 mode, but the rapid quad pulse train means the PWM chopper's reference voltage shifts four steps at a time.
And as we all know, 1/8 or 1/4 stepping is rougher and noisier than 1/16 stepping. If you have a good ear, you can hear the printer shift stepping mode between 1x, 2x, and 4x when it hits speeds that trigger these critical microstep frequency thresholds.
So that's all nice and complicated.
This is a good place to stop and note that these errors are not particularly large compared to other motion system errors. In particular, ringing and filament blobbing and Z-wobble often introduce >10x bigger errors than stepper/driver ripples. Many people never notice stepper issues. They're usually quite faint. But even if your printer is extremely well-built and print settings are perfectly tuned, the stepper driver mechanics can still introduce visible surface ripple defects. It's one of the few parts of printer operation that cause bigger problems with slower print speeds. Lots of people mess this up, from hobbyists to major OEMs. It seems unavoidable with cheap drivers -- their PWM frequency just isn't high enough for precise current control.
I'm going to keep working on my simulator, and hopefully get some live oscilloscope current probe data to validate all the calculations. (Voltage probing says the PWM chopper is running the way I think it is, but that's no substitute for direct current waveform measurement.) And I'm going to make another version for the popular DRV8825 driver, which has different duty cycle constraints. When that's all done, I'll share some version of it with the community for design & tuning.