Motor Controllers & Field-Oriented Control (FOC): The Ultimate Guide
A deep, practical guide to motor controllers and Field-Oriented Control: the three-phase power stage, Clarke/Park math, the current-velocity-position cascade, sensorless observers, tuning, and picking ODrive vs Moteus vs VESC vs industrial servo drives.
A motor by itself is a dumb electromagnet. It is the controller — the box of MOSFETs, the current sensors, and a few kilobytes of fast-loop firmware — that decides whether your three-phase machine behaves like a screaming RC drone motor or a precision servo that holds 0.01° under load. The motor sets the ceiling on torque and speed; the controller decides how much of that ceiling you actually reach, and how gracefully.
This guide is about that controller, and specifically about Field-Oriented Control (FOC), the algorithm that turns a synchronous AC machine into something you can command like a DC motor. We will go through the power stage transistor by transistor, derive the Clarke and Park transforms (correctly, with the conventions stated), walk the current→velocity→position cascade, deal with the rotor-position problem and sensorless observers, and then get concrete about real hardware: ODrive, Moteus, VESC, SimpleFOC, and the industrial drives from Copley, Elmo, and Kollmorgen.
The take: FOC is not exotic anymore — it is the default for any brushless machine where you care about torque quality, efficiency, or quiet operation, and a $50 board now runs the same dq-frame control loop that cost $3,000 a decade ago. What still separates a good drive from a bad one is not the math (everyone has the math) but the power stage, the current sensing, the loop rate, and the protection. Get those right and FOC is almost boring. Get them wrong and no amount of clever control hides a noisy current sensor or a 50 µs loop.
Companion reading: brushless DC motors, servo motors, encoders, real-time control systems, and robot actuators.
Table of contents
- Key takeaways
- What a motor controller actually does
- The power stage: inverter, transistors, gate drivers, sensing
- Commutation methods: six-step vs sinusoidal vs FOC
- FOC explained properly: Clarke, Park, and the dq frame
- The control cascade: current, velocity, position
- Rotor position and the sensor problem
- PWM, switching, dead-time, and field weakening
- Tuning a FOC drive
- The drive ecosystem: hobby vs industrial
- Communication and real-time interfaces
- Protection and fault handling
- Choosing a controller for your robot
- Frequently asked questions
What a motor controller actually does
Strip away the marketing and a motor controller does one thing: it takes a DC bus (a battery, a rectified mains supply, a bench supply) and a command (torque, velocity, or position), and synthesizes the phase currents that make the motor follow that command. Everything else — the comms, the displays, the safety relays — is scaffolding around that core job.
For a brushed DC motor the job is almost trivial: current is proportional to torque, so a single H-bridge with PWM duty controls torque directly. There is no commutation to do because the motor's mechanical commutator already does it. This is why brushed-motor "controllers" are so simple, and why brushed motors persist in low-cost gear.
For a brushless machine — BLDC or PMSM, see the brushless DC motors guide — there is no mechanical commutator. The controller is the commutator. It must continuously decide, based on rotor angle, which windings to energize and how hard, so the stator field stays roughly 90 electrical degrees ahead of the rotor field. That is the whole game: keep the produced torque maximal and smooth by keeping the field angle right.
Rule of thumb: the controller is what turns a motor into a servo. A motor has a torque constant; a servo has a torque command you can trust.
Torque, current, and the role of the controller
In a permanent-magnet machine, torque is (to first order) proportional to the current component that is orthogonal to the rotor flux. Control that current and you control torque. The controller closes a loop around current precisely so that when you ask for 10 N·m, the firmware drives whatever phase voltages are needed — accounting for back-EMF, resistance, and inductance — to make the torque-producing current equal to its target.
This is the conceptual leap that separates a "driver" from a "controller": a driver applies voltage; a controller regulates current (and therefore torque) by closing a feedback loop hundreds or thousands of times per second.
The power stage: inverter, transistors, gate drivers, sensing
Before any math, there has to be hardware that can actually push amps into windings. For a three-phase machine that hardware is a three-phase inverter: three half-bridges, one per motor phase, six switches total.
The three-phase inverter
Each half-bridge (a "leg") has a high-side switch connecting the phase to V+ and a low-side switch connecting it to ground. By PWM-modulating each leg's duty cycle you set the average voltage on each phase. Three legs, three phase voltages, and the difference between them is what drives current through the motor's star- or delta-connected windings.
The six switches are never all independent: in each leg, high and low must never be on simultaneously (that is a dead short across the bus — "shoot-through" — and it destroys transistors in microseconds). Hence dead-time, covered later.
MOSFET vs IGBT vs GaN
The switch technology you pick is mostly a function of bus voltage and switching frequency:
- Silicon MOSFETs dominate from a few volts up to ~200 V (and increasingly to 650 V). Low on-resistance (
R_DS(on)in the single-digit milliohms for good 40–100 V parts), fast switching, cheap. Nearly every hobby and robotics drive uses them. ODrive, VESC, and Moteus are all MOSFET designs. - IGBTs take over at high voltage and high power — think 600 V to 1700 V, tens to thousands of amps, industrial and traction drives. They have a fixed ~1–2 V saturation drop (bad at low current) but scale to power levels MOSFETs cannot. Switching is slower, so IGBT drives often run 4–16 kHz PWM.
- GaN (gallium nitride) and SiC (silicon carbide) are the modern wide-bandgap options. GaN excels at lower voltages (≤650 V) with extremely fast switching and tiny losses, enabling >100 kHz PWM and very compact drives. SiC owns the 650 V–1200 V high-power space (EV traction inverters). Both cost more and demand careful layout because the fast
dV/dt(tens of V/ns) makes EMI and gate-loop parasitics unforgiving.
Rule of thumb: under 60 V, use silicon MOSFETs unless you have a specific reason not to. GaN is worth it when size or switching loss dominates; SiC and IGBT belong above a few hundred volts.
Gate drivers and bootstrap
A logic-level microcontroller pin cannot switch a power MOSFET fast enough — gate charge is too large and the high-side gate needs to float above the bus. That is the gate driver's job: it takes a PWM logic signal and delivers several amps of gate current to switch the FET in tens of nanoseconds.
The high-side switch is the tricky one. Its source floats at the phase voltage, which swings between 0 and V+. To turn it fully on, the gate must be driven above V+. Two common solutions:
- Bootstrap: a capacitor charges through a diode to roughly the gate-drive rail (~12 V) while the low-side is on and the phase is near ground; that charge then floats the high-side gate supply when the high-side turns on. Cheap, but the bootstrap cap must be periodically refreshed, so you cannot hold a phase high indefinitely at zero speed without a charge-pump or isolated supply.
- Isolated supplies / charge pump: an isolated DC-DC per high-side, or a charge pump, supplies the high-side gate continuously. More expensive, but mandatory for sustained DC output (e.g., a servo holding torque at zero speed).
This bootstrap limitation is a real gotcha: some cheap ESCs visibly struggle to hold a stalled motor because the bootstrap caps droop. Servo-grade drives use isolated or charge-pump high-side supplies for exactly this reason.
Current sensing: shunt vs hall
FOC needs phase current measurements, and the quality of those measurements sets a hard ceiling on control quality. You cannot regulate what you cannot see.
- Low-side shunt resistors: a small resistor (e.g., 0.5–2 mΩ) in series with each low-side FET, measured with a differential amplifier. Cheap and accurate, but you can only read current when the low-side is on, so sampling must be synchronized to the PWM (sample in the middle of the low-side-on window). At very high duty cycles the low-side window shrinks and measurement gets hard — three-shunt designs help, and many drives reconstruct the third phase from
Ia + Ib + Ic = 0. - Inline (phase) shunts: resistor directly in the phase wire with a high-side-capable or isolated amplifier. Measures continuously regardless of switch state, which is cleaner for FOC, at higher cost and complexity. ODrive and Moteus use inline/high-side sensing.
- Hall-effect current sensors (e.g., closed-loop or magnetoresistive): galvanically isolated, no insertion loss, good for high current and high voltage. More expensive, more board area, and bandwidth/offset can be limiting. Common in industrial and high-power drives.
Rule of thumb: two phase-current measurements are enough (the third is
-(Ia+Ib)), but three measurements give you redundancy, fault detection, and better performance near 100% duty.
The DC bus
The bus capacitor is not a detail. The inverter draws pulsed current from the bus at the switching frequency, and the source (battery, supply) cannot respond that fast. Bus capacitance — bulk electrolytics plus ceramic decoupling close to the FETs — supplies the high-frequency ripple current and clamps voltage transients. Undersized bus caps cause voltage ripple, EMI, and in the worst case overvoltage trips during regen. A drive that ignores its bus capacitor will be noisy and unreliable no matter how good the firmware is.
Commutation methods: six-step vs sinusoidal vs FOC
There are three families of commutation for a brushless machine, in increasing order of sophistication and torque quality.
Six-step (trapezoidal) — the BLDC ESC
In six-step or trapezoidal commutation, at any instant exactly two of the three phases conduct and one floats. As the rotor turns, the controller switches through six conduction states (hence "six-step"), each spanning 60 electrical degrees, typically using Hall sensors or back-EMF zero-crossing on the floating phase to know when to commute.
It is simple and computationally trivial — a lookup table and a PWM duty. It is also what most RC/drone ESCs do. The downside is torque ripple: because current is held flat across each 60° sector while the back-EMF and ideal current vary, torque pulses at six times the electrical frequency, on the order of ~14% peak-to-peak ripple in the ideal case, worse in practice. At low speed this ripple is audible and felt as cogging-like roughness, and back-EMF sensing fails near zero speed.
Sinusoidal commutation
Sinusoidal (or "sine") commutation drives all three phases continuously with sinusoidal currents phased 120° apart, tracking rotor angle from a position sensor. This eliminates the six-step torque ripple and is smooth and quiet. But classic sinusoidal control regulates the phase currents directly in the stationary frame, where the targets are time-varying sinusoids — and PI controllers have finite bandwidth, so they lag and lose accuracy as speed rises. It is smooth at low speed but degrades at high speed.
FOC (vector control)
FOC keeps the smooth sinusoidal currents but transforms the control problem into the rotor's rotating frame, where the quantities become DC and the PI loops face a constant setpoint at any speed. It also explicitly decouples torque-producing current from flux-producing current. The result is smooth torque from zero to top speed, optimal torque per amp, and the ability to do field weakening. The cost is more computation (the transforms) and a need for accurate, fast rotor-angle and current measurement.
| Method | Torque ripple | Low-speed quality | High-speed quality | Sensor need | Compute | Typical use |
|---|---|---|---|---|---|---|
| Six-step / trapezoidal | High (~14%+) | Poor | Good | Hall or sensorless BEMF | Trivial | Drones, fans, pumps, e-bikes (cheap) |
| Sinusoidal | Low | Good | Degrades with speed | Needs angle (encoder) | Moderate | Quiet appliance/HVAC, basic servo |
| FOC (vector) | Very low | Excellent | Excellent | Needs accurate angle | Higher (transforms) | Robotics, servos, EVs, anything precise |
Rule of thumb: if it spins fast and roughness doesn't matter (a propeller, a pump), six-step is fine and cheaper. If you need controllable torque, smoothness, or motion at low/zero speed, use FOC.
FOC explained properly: Clarke, Park, and the dq frame
Here is the part people get hand-wavy about. Let us do it correctly, stating conventions.
The problem: in the stator frame, phase currents Ia, Ib, Ic are sinusoids that vary with rotor position. Controlling sinusoids with PI loops is hard because the target keeps moving. The solution is two coordinate transforms that take us into a frame that rotates with the rotor, where the currents we care about are constant (DC) in steady state.
Step 1 — Clarke transform: 3-phase → 2-axis stationary (αβ)
The three phase currents are not independent (they sum to zero in a star connection), so two orthogonal axes fully describe them. The Clarke transform maps (Ia, Ib, Ic) onto a stationary two-axis frame (Iα, Iβ) where α is aligned with phase A.
Using the amplitude-invariant (2/3) convention:
Clarke transform (amplitude-invariant, assuming Ia + Ib + Ic = 0):
Iα = Ia
Iβ = (Ia + 2·Ib) / sqrt(3)
Full form (not assuming sum = 0):
Iα = (2/3) · ( Ia - 0.5·Ib - 0.5·Ic )
Iβ = (2/3) · ( (sqrt(3)/2)·Ib - (sqrt(3)/2)·Ic )
The αβ frame is still stationary — Iα and Iβ are still sinusoids as the rotor turns. We have just gone from three numbers to two. The real magic is next.
Step 2 — Park transform: stationary αβ → rotating dq
The Park transform rotates the αβ vector by the rotor electrical angle θe, into a frame that spins synchronously with the rotor. The d-axis (direct) is aligned with the rotor's permanent-magnet flux; the q-axis (quadrature) is 90 electrical degrees ahead and is the torque-producing axis.
Park transform (αβ -> dq), θe = rotor electrical angle:
Id = Iα·cos(θe) + Iβ·sin(θe)
Iq = -Iα·sin(θe) + Iβ·cos(θe)
Because the frame rotates with the rotor, the sinusoidal αβ currents become constant Id and Iq in steady state. That is the whole point: AC control becomes DC control. A PI controller regulating a DC quantity has zero steady-state error and behaves beautifully — none of the lag problems of chasing a moving sinusoid.
The physical meaning:
- Iq is the current orthogonal to the rotor flux → it produces torque. Torque ≈
(3/2)·(P/2)·λ_pm·Iqfor a surface-PM machine, wherePis pole count andλ_pmis the magnet flux linkage. - Id is the current aligned with the rotor flux → it produces no useful torque in a non-salient machine; it adds to or weakens the magnet flux.
Step 3 — Id = 0 control
For a surface-mount PMSM (non-salient, Ld ≈ Lq), every amp of d-axis current is wasted heat that produces no torque. So the d-axis setpoint is Id* = 0: put all your current into the q-axis, getting maximum torque per amp (MTPA). For interior PM or salient machines, MTPA actually wants a small negative Id to exploit reluctance torque — but Id = 0 is the correct, simple default for the surface-PM motors most robots use.
Step 4 — The two PI current loops
Now we have two clean DC control problems:
- A q-axis PI loop drives
Iq → Iq*(the torque command from the outer loops). Its output isVq, the q-axis voltage demand. - A d-axis PI loop drives
Id → 0(or the field-weakening setpoint). Its output isVd.
The two axes are slightly coupled through speed (the ω·L·I cross terms and back-EMF). Good FOC adds decoupling feedforward terms so each PI loop sees an almost independent first-order plant:
Decoupling feedforward (added to PI outputs):
Vd_ff = -ωe · Lq · Iq
Vq_ff = +ωe · (Ld · Id + λ_pm)
Step 5 — Inverse Park, then SVPWM
The PI loops give us (Vd, Vq) in the rotating frame. To actually command the inverter we rotate back to the stationary frame with the inverse Park transform:
Inverse Park (dq -> αβ):
Vα = Vd·cos(θe) - Vq·sin(θe)
Vβ = Vd·sin(θe) + Vq·cos(θe)
Then (Vα, Vβ) — a voltage vector in the stationary plane — is realized by the inverter using Space Vector PWM (SVPWM). Conceptually SVPWM approximates the desired voltage vector as a time-weighted average of the eight discrete states the inverter can produce (six "active" vectors 60° apart, plus two "zero" vectors with all-high or all-low). It computes how long to spend in the two adjacent active vectors and the zero vectors over each PWM period.
The practical reason to use SVPWM rather than naive sinusoidal PWM: it uses the DC bus about 15.5% more effectively (it can synthesize a fundamental amplitude up to Vdc/√3 rather than Vdc/2), because it injects a third harmonic / common-mode offset that cancels across the line-to-line voltages. More bus utilization means more speed and more torque headroom from the same battery.
The complete FOC loop, in order
Putting it together, every current-loop tick (typically every 25–125 µs):
1. Sample phase currents Ia, Ib (Ic = -(Ia+Ib)) [synchronized to PWM]
2. Read rotor electrical angle θe from sensor/observer
3. Clarke: (Ia, Ib) -> (Iα, Iβ)
4. Park: (Iα, Iβ, θe) -> (Id, Iq)
5. PI loops: Id->Id*=0 gives Vd ; Iq->Iq* gives Vq (+ decoupling)
6. Inverse Park: (Vd, Vq, θe) -> (Vα, Vβ)
7. SVPWM: (Vα, Vβ) -> three PWM duty cycles
8. Update inverter compare registers
That loop, run fast and fed accurate current and angle, is FOC. Everything in the rest of this guide is in service of running it well.
The control cascade: current, velocity, position
FOC's current loop regulates torque. But you rarely command raw torque to a robot joint — you command a position or a velocity. So real drives stack three nested loops, the classic cascade:
position* -> [POSITION PI/P] -> velocity* -> [VELOCITY PI] -> Iq* (torque) -> [CURRENT PI x2 = FOC] -> inverter
- Inner: current (torque) loop. The FOC dq loops. Fastest, runs at the PWM-synchronized rate (e.g., 10–40 kHz). It must be the fastest because everything outside it assumes torque is "instant."
- Middle: velocity loop. Takes a velocity command, compares to measured velocity (from encoder differentiation or observer), outputs a torque command. Runs at, say, 1–8 kHz.
- Outer: position loop. Takes a position command, compares to measured position, outputs a velocity command. Often just proportional, runs at hundreds of Hz to a few kHz.
Bandwidth separation
The cascade only works if the loops are separated in bandwidth. Each loop must be fast enough that the loop inside it looks instantaneous, and slow enough that it doesn't fight the loop outside it.
Rule of thumb: target roughly a 5–10× bandwidth ratio between adjacent loops. If your current loop is ~1 kHz, velocity loop ~100–200 Hz, position loop ~10–30 Hz. Violate this and the loops interact, you get oscillation, and tuning becomes a nightmare.
Feedforward
Pure cascaded feedback always lags — the error has to exist before the controller reacts. Feedforward injects a predicted command ahead of the error:
- Velocity feedforward into the position loop: feed the commanded velocity directly, so the position loop only corrects the residual.
- Acceleration / torque feedforward into the velocity loop: from a trajectory's known acceleration and the load inertia, compute the torque you know you'll need (
τ = J·α) and add it directly to Iq*.
Done well, feedforward lets a drive track a smooth trajectory with tiny following error while keeping feedback gains modest. This is standard on industrial motion controllers and increasingly on robotics drives like Moteus and ODrive. For where these loops physically run and at what determinism, see real-time control systems.
Rotor position and the sensor problem
FOC's Park transform needs the rotor electrical angle θe every tick. Get it wrong by even 10–20 electrical degrees and you lose torque and efficiency; get it 90° wrong and the motor produces no torque or runs away. So rotor position sensing is the most consequential decision in a FOC system after the power stage.
Encoders and absolute sensors
The clean answer is a position sensor on the shaft. See the encoders guide for depth, but in brief:
- Magnetic absolute encoders (e.g., on-axis Hall-array chips like the AS5047/AS5048, or the iC-Haus/MA-series parts) give 12–14 bit absolute angle over SPI/ABI, are cheap, and are the workhorse of robotics drives. ODrive and Moteus default to these.
- Optical incremental encoders give high resolution and accuracy but are incremental — you need an index pulse or commutation hall sensors to find the absolute angle at startup.
- Resolvers are rugged, analog, absolute, and standard in industrial/automotive servo motors; they need resolver-to-digital conversion.
With a known electrical angle offset (the alignment between the encoder zero and the rotor's d-axis, found by a calibration routine at startup), the sensor gives θe directly and FOC just works from zero speed.
Hall sensors
Three Hall sensors give 60°-resolution commutation states — enough for six-step, and enough to bootstrap FOC at startup, but too coarse for high-quality FOC angle on their own. Some drives interpolate Hall transitions with velocity, or use Halls only to seed a sensorless observer.
Sensorless: observers and back-EMF
A sensor adds cost, wiring, and a failure point. Sensorless FOC estimates θe from the electrical signals alone:
- Back-EMF / flux observers: the rotor's motion induces a back-EMF proportional to speed; by observing the motor's voltage and current and running a model (a flux-linkage observer, a Luenberger observer, or an extended Kalman filter), you can estimate the flux angle and thus θe. Texas Instruments' InstaSPIN-FOC packages exactly this (their "FAST" flux/angle/speed/torque estimator) in ROM.
- Sliding-mode observers (SMO): a robust nonlinear observer that estimates back-EMF and is popular for its disturbance rejection.
These work well above some minimum speed (often a few hundred electrical RPM). The fundamental problem is zero and low speed: back-EMF is proportional to speed, so near standstill there is almost no signal to observe. The angle estimate becomes garbage exactly when you need to start.
The startup / zero-speed problem
Two common fixes:
- Open-loop / forced commutation start: ramp a rotating voltage vector to drag the rotor up to a speed where the observer locks in, then switch to closed-loop. Crude, can cause a stutter or backward kick, but fine for fans and pumps.
- High-frequency injection (HFI): inject a small high-frequency signal and measure the inductance variation with rotor angle (it only works on salient machines, where
Ld ≠ Lq). This gives true zero-speed sensorless position — it is how some appliance and traction drives start under load without a sensor.
Rule of thumb: if you need controllable torque at zero speed (a robot joint, a winch, a stalled actuator), use a position sensor. Sensorless is excellent for spinning loads but is a compromise at standstill.
PWM, switching, dead-time, and field weakening
Switching frequency
The inverter chops the bus at the PWM switching frequency, typically:
- 8–20 kHz for industrial IGBT drives and many BLDC ESCs (often kept below ~20 kHz to limit switching loss; above 20 kHz also pushes it out of the audible band).
- 20–60 kHz for low-voltage MOSFET robotics drives (ODrive, Moteus, VESC commonly run 20–40 kHz).
- >100 kHz possible with GaN.
Higher switching frequency means lower current ripple (the inductor sees the chopping less), higher achievable control bandwidth, and quieter operation — but more switching loss (each transition burns energy in the FET). It is a direct trade.
The current control loop usually runs at the PWM rate or half of it (sampling at the PWM peak/trough where current is at its average value). So switching frequency and control-loop rate are linked.
Dead-time
In each leg, you must insert a dead-time — a brief window where both high and low switches are off — during the transition, so they are never on together (shoot-through). Typical dead-time is 0.1–2 µs depending on device speed and gate drive.
Dead-time is necessary but harmful: during it, current flows through the body/freewheel diodes and the actual output voltage deviates from what you commanded, by an amount that depends on current direction. This dead-time distortion causes low-order harmonics, torque ripple, and current crossover distortion near zero current. Good drives apply dead-time compensation — predicting the error from current sign and adding it back to the duty command.
Rule of thumb: minimize dead-time to the smallest value your gate drive and FETs can safely tolerate, then compensate the residual in firmware. Excess dead-time is pure distortion.
Bus voltage and modulation index
The modulation index is how much of the available DC bus you're using. At 100% (full modulation) you've run out of voltage — the back-EMF plus the IR and L·di/dt drops have consumed the entire bus. Once you hit the voltage ceiling, you cannot push more current at that speed; the current loop saturates.
With SVPWM the linear ceiling is V_phase_peak ≤ Vdc/√3 (≈ 0.577·Vdc), vs 0.5·Vdc for sinusoidal PWM. Beyond linear, overmodulation squeezes a little more out at the cost of harmonic distortion.
Field weakening
What happens when you want to spin faster than the bus voltage allows at Id = 0? The back-EMF grows with speed and eventually equals the bus, leaving no headroom to push current. Field weakening drives Id negative, creating a stator flux that opposes the rotor magnet flux, reducing the effective back-EMF and letting the motor spin faster — at the cost of torque (you're spending current on flux instead of torque, and the total current is limited).
Field-weakening logic (simplified):
- Run Id* = 0 until the q-axis voltage demand Vq approaches the bus limit.
- As the voltage vector magnitude sqrt(Vd^2 + Vq^2) hits the SVPWM ceiling,
command Id* < 0 to reduce back-EMF and free up voltage for Iq.
- Respect total current limit: Id^2 + Iq^2 <= Imax^2.
Field weakening is how EVs and high-speed spindles get a wide constant-power speed range above base speed. ODrive, VESC, and most industrial drives support it; it demands accurate motor parameters and careful current limiting because a field-weakening fault at speed (e.g., losing control while back-EMF exceeds the bus) can overvoltage the bus.
Tuning a FOC drive
The single best thing about FOC is that the inner loop is analytically tunable from motor parameters — you don't have to guess.
Current-loop gains from R and L
Model one axis of the motor as a first-order R–L plant: V = R·I + L·(dI/dt). A PI controller Kp + Ki/s regulating this plant has a clean closed-form tuning if you place the PI zero to cancel the plant pole (Ki/Kp = R/L). Then the closed loop becomes a first-order system with bandwidth ωc (rad/s), and:
Current-loop PI gains (pole-zero cancellation):
Let ωc = desired current-loop bandwidth in rad/s
(e.g., bandwidth_Hz * 2*pi; pick ~1/10 of switching freq)
Kp = L · ωc // proportional gain (volts per amp)
Ki = R · ωc // integral gain (volts per amp-second)
Check: Ki/Kp = R/L -> PI zero cancels the motor's electrical pole
So if you measure R = 0.1 Ω, L = 50 µH, and want a 1 kHz current loop (ωc = 2π·1000 ≈ 6283 rad/s): Kp = 50e-6 · 6283 ≈ 0.31 V/A and Ki = 0.1 · 6283 ≈ 628 V/(A·s). No guessing. This is why ODrive and similar drives ask you to measure R and L first (their calibration routine injects current and identifies both) — then they compute current gains automatically.
Rule of thumb: set current-loop bandwidth to roughly 1/10 of the PWM frequency. At 20 kHz PWM, a ~2 kHz current loop is reasonable. Faster than ~1/5 and you risk instability from sampling and delay.
Anti-windup
When the voltage demand saturates against the bus, the integrator keeps accumulating error it cannot act on — integral windup — and when the saturation clears, the wound-up integral causes a big overshoot. Every real PI loop needs anti-windup: clamp or back-calculate the integrator so it doesn't accumulate during saturation. In a FOC voltage limiter, when sqrt(Vd²+Vq²) exceeds the ceiling, both axis integrators must be held/back-calculated, with the q-axis usually prioritized for torque.
Autotuning
Modern drives automate most of this. TI InstaSPIN identifies motor parameters and sets up FOC with minimal user input. ODrive runs a motor-calibration sequence (resistance, inductance, encoder offset, pole pairs). Industrial drives from Copley and Elmo have one-button autotuning that identifies the mechanical plant (inertia, friction, resonances) and sets velocity/position gains, often with notch filters for mechanical resonances.
The practical bring-up sequence
A safe order to bring up a new motor+drive combination:
1. Power stage check at low bus voltage / current limit. Confirm no shoot-through.
2. Motor parameter ID: measure phase resistance R and inductance L.
3. Encoder/sensor calibration: find pole pairs and the electrical angle offset
(align rotor to a known phase, record encoder reading).
4. Current (FOC) loop: set Kp/Ki from R, L. Command small Iq, verify smooth
torque and correct direction. Watch current waveforms if you can.
5. Velocity loop: with current loop trusted, close velocity. Tune for ~1/5 to
1/10 of current-loop bandwidth. Add inertia feedforward if known.
6. Position loop: close last, slowest. Add velocity feedforward.
7. Set protection limits (I2t, overtemp, overvoltage) BEFORE real loads.
8. Test under representative load, then under fault conditions (e-stop, stall).
Rule of thumb: never close the velocity loop until the current loop is verified, and never close the position loop until velocity is solid. Tune from the inside out, always.
The drive ecosystem: hobby vs industrial
The FOC algorithm is the same everywhere. What differs across the market is hardware quality, interfaces, certification, ruggedness, and price. Three tiers:
Hobby / robotics open ecosystem
- ODrive — open(-ish) high-performance dual-axis FOC controllers (ODrive 3.6, and the newer ODrive Pro / S1 / Micro). Strong at high-torque robotics and direct-drive joints; encoder-based FOC, CAN, good docs and community. Typical: 12–56 V, tens of amps continuous.
- Moteus (mjbots) — compact single-axis FOC controller designed for legged/dynamic robots, integrated magnetic encoder, CAN-FD, very high loop rates, sold with matching actuators. Excellent for quadrupeds and dynamic legged machines.
- VESC — originally an e-skateboard/e-bike controller, now a huge open-source FOC ecosystem (hardware + VESC Tool firmware). Wide voltage/current range, sensorless and sensored, enormous community, many clones (buyer beware on clone power-stage quality).
- SimpleFOC — an open-source Arduino/STM32 library plus reference driver boards. Not a product so much as a way to put real FOC on your own MCU. Great for learning and custom low/medium-power designs; performance depends entirely on your hardware.
Industrial servo drives
- Copley Controls — high-end servo drives (Accelnet, Xenus families), EtherCAT/CANopen, excellent tuning tools, strong in semiconductor/medical/automation.
- Elmo Motion Control — famously tiny, high-power-density "Gold" line servo drives (Gold Solo Whistle, etc.), EtherCAT, aerospace/robotics.
- Kollmorgen — AKD servo drive family, tightly integrated with their servo motors, industrial automation and robotics.
- Others worth knowing: Beckhoff (drives + EtherCAT ecosystem), Trinamic/ADI (TMC) for integrated stepper/BLDC driver ICs with onboard FOC (e.g., TMC4671 hardware FOC), and Texas Instruments InstaSPIN as a chip-level FOC solution.
Integrated motor + drive
A growing category: the drive lives inside the motor housing. Examples include mjbots actuators, many collaborative-robot joint modules, and "smart" servo actuators (Dynamixel-class, though those are often simpler control). Benefits: no motor-to-drive wiring (huge for EMI and assembly), compact, calibrated as a unit. Costs: harder to service, thermal coupling between drive and motor, less flexibility. See robot actuators for the actuator-level view.
| Drive | Tier | Typical voltage | Comms | Sensor | FOC | Best for |
|---|---|---|---|---|---|---|
| ODrive Pro / S1 | Hobby/robotics | 12–56 V | CAN, USB | Encoder (mag/optical) | Yes | High-torque robotics, direct drive |
| Moteus (mjbots) | Hobby/robotics | up to ~44 V | CAN-FD | Onboard magnetic | Yes | Legged/dynamic robots |
| VESC | Hobby/robotics | ~12–60+ V (variant) | CAN, UART, USB | Sensored + sensorless | Yes | E-mobility, makers, wide range |
| SimpleFOC | Library/DIY | Your design | Your choice | Your choice | Yes | Learning, custom designs |
| TMC4671 (ADI/Trinamic) | IC | Chip-level | SPI/Step-Dir | Many | Hardware FOC | Embedding FOC in a product |
| Copley Accelnet/Xenus | Industrial | up to ~400 V+ | EtherCAT, CANopen | Encoder, resolver | Yes | Automation, semicon, medical |
| Elmo Gold | Industrial | wide | EtherCAT, CANopen | Encoder, resolver | Yes | Aerospace, compact high power |
| Kollmorgen AKD | Industrial | 120–480 VAC | EtherCAT, etc. | Encoder, resolver | Yes | Industrial servo systems |
| TI InstaSPIN (C2000) | IC/SDK | Your design | Your choice | Sensorless (FAST) | Yes | Sensorless products |
Rule of thumb: if you're building a robot prototype or a small fleet, the open robotics drives give you 90% of the performance at 10–20% of the cost. If you need certified functional safety, deterministic EtherCAT motion across many axes, and a vendor to call at 2 a.m., pay for an industrial drive.
Communication and real-time interfaces
How does the drive get its commands, and how fast? This matters as much as the control loop, because a perfectly-tuned 20 kHz current loop is useless if commands arrive late or jittery.
Command interfaces, from simple to deterministic
- Analog torque/velocity command (±10 V): the old-school servo interface. The drive runs its own loops; an external motion controller feeds an analog setpoint. Simple, fast, but noise-prone and one wire per axis.
- Step/direction: a pulse train sets position increments (inherited from stepper drives). Common on CNC and lower-end servo drives. Simple, but open-loop in the command path and limited in bandwidth by pulse rate.
- CAN / CAN-FD: the robotics workhorse. ODrive, Moteus, and VESC all use CAN. Classic CAN tops out at 1 Mbit/s; CAN-FD pushes payloads and bitrates much higher (multi-Mbit/s data phase), which is why Moteus uses it for high-rate multi-joint robots. Multi-drop (one bus, many drives), robust, cheap. Not hard-real-time deterministic at the protocol level, but fine for many robots if you manage bus load.
- EtherCAT: the industrial gold standard for multi-axis motion. Deterministic, sub-microsecond synchronization across dozens of axes via distributed clocks, with cycle times down to tens of microseconds. This is what Copley, Elmo, Kollmorgen, and Beckhoff drives speak. If you need 32 synchronized axes updating every 250 µs, this is the answer. See industrial automation context in the real-time guide.
- Ethernet/IP, PROFINET, SERCOS, POWERLINK: other industrial real-time buses, vendor-dependent.
Where the loops run and at what rate
A crucial architectural question: which loops live in the drive, and which on the host?
- In most robotics and industrial setups, all three loops (current, velocity, position) run inside the drive, at the drive's high internal rate (current 10–40 kHz, velocity kHz, position sub-kHz). The host just streams setpoints (e.g., target position every 1 ms over EtherCAT/CAN). This keeps the fast loops local and deterministic regardless of host jitter.
- In some advanced robots, the outer loop (whole-body control, impedance) runs on the host at 0.5–2 kHz, streaming torque commands to drives running only the current loop. This demands a low-latency, low-jitter bus (CAN-FD or EtherCAT) and a real-time host. Legged-robot stacks often do this.
Rule of thumb: keep the current loop in the drive, always. Push only the loop you can afford to run at the bus rate up to the host, and only if your bus and host are genuinely real-time. For loop timing and determinism, see real-time control systems.
Protection and fault handling
A drive that can't protect itself and the motor is a fire and a destroyed gearbox waiting to happen. Protection is where "it works on the bench" becomes "it survives the field."
Overcurrent
- Hardware overcurrent trip: a comparator on the current-sense signal that shuts the gates off in nanoseconds to a microsecond, independent of firmware. This is the last line of defense against a short or a control fault. Non-negotiable on a real drive.
- Software current limit: the current loop's setpoint is clamped to
Imax, so under normal control you never command more than the FETs/motor can take.
I²t (thermal current limiting)
Motors and FETs tolerate brief overcurrent but not sustained. I²t protection models the heating: it allows, say, 2–3× rated current for a short window (a few seconds) for acceleration, then folds back to the continuous rating. This mirrors the physics — heating is proportional to I²·t. A drive without I²t either nuisance-trips on legitimate peaks or cooks the motor on sustained overload. Industrial drives model this carefully; good robotics drives (ODrive, Moteus) expose continuous and peak current limits that approximate it.
Overtemperature
Thermistors or onboard temp sensors on the FETs/heatsink, and ideally a motor thermistor, with foldback or shutdown thresholds. Power FETs derate hard with temperature; a drive that ignores temperature will silently lose capability or fail.
Overvoltage, regen, and braking
When a motor decelerates or is back-driven, it acts as a generator and pumps energy back into the bus. The bus voltage rises. If nothing absorbs that energy:
- A battery can usually absorb it (it just charges) — within its charge-current limits.
- A mains-rectified supply cannot sink current backward, so the bus capacitor voltage climbs until something trips or pops.
Two solutions:
- Brake (dump) resistor: a resistor switched across the bus by a "brake chopper" when voltage exceeds a threshold, burning the regen energy as heat. Standard on industrial drives and offered as an option on robotics drives. Size it for your worst-case deceleration energy.
- Regenerative drive: feeds energy back to the mains or battery. Efficient, more expensive, used in high-power and energy-conscious systems.
Rule of thumb: any drive that can decelerate a significant inertia, or hold a back-driven load (a vertical axis, a winch), needs a defined path for regen energy — a battery that can take it, a brake resistor, or a regen front end. "We'll figure out braking later" is how bus capacitors explode.
Fault handling
Beyond trips, a mature drive has defined fault states: encoder loss, phase loss/open, communication timeout (watchdog — if commands stop, stop the motor safely), DC-bus undervoltage, gate-driver fault, and a clean fault latch that requires an explicit reset. Safe-torque-off (STO) is a hardware safety input on industrial drives that disables the gates independently of firmware for functional-safety compliance.
Choosing a controller for your robot
Selection is mostly arithmetic and honesty about your loads. Work through it in this order — most bad choices are current/thermal errors made because someone fixated on features first.
1. Bus voltage
Pick a controller whose voltage range comfortably brackets your supply, including regen overshoot headroom. A 48 V system with regen can transiently see 55–60 V; choose a drive (and FETs) rated above that. Higher voltage means lower current for the same power (less I²R loss, thinner wires) but more switching stress and safety concern.
2. Current — continuous AND peak
This is where selections fail. You need:
- Continuous current matching your motor's continuous torque demand at the worst sustained operating point (with margin and at realistic temperature, not the datasheet's optimistic figure).
- Peak current for acceleration and transient torque. A drive's "peak" rating is meaningless without its duration — check the I²t window.
3. Sensor support
Match the drive to your feedback: incremental/absolute encoder type and protocol (ABI, SPI, SSI, BiSS), Hall, resolver, or sensorless. If you need zero-speed torque, you need an absolute or properly-calibrated sensor (see encoders).
4. Comms
CAN/CAN-FD for robotics multi-drop; EtherCAT for deterministic multi-axis industrial; step/dir or analog for simple retrofits; USB/UART for config. Make sure the protocol matches your host stack and update-rate needs.
5. Form factor and thermal
Board-level vs enclosed, integrated-in-motor vs separate, and crucially how you'll cool it. A 40 A drive on a 20 A heatsink is a 20 A drive. Account for ambient, airflow, and duty cycle.
| Application | Voltage | Continuous current | Sensor | Comms | Suggested tier/example |
|---|---|---|---|---|---|
| Quadruped/legged joint | 24–48 V | 10–40 A | Onboard magnetic abs. | CAN-FD | Moteus / ODrive S1 |
| Direct-drive robot arm joint | 24–56 V | 20–60 A | Absolute encoder | CAN / EtherCAT | ODrive Pro / Copley |
| Mobile-robot drive wheel | 24–48 V | 10–30 A | Hall + encoder | CAN | VESC / ODrive |
| E-bike / light EV | 36–72 V | 30–100 A | Hall + sensorless | CAN/UART | VESC (quality HW) |
| Industrial multi-axis machine | 230–480 VAC | per axis | Encoder/resolver | EtherCAT | Copley / Elmo / Kollmorgen |
| Drone propulsion | 12–52 V (LiPo) | per motor | Sensorless BEMF | DShot/CAN | BLDC ESC (six-step/FOC) |
| Embedding FOC in a product | Your design | Your design | Your choice | SPI/CAN | TMC4671 / TI C2000 InstaSPIN |
| Precision quiet actuator (low spd) | 12–48 V | 1–10 A | Absolute encoder | CAN | ODrive / TMC4671 |
Rule of thumb: size for the worst-case sustained thermal operating point, not the catalog peak. Then verify peak/acceleration is covered by the I²t window. Comms and form factor are last — they're easy to get right once the power and sensing are correct.
Frequently asked questions
What is the difference between an ESC and a FOC controller? "ESC" (Electronic Speed Controller) usually means a simple, often six-step/trapezoidal BLDC controller for drones and RC, optimized for cheap, high-speed open-loop-ish operation. A FOC controller runs Field-Oriented Control for smooth torque and precise closed-loop behavior. Many modern "ESCs" now run FOC (e.g., some drone ESCs, VESC), so the terms have blurred — the real question is whether the device does vector control with current feedback or simple six-step commutation.
Do I really need FOC, or is six-step good enough? If your load just needs to spin fast and a little torque ripple doesn't matter — a propeller, a fan, a pump — six-step is cheaper and perfectly fine. If you need smooth, controllable torque, low-speed or zero-speed operation, high efficiency, or quiet running — robot joints, servos, precision actuators — use FOC. Roughness, low-speed control, and torque accuracy are the deciding factors.
Why transform into the dq frame at all — why not just control the phase currents directly? Because in the stationary frame the target currents are sinusoids that move with the rotor, and PI controllers lag a moving target, losing accuracy as speed rises. The Park transform rotates into the rotor frame where, in steady state, the currents are constant DC values. A PI loop nails a DC setpoint with zero steady-state error. That conversion of AC control into DC control is the entire reason FOC exists.
What does Id = 0 mean and when should I not use it? Id is the current aligned with the rotor's magnet flux; for a surface-PM (non-salient) motor it produces no torque, so you set Id = 0 to put all current into torque (maximum torque per amp). You deviate from Id = 0 in two cases: field weakening (Id negative to spin above base speed), and salient/interior-PM motors where a small negative Id exploits reluctance torque for true MTPA.
How do I tune the current loop?
Measure motor phase resistance R and inductance L (most drives do this automatically). Then with pole-zero cancellation: Kp = L·ωc and Ki = R·ωc, where ωc is your target current-loop bandwidth in rad/s (pick roughly 1/10 of the PWM frequency). That gives a clean first-order closed loop with no guessing. Add anti-windup for when the voltage saturates.
Can I run FOC without an encoder? Yes — sensorless FOC estimates rotor angle from back-EMF using observers (sliding-mode, flux, Kalman) or TI's InstaSPIN FAST estimator. It works well above some minimum speed. The catch is zero and low speed, where back-EMF is too small to observe; you need open-loop forced start or high-frequency injection (HFI, salient motors only). If you need controllable torque at standstill, use a position sensor.
What switching frequency should I use? Common ranges: 8–20 kHz for IGBT/industrial, 20–40 kHz for low-voltage MOSFET robotics drives, >100 kHz for GaN. Higher means lower current ripple and more control bandwidth but more switching loss. A frequent default is to keep it ≥20 kHz (above audible) and set the current loop at ~1/10 of it. Match it to your motor inductance — low-inductance motors need higher PWM to keep ripple sane.
Why does my motor draw current and get hot but produce no torque? Almost always a rotor-angle problem: a wrong electrical-angle offset, miscounted pole pairs, swapped encoder direction, or a sensorless observer that hasn't locked. If θe fed to the Park transform is wrong, current goes into the d-axis (or worse) and dissipates as heat without making torque. Re-run encoder/commutation calibration and verify pole pairs.
What is dead-time and why does it matter? Dead-time is the brief interval (0.1–2 µs) where both switches in an inverter leg are off during a transition, preventing shoot-through (a destructive bus short). It's necessary, but it distorts the output voltage in a current-direction-dependent way, causing harmonics and torque ripple — especially near zero current. Good drives apply dead-time compensation in firmware. Use the minimum safe dead-time and compensate the rest.
What is SVPWM and why is it better than sine PWM? Space Vector PWM realizes a desired voltage vector by time-averaging the inverter's discrete switching states. Versus naive sinusoidal PWM it uses the DC bus about 15.5% more effectively (peak phase voltage up to Vdc/√3 instead of Vdc/2) by adding a common-mode/third-harmonic offset that cancels in the line-to-line voltages. More usable bus voltage means more speed and torque headroom from the same battery, plus generally lower harmonic distortion.
How do I handle regen / braking energy? When a motor decelerates or is back-driven it pumps energy into the DC bus, raising its voltage. A battery can usually absorb it within its charge limits; a rectified mains supply cannot, so you need a brake (dump) resistor with a chopper to burn the energy, or a regenerative front end to return it. Any drive moving significant inertia or holding a back-driven load needs a defined regen path, sized for worst-case deceleration energy, or the bus capacitor will overvoltage.
ODrive vs Moteus vs VESC — which should I pick? Roughly: Moteus for legged/dynamic robots needing compact single-axis drives with onboard encoders and CAN-FD at high rates. ODrive for higher-torque robotics, direct-drive joints, and dual-axis applications with strong docs. VESC for e-mobility and the widest open-source community and voltage/current flexibility (but vet clone hardware quality). All three do real FOC; the choice is about form factor, current/voltage range, comms, and ecosystem fit rather than the control algorithm.
Related guides
- Brushless DC Motors (BLDC) for Robotics: The Ultimate Guide
A robotics engineer's deep dive into brushless DC motors: Kv vs Kt, trapezoidal vs FOC commutation, sensored vs sensorless, gimbal/QDD actuators, datasheet math, and how to size a BLDC for a robot joint or drone.
- Drone & UAV Hardware: The Ultimate Guide
A UAV engineer's 2026 deep dive into drone hardware: airframes, BLDC motors and Kv, props, BLHeli_32/AM32 ESCs with DShot, Betaflight vs PX4 vs ArduPilot, sensor fusion, LiPo packs, thrust-to-weight, and how to size a multirotor.
- Stepper Motors & Drivers: The Ultimate Guide
An engineer-grade guide to stepper motors and drivers: how steps and microsteps really work, NEMA frame sizes, the torque-speed curve, resonance and missed steps, A4988 vs Trinamic TMC drivers, closed-loop steppers, and honest sizing math.
- Servo Motors: The Ultimate Guide
A deep, engineer-grade guide to servo motors: RC vs industrial vs smart serial servos, PWM and closed-loop control, datasheet specs, cascaded PID, sizing math, failure modes, and a real-product comparison table.
- Linear Motion Systems: Rails, Ball Screws & Linear Motors — The Ultimate Guide
A working engineer's guide to linear motion: profile rails and recirculating-ball guides, ball/lead/roller screws, belt and rack drives, and linear motors — with preload classes, accuracy grades, life and critical-speed math, real parts, and a selection workflow.
- Robot Wiring, Connectors & Slip Rings: The Ultimate Guide
A practical engineering guide to robot wiring: wire gauge & ampacity, continuous-flex cable (Igus chainflex) vs standard, e-chains, M8/M12 connectors, EMI shielding & grounding, slip rings, and the flex-fatigue failures that quietly kill robots.