The motor in the drawer
There is a small brushless motor that has followed me through four apartments, three cities and one career change. I pulled it out of a broken VCR sometime around 2003, decided it was obviously going to power something important, and then put it in a drawer for two decades. I never threw it out. Engineers don't throw out motors.
This year I finally decided to make it spin — properly, under field-oriented control, not just buzzing on a battery. It was the cleanest possible excuse to get back into robotics after years away. One motor, one driver, one weekend.1
The plan was deliberately small. No robot yet. No legs, no wheels, no grand chassis. Just closed-loop velocity control on a single salvaged BLDC, and a serial monitor telling me the truth.
Field-oriented control, briefly
A brushless motor is just three coils and a spinning magnet. The hard part is timing: you have to push current through the right coils at the right instant, relative to where the rotor actually is. Get it wrong and the motor cogs, heats up, and goes nowhere.
Field-oriented control (FOC) solves this elegantly. It transforms the three messy phase currents into two clean, rotor-aligned axes — d (flux) and q (torque) — runs simple PI controllers there, and transforms the result back into three phase voltages. You command torque directly and the math handles the commutation.
The loop runs thousands of times a second. Conceptually it looks like this:
"You stop thinking about coils, and start thinking about torque."
SimpleFOC implements every box in that diagram for you.2 My job was mostly wiring, and telling it the truth about my hardware.
Wiring it up
The bench is deliberately boring: an ESP32 for brains, a DRV8302 gate driver to push real current, and an AS5600 magnetic encoder glued to the shaft so the controller always knows the rotor angle. A diametric magnet on the shaft end, an I²C bus, and six PWM lines.
One detail that cost me an evening: the encoder and the logic side must share a ground with the power stage, or the angle readings wander and FOC quietly falls apart.3
First light
Here is the entire sketch that brought it to life. SimpleFOC keeps it almost embarrassingly short — link a sensor, link a driver, pick a control mode, and call initFOC().
#include <SimpleFOC.h>
// 11 pole-pairs, salvaged ~2003. Pole count found by experiment.
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(25, 26, 27, 12);
// AS5600 magnetic encoder over I2C — the rotor's source of truth
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
void setup() {
Serial.begin(115200);
sensor.init();
motor.linkSensor(&sensor);
driver.voltage_power_supply = 12;
driver.init();
motor.linkDriver(&driver);
motor.controller = MotionControlType::velocity;
motor.PID_velocity.P = 0.2f; // tuned on the bench, by ear
motor.PID_velocity.I = 2.0f;
motor.voltage_limit = 6; // be gentle with a 20-year-old
motor.useMonitoring(Serial);
motor.init();
motor.initFOC(); // align sensor, find electrical zero
Serial.println(F("ready."));
}
void loop() {
motor.loopFOC();
motor.move(6.28); // ~1 rev/s
motor.monitor();
}
The one parameter I had to discover was the pole-pair count — the motor came with no datasheet, no markings, nothing. So I guessed, watched it cog, and adjusted until initFOC() reported a clean alignment.
Telemetry & first spin
Upload, open the serial monitor at 115200 baud, and hold your breath. This is the moment twenty years had been building toward:
It spun on the first genuine try — and twenty years collapsed into one quiet click. Logging the velocity against a step command shows the PI controller settling in well under 200 ms with barely any overshoot:
And because torque control is what FOC is really for, here is measured torque against commanded current — the satisfyingly straight line that means commutation is actually working:
What's next
One motor spinning under closed-loop velocity is not a robot. But it is the single hardest primitive in robotics, and now I have it on the bench, reproducible, logged. The next entries write themselves: closed-loop position control, then two motors and a five-bar linkage, then — finally — a leg.
Twenty years is a long time to leave a motor in a drawer. It turns out it was just waiting for the right weekend.
References & Links
- SimpleFOC — Arduino field-oriented control librarydocs.simplefoc.com
- DRV8302 three-phase gate driver — datasheetti.com · DRV8302
- AS5600 12-bit magnetic position sensorams-osram.com
- A primer on field-oriented control & the Park/Clarke transformstechnical note
- Nova Eletrônica — archived issues (the reason this looks like this)archive
- Finding pole-pair count without a datasheetbench note