Stepper vs Servo vs BLDC
Pick the wrong motor class for a project and no amount of firmware will save it. A stepper that misses a step at the wrong moment ruins a print; a hobby RC servo asked to hold a robot arm in place burns its driver in twenty minutes; a BLDC without a half-decent commutation strategy cogs hard enough to feel through a steel frame. The three families look interchangeable from the outside — same NEMA bolt patterns, same shaft diameters, same generic “motor” label in a parts list — but they are three genuinely different machines with three different control philosophies, three different torque-vs-speed shapes, and three different failure modes. The decision is rarely about which motor is “best.” It is about matching the motor’s natural behavior to what the mechanism actually needs: precise open-loop positioning, closed-loop trajectory tracking, or efficient high-speed torque with minimal weight. This post walks each family at the rotor level, the math that separates a noisy six-step BLDC from a silky FOC one, why stepper torque collapses at speed, what closed-loop steppers actually solve, and the realistic project-level decisions that fall out of all of it.
What each motor actually is
The three motor classes share a basic premise — current through coils makes a magnetic field, that field pushes on a rotor with permanent magnets or shaped iron, the rotor spins — but the way they arrange the coils and the way they decide when to switch the current is wildly different. That switching strategy is the entire game.
A stepper motor is, mechanically, a multi-pole permanent-magnet rotor inside a stator with many small teeth. The most common type in hobby and industrial work is the hybrid stepper — a permanent-magnet axial core plus a toothed iron rotor, sitting inside a stator with typically eight teeth per phase, two phases. The geometry is chosen so that with two phases and the right tooth count, you get 200 full steps per revolution (1.8 degrees each). Energize phase A in one direction, the rotor lines up with one tooth position. Energize phase B, it snaps to the next. Reverse A, the next. Reverse B, the next. The rotor lands at discrete, repeatable angular positions purely because of geometry. There is no encoder. There does not need to be. If you count the pulses you sent, you know where the rotor is — as long as it actually followed every pulse.
A servo is not really a separate motor type — it is a control architecture. The classic industrial servo is a brushed or brushless motor plus an encoder plus a closed-loop controller that runs a PID loop on position, velocity, or torque. The motor underneath might be a DC brushed motor (in cheap RC servos), a BLDC (in modern industrial servos), or even a stepper (in closed-loop steppers, which we will get to). The defining feature is the feedback loop: the controller continuously measures where the shaft is and compares it to where it should be, then adjusts. A hobby RC servo is the same idea in miniature: small brushed DC motor, plastic gears, a potentiometer for position feedback, and a tiny PWM-driven controller stuffed into one plastic case.
A BLDC — brushless DC motor — is a permanent-magnet synchronous machine with three-phase windings on the stator and a permanent-magnet rotor. Unlike a stepper, it has only a handful of magnetic poles (commonly 7 or 14 pole pairs in outrunners), and unlike a brushed DC motor, the commutation is done electronically rather than mechanically by brushes. That electronic commutation is where the complexity lives. The motor itself has no idea which winding to energize next — that decision has to be made externally by an ESC or motor controller, either with crude trapezoidal six-step commutation, with Hall sensors, or with full sensored/sensorless field-oriented control.
To make the structural difference concrete, here is what is inside each:
STEPPER (hybrid, 2-phase, 1.8 deg)
+-------------------------------+
| Stator: 8 teeth per phase |
| Rotor: 50 teeth + PM core |
| Phases: A, B (bipolar) |
| Steps/rev: 200 (full step) |
| Position: open-loop, geometric|
+-------------------------------+
BLDC (3-phase, 7 pole pairs)
+-------------------------------+
| Stator: 12 slots, 3 phases |
| Rotor: 14 magnets (PM) |
| Phases: U, V, W |
| Commutation: electronic |
| Position: needs sensor/FOC |
+-------------------------------+
SERVO (RC-style)
+-------------------------------+
| Motor: small brushed DC |
| Gearbox: ~150:1 plastic/metal|
| Feedback: potentiometer |
| Driver: H-bridge + PID MCU |
| Input: 50 Hz PWM, 1-2 ms pulse|
+-------------------------------+
These are three different machines solving three different problems. The stepper’s superpower is geometric position without an encoder. The BLDC’s superpower is high torque density, efficiency, and speed with a clean commutation strategy. The servo’s superpower is closed-loop position tracking out of the box.
Torque curves: the single most important picture
If you only look at one specification when choosing a motor, look at the torque-vs-speed curve. It tells you more about real-world behavior than the data-sheet nominal torque ever will.
A stepper motor’s torque curve is shaped like a cliff. It has a high holding torque at zero speed — this is the torque the motor produces standing still with rated current in the windings — and that torque stays roughly flat through a low-speed region. Then, somewhere between a few hundred and a few thousand RPM depending on the motor, inductance starts to dominate. The windings have inductance L, and the time constant L/R sets how fast current can rise into the coil each step. At low step rates the current has time to reach its setpoint; at high step rates it does not, and the torque falls off sharply. The pull-out torque curve from manufacturers like Oriental Motor and Portescap captures this: it is the maximum torque the motor can sustain at a given speed without losing synchronism. Cross the curve and the rotor stops following — a missed step.
A BLDC torque curve looks completely different. At low speed the available torque is set by current limit (which is set by your driver and your thermal budget). It stays roughly flat from zero up to base speed, the speed at which back-EMF equals supply voltage. Past base speed, torque falls off as 1/speed because the controller cannot push more current into the windings. With field weakening you can extend the constant-power region further, at the cost of efficiency. The practical result: a BLDC happily produces useful torque at thousands or tens of thousands of RPM. A stepper has typically given up by 1,000 RPM.
A servo’s torque curve is whatever the underlying motor’s curve is — minus the gearbox reduction. An RC servo with a 150:1 gearbox has enormous torque and very slow rotation; a direct-drive industrial servo on a BLDC has the BLDC’s curve. The PID loop on top changes how the servo tracks a trajectory but does not change the fundamental physics of what torque the motor can produce.
| Motor class | Holding torque | Low-speed torque | High-speed torque | Typical max RPM | Open-loop pos? |
|---|---|---|---|---|---|
| Stepper (NEMA 17) | High | High | Falls off fast | 600-1,500 | Yes |
| Stepper (closed) | High | High | Slightly better | 800-2,000 | No (encoder) |
| BLDC (gimbal) | Low-medium | Smooth | Flat to high | 5,000-15,000 | No (FOC) |
| BLDC (drone) | Low at zero | Mediocre at low | Excellent | 20,000-50,000+ | No |
| RC servo (hobby) | High (geared) | High (geared) | Limited (geared) | ~60 RPM at shaft | No (PID) |
| Industrial servo | High | High | Excellent | 3,000-6,000 | No (encoder) |
The pattern that falls out of this table: steppers are for slow, precise, high-holding-torque jobs where you do not want an encoder. BLDCs are for fast, efficient, smooth jobs where you accept that you need a controller doing real math. Servos are for “I want to command an angle and have the shaft go there.”
Open-loop steppers and the missed step
The most beautiful thing about a stepper is also its worst failure mode. Because the motor’s position is purely a function of how many step pulses you have sent, you can drive it open-loop — no encoder, no PID, just count pulses. A 3D printer firmware says “move X axis 10 mm at 60 mm/s,” the motion planner translates that to a stream of step pulses to the X stepper driver, and the rotor obediently advances 10 mm worth of steps. Cheap. Simple. Repeatable. No tuning.
Until the rotor doesn’t obediently advance. If the commanded torque at a given speed exceeds the pull-out torque curve — because the bed is sticky, because the belt is over-tensioned, because the acceleration was a hair too aggressive, because the toolhead crashed into a print — the rotor slips a tooth. The driver has no idea this happened. It keeps sending pulses. The firmware thinks the head is at X=120 mm; it is actually at X=118.4 mm. The rest of the print is shifted, ruined, and the only diagnostic is the visible artifact on the part.
Stepper drivers have spent two decades trying to make this less painful. The classic A4988 and DRV8825 drivers from Allegro and TI are honest-to-god current-chopping bipolar drivers with microstepping (1/16 and 1/32 respectively). They are loud, they get hot, and they have no missed-step detection. They are also four dollars on a breakout board, which is why every cheap CNC and 3D printer used them for a decade.
The TMC2209 and TMC5160 from Trinamic (now Analog Devices) changed the conversation. The TMC2209 has two important modes: stealthChop, a voltage-mode PWM scheme that is genuinely silent at low speeds, and spreadCycle, a constant-off-time current control scheme that gives more stable torque at higher speeds. You switch between them based on a velocity threshold via the TPWMTHRS register. The mode bit lives in GCONF.en_spreadcycle — clear it for stealthChop, set it for spreadCycle. A typical Klipper or Marlin config for a TMC2209 looks like:
|
|
That driver_SGTHRS line is where the missed-step problem partly gets solved. stallGuard measures the back-EMF in the motor windings; when the rotor stalls (or is about to), the back-EMF profile changes, and the driver pulls a DIAG pin high. You can wire that into your MCU and either home off it (sensorless homing — no endstop switch needed) or detect a crash and abort. Importantly, on the TMC2209 stallGuard only works in stealthChop mode. On the bigger TMC5160 it works in both modes and adds CoolStep, which dynamically reduces motor current based on load.
This is still not closed-loop position. The driver knows the motor stalled; it does not know precisely where the rotor is. For that you need a true closed-loop stepper: a stepper with an encoder bolted to the back (typically a magnetic encoder reading the shaft) and a small MCU that runs current vector commutation just like a BLDC. The motor still has 200 poles per revolution, but instead of dumb step-pulse counting it does servo-control on the stepper: it commutates the windings based on actual rotor position and increases current only when load demands it. Brands like LDO, MKS, and BTT make these as drop-in replacements for open-loop NEMA 17s on Voron and other 3D printers. They cost three to five times as much, they run cooler under light load (because they only push current when needed), and they cannot miss a step in any meaningful sense — at worst they raise an error.
Servos and the PID lever
A servo’s defining feature is that you command position, not current and not steps. Inside, a controller runs a feedback loop comparing commanded position to measured position. The math is the same PID loop you would write for any closed-loop system — proportional gain to push toward the setpoint, integral gain to eliminate steady-state error, derivative gain to damp oscillation. For a clean walk through the underlying control theory, see PID control from first principles; the servo case is the canonical application.
The cheap RC servo end of the market is dominated by analog and digital hobby servos: small brushed DC motor, plastic or metal gear train, potentiometer feedback, controlled by a 50 Hz PWM signal where 1.0 ms pulse means full counterclockwise, 1.5 ms means center, and 2.0 ms means full clockwise. Driving one from an Arduino is the embedded “hello world”:
|
|
Behind that one-liner the servo’s internal MCU is running the PID loop at a few hundred Hz. The gains are fixed at the factory. You cannot tune them. You cannot read the position back. You cannot get torque feedback. For pan-tilt cameras, hobby robotics, and home automation flaps and valves, this is fine — exactly fine, in fact, because the simplicity is the point.
Industrial servos are a different animal. A Yaskawa, Mitsubishi, or Delta servo drive runs nested loops: a fast current loop (often 10-20 kHz), a velocity loop on top of that (1-5 kHz), and a position loop on top of that (500-1000 Hz). You tune each. You read encoder position, torque, following error, and a dozen other signals back over an industrial bus (EtherCAT, Mechatrolink, CANopen). The motor is almost always a BLDC with a high-resolution encoder — often a 20-bit absolute encoder, meaning roughly one million counts per revolution. That is what makes servo-driven CNC mills hold tenths-of-a-thousandth-of-an-inch accuracy at meaningful feed rates.
Tuning a closed-loop system without overshoot, oscillation, or sluggish tracking is its own skill, and the lessons cross domains. The same logic that shapes a printer toolhead’s acceleration profile (see Klipper input shaping) shows up in servo trajectory shaping: feed the controller a command it can actually follow without exciting mechanical resonance, or you will fight ringing forever.
BLDC commutation: from six-step to FOC
The naive way to spin a BLDC is six-step trapezoidal commutation. The three phases (U, V, W) are connected to a three-half-bridge inverter, and you cycle through six switching states per electrical revolution. Hall sensors tell you which state to enter next. It works, it is cheap, and it is what every $5 hobby ESC has been doing for twenty years.
It is also rough. At each transition between states you get a torque ripple — current is being commutated abruptly. You can feel it as cogging, you can hear it as buzz, and at low speeds it is visibly jerky. For a drone propeller spinning at 20,000 RPM the ripple averages out and nobody cares. For a robot arm holding a delicate position, or a camera gimbal trying to look smooth on video, six-step is not acceptable.
Field-oriented control (FOC, also called vector control) is the alternative. The idea: instead of switching the phases on and off in chunks, continuously control the direction and magnitude of the stator magnetic field so it is always exactly 90 electrical degrees ahead of the rotor field. That is the angle that produces maximum torque per amp. To do that, you need three things at every control tick (typically 10-40 kHz):
- Rotor electrical angle (from an encoder, Hall array, or sensorless observer).
- Phase currents (from two or three current sensors).
- The current-loop math.
The math is two coordinate transforms. The Clarke transform takes the three phase currents (Ia, Ib, Ic) and projects them onto a stationary two-axis frame (Ialpha, Ibeta). The Park transform then rotates that frame by the rotor electrical angle theta into a rotating frame (Id, Iq) synchronized with the rotor. In that rotor-synchronous frame the AC currents look like DC. Id is the current aligned with the rotor flux (which produces no torque and is usually held at zero for normal operation, or driven negative for field weakening). Iq is the current perpendicular to the rotor flux — the torque-producing component.
You run a PI loop on Id to drive it to zero, and a PI loop on Iq to drive it to a torque setpoint. The outputs are voltage commands Vd and Vq, which you run through the inverse Park and inverse Clarke transforms to get the three-phase voltages, then through space vector modulation (SVM) to compute PWM duty cycles for the inverter. The motor never sees the rotation; it just sees a smoothly rotating voltage vector that produces a smoothly rotating current vector, which produces smooth torque. No ripple, no audible commutation, no cogging beyond what the magnetic geometry itself contributes.
In pseudocode the inner loop looks like:
|
|
That is essentially the heart of what SimpleFOC (an Arduino-friendly FOC library that works on AVR, STM32, ESP32, and RP2040) and ODrive (a much heavier-duty STM32-based controller for high-power BLDCs and gimbal motors) do, with substantial polish around motor identification, encoder calibration, current sensing calibration, and trajectory planning. ODrive runs the current loop at 20-40 kHz, supports incremental and absolute encoders, and is rated up to 5 kW peak depending on the model. SimpleFOC is far smaller scale but runs anywhere and is the easiest entry point for understanding what FOC actually does.
The physical effect, if you have not felt it: a properly FOC’d BLDC at zero speed produces holding torque like a servo — you push the shaft, it pushes back smoothly, with no detents, no buzzing, just resistance. Spin it slowly with your hand and it is silent. That is what makes FOC suddenly viable for robot joints (Berkeley Humanoid, Stanford Pupper, MIT Mini Cheetah and its descendants all use direct-drive or quasi-direct-drive BLDCs with FOC) and for camera gimbals (every modern handheld gimbal — DJI, Zhiyun — runs FOC on small gimbal motors).
Why FOC needs the math: a quick sanity check
People sometimes ask why you cannot just sinusoidally commutate without the Clarke/Park business. You can — and at constant speed with no load changes it works fine. The reason FOC dominates is that the transforms turn the control problem from one of tracking sinusoidal references (hard, with phase lag and gain rolloff in the PI loops) into one of regulating DC quantities (easy, exactly what PI loops are designed for). You also get field weakening for free: drive Id negative and you reduce the effective rotor flux, letting the motor spin faster at the cost of torque. You also get clean torque control as a first-class command — set Iq, get torque proportional to it, which is what makes direct torque-controlled robots possible.
This is the same kind of physics-driven layering that makes other “messy at first glance” engineering problems tractable: transform into a frame where the dynamics are linear, control there, transform back. The same approach shows up in solving robot arm motion (see Inverse kinematics for the working engineer), where reducing a non-linear geometry problem to clean joint-space coordinates is what makes the controller solvable in real time.
Drivers and ecosystems
The motor you choose locks you into a driver and software ecosystem. Pretending otherwise leads to projects that stall at the integration step.
| Motor class | Common driver chips / boards | Typical software / library | Encoder? |
|---|---|---|---|
| Open-loop stepper | A4988, DRV8825 | GRBL, Marlin, Klipper | No |
| Quiet stepper | TMC2209, TMC2240, TMC5160 | Marlin, Klipper, RepRapFirmware | No (stallGuard) |
| Closed-loop stepper | LDO/MKS/BTT integrated, BTT EBB | Klipper CAN, custom firmware | Yes (magnetic) |
| Hobby BLDC ESC | BLHeli_32, AM32 | Betaflight, ArduPilot | No (sensorless trapezoidal) |
| FOC BLDC | SimpleFOC shield, ODrive, MoteusController | SimpleFOC, ODrive, Moteus | Yes (mandatory for low speed) |
| RC servo | Built in | Arduino Servo lib, ROS | Internal pot |
| Industrial servo | Yaskawa, Delta, Mitsubishi drives | EtherCAT, Mechatrolink, LinuxCNC | Yes (high-res absolute) |
A note on driver electronics in general: every one of these drivers is at heart a small handful of switching transistors arranged as half-bridges. If you are fuzzy on why MOSFETs are everywhere in motor control, how a transistor actually works covers the relevant physics. The driver IC’s job is to take logic-level inputs and turn them into clean, dead-time-respected gate drive for the bridge.
Project-level decisions: which motor where
The torque curves, control strategies, and ecosystems map cleanly onto which kinds of projects each motor wins.
3D printers. Steppers have dominated for two decades because they are cheap, they hold position without an encoder, and the speeds involved (under 1,000 RPM at the motor in most cases) fit comfortably inside the stepper torque envelope. TMC2209 or TMC5160 drivers in stealthChop give you near-silent operation. Closed-loop steppers are starting to show up on the Voron community’s high-end builds and on production machines like the BambuLab X1. There is also growing interest in BLDC for tool changers and extruders — small gimbal motors give cleaner low-speed control and lower mass, which matters for ringing and acceleration limits.
Robotic arms. Industrial arms (Universal Robots, ABB, Kuka) use sized BLDCs with high-resolution encoders and harmonic-drive gearboxes — effectively, very high-end servos. Hobby and research arms split: small arms (think SO-100, koch arms, the cheap Aliexpress 6-DOF stuff) use closed-loop steppers because they are simple and cheap and don’t need to be fast. Performance research arms (MIT Mini Cheetah descendants, the open-source LeRobot family) increasingly use quasi-direct-drive BLDC actuators with custom FOC controllers, because the torque-control and low mechanical impedance let them do dynamic locomotion.
Drones and multirotors. BLDC, full stop, almost always with sensorless trapezoidal or trapezoidal-with-sinusoidal-blend commutation from an ESC running BLHeli_32 or AM32. At 20,000+ RPM the commutation roughness is invisible, and you want every gram and every watt of efficiency.
CNC mills and lathes. Light-duty hobby CNC routers use steppers (often closed-loop) because rigidity and accuracy at low feed rates matter more than peak power. Production-class mills and lathes use industrial AC servos because they hold position under cutting load, accelerate fast, and tolerate the side loads of a real spindle.
Camera gimbals. BLDC gimbal motors with FOC. The whole product category exists because FOC produces smooth, silent, low-detent torque at zero speed.
Home automation, RC, simple animatronics. Hobby RC servos. The cost per axis is unbeatable and the simplicity (1.5 ms pulse equals center) is the actual feature. For anything needing more than a kilogram-centimeter of torque at the axis, look at DS-series digital servos with metal gears.
Conveyor belts, simple positioning, slow indexing. Open-loop steppers. The job is exactly what they were invented for.
Decision framework
A quick way to choose without overthinking:
- Is the speed under ~600 RPM and the duty cycle moderate? Stepper. Open-loop if you can guarantee load and acceleration; closed-loop if you cannot.
- Is the speed over ~3,000 RPM, or is mass/efficiency critical? BLDC. Six-step if you only run at speed (drones); FOC if you also need clean low-speed behavior.
- Do you need to command position, do not want to write a control loop, and have a moderate price budget? Servo. RC for tiny loads, industrial for real loads.
- Do you need precise torque control or zero-speed holding without buzzing? BLDC with FOC.
- Are you on a printer or a hobby CNC? Probably stepper, probably TMC2209, probably stealthChop.
The single biggest mistake is forcing a stepper into a job that wants speed (you will burn it up and miss steps), or forcing a BLDC into a job that wants open-loop positioning (you will spend a month writing controller code you did not need to write).
Verdict
There is no winner among steppers, servos, and BLDCs — there are only correct matches and incorrect ones. Steppers are unmatched for cheap, simple, repeatable, slow positioning, and modern drivers like the TMC2209 plus the option of closed-loop variants have kept them entirely relevant in 2026. Servos, whether hobby RC or industrial, are the right answer whenever “command an angle, get an angle” is the actual requirement and you do not want to engineer a control loop yourself. BLDCs win whenever you need real torque density, real speed, real efficiency, or silky low-speed control via FOC — and FOC has moved from exotic to routine thanks to SimpleFOC, ODrive, Moteus, and the open-source community around them. Choose the motor class first based on the torque curve and control story your mechanism wants, choose the driver to match, and only then start writing firmware. Get those three layers aligned and the project quietly works; get them misaligned and no amount of clever code will save it.
Sources
- TMC2209 Datasheet (Analog Devices)
- TMC2209 SilentStepStick Pinout and Powering (Watterott)
- Tuning stepper motor drivers (Duet3D Documentation)
- Pull-In and Pull-Out Torque (Kollmorgen)
- Speed-Torque Curves for Stepper Motors (Oriental Motor)
- Torque-Speed Curve Generation in Stepper Motors (Portescap)
- SimpleFOC: Arduino Field Oriented Control Project
- Arduino-FOC on GitHub (simplefoc)
- SimpleFOC: A Field Oriented Control Library for BLDC and Stepper Motors (Zenodo)
- ODrive Robotics
- FOC Current Mode (SimpleFOC docs)
Comments