Field-Oriented Control for BLDC Motors: SimpleFOC, Current Sensing, and Smooth Motor Control Beyond ESCs
If you've built a project around a brushless motor and an off-the-shelf ESC, you've been using trapezoidal (six-step) commutation — cheap, simple, and good enough for props and wheels, but it drives a motor in coarse voltage steps that produce audible torque ripple, waste efficiency, and give you almost no useful information about the motor's actual state. Field-Oriented Control (FOC) drives the same motor with smoothly varying sinusoidal currents aligned to the rotor's actual magnetic field, and the payoff is real: near-silent operation, higher efficiency, and — critically for robotics — the ability to command precise torque, velocity, or position rather than just "go" and "stop." This guide covers what FOC actually does differently, the hardware you need, and how to get a SimpleFOC-based setup running on an ESP32 or STM32.
Trapezoidal vs. Sinusoidal vs. FOC
Control MethodHow It Drives the MotorTorque RippleEfficiencyRequires Feedback? Trapezoidal (standard ESC)Six discrete commutation steps, full voltage per stepHighLowerNo (or Hall-only) Sinusoidal (open-loop)Smooth sine drive, no feedback on rotor positionMediumMediumNo FOC (closed-loop)Sine drive continuously aligned to measured rotor angleVery lowHighestYes — encoder or sensorless estimationThe Core Idea, Without the Full Derivation
A three-phase motor's currents are, mathematically, three sine waves 120 degrees apart. FOC uses two coordinate transforms — the Clarke transform (three phase currents into a two-axis stationary frame) and the Park transform (that stationary frame rotated into a frame that spins with the rotor) — to turn those three time-varying sine waves into two DC-like quantities: Id (the current component that does no useful work, ideally driven to zero) and Iq (the current component that directly produces torque). Once your currents are expressed this way, controlling torque becomes a straightforward PI control loop on Iq, exactly like regulating a DC quantity — which is the entire point. You don't need to hand-derive these transforms to use FOC; libraries like SimpleFOC implement them for you. Understanding what Id and Iq represent, though, is what makes tuning make sense instead of feeling like magic numbers.
Hardware You'll Need
- A FOC-capable driver board. The SimpleFOC ecosystem's own boards (SimpleFOCShield, SimpleFOCMini) are the easiest path, pairing a three-phase gate driver with onboard current sense. Generic BLDC gate driver ICs like the DRV8302 or DRV8305 work too if you're building your own board.
- A rotor position sensor. A magnetic angle encoder like the AS5600 (I2C, cheap, good enough for most maker projects) or AS5048A (SPI, faster and more precise) mounted over a diametrically-magnetized magnet on the motor shaft gives you the rotor angle FOC needs. Sensorless FOC (estimating rotor position from back-EMF, no physical sensor) exists and is what most commercial ESCs use at speed, but it performs poorly at low RPM and is a much harder tuning problem — start with a physical encoder.
- Current sensing. Either inline shunt resistors with a differential amplifier per phase, or a driver IC with integrated current sense (the DRV83xx family again). This is what lets you measure Id and Iq directly rather than estimating them.
- A microcontroller with the right peripherals. ESP32 and STM32 (particularly the STM32G4 family, which has hardware built specifically for motor control) are the two platforms SimpleFOC supports well, since FOC's control loop needs to run at several kHz with tight, deterministic timing — this is not a job for software-timed PWM on an 8-bit AVR.
Getting a SimpleFOC Setup Running
- Verify motor phase and encoder wiring separately before combining them. Confirm your driver can spin the motor open-loop (no feedback) first, and confirm your encoder reports a clean, monotonic angle as you turn the shaft by hand, before you ever close the loop.
- Run SimpleFOC's built-in motor and sensor calibration. The library's initFOC() routine automatically detects the electrical offset between your encoder's zero point and the motor's actual electrical angle, and detects motor direction — this replaces what used to be manual, error-prone calibration in older FOC implementations.
- Start in velocity or angle control mode with conservative PI gains. SimpleFOC exposes separate PID loops for current (innermost), velocity, and angle (outermost) — tune from the inside out, starting with current loop gains reasonable for your driver and motor's electrical characteristics, before touching the outer loops.
- Watch current draw closely while tuning. Excessive gain on any loop shows up first as audible motor whine or vibration, then as current spikes — back off gain before you cook a driver IC or a winding.
Where FOC Actually Earns Its Complexity
Robot joints, camera gimbals, haptic feedback devices, and any application needing accurate low-speed torque control are where FOC's benefits over a standard ESC are worth the extra build complexity — a gimbal driven by a plain ESC is unusable, while the same motor under FOC velocity control is silky smooth down to a near standstill. For a basic drone or RC car, a standard ESC remains the right tool; don't reach for FOC there just because it's the more sophisticated option; the added encoder, current-sense hardware, and tuning time only pay for themselves when you actually need the precision.
Safety Notes
FOC systems commonly run higher continuous current through the driver stage than a hobby ESC sees in normal use, especially during tuning when gains are wrong and the motor is fighting itself — watch driver IC temperature and motor winding temperature during early testing, and add current limiting in firmware before you leave anything running unattended. As with any BLDC project, secure the motor and rotor before power-up; an unexpectedly high gain setting can spin a shaft hard and fast with no warning.
FOC is one of those techniques that looks intimidating from the math and turns out to be very approachable once you have working example code to build from — SimpleFOC's documentation and example projects will get a basic closed-loop setup running in an afternoon. From there, the door opens to genuinely precise motor control for robotics projects that a standard ESC could never deliver.
Related Guides
- Brushless DC Motors and ESCs for Makers: KV Rating, Sensored vs Sensorless, and Driving with Arduino/ESP32
- Raspberry Pi Robot Car: Motors, Chassis, Control
- Line Follower / Obstacle Avoidance Robot
- Getting Started with ROS2 on Raspberry Pi for Robotics
- CAN Bus for Makers: ESP32 TWAI and MCP2515 Wiring, Termination, and Message Design
- Real-Time Linux on Raspberry Pi: PREEMPT_RT for Low-Latency GPIO and Motor Control
- Current Sensing for Makers: Shunt Resistors, INA219/INA226, and ACS712 Hall-Effect Sensors
- Driving Many Servos with a PCA9685 PWM Driver: I2C Wiring for Raspberry Pi and ESP32 Robotics