On this page
Closed-Loop Control (Voltage-Based Torque)
⏱️ ~15 minutes
Now that you have a working motor and sensor, test closed-loop Field Oriented Control (FOC). This is the simplest closed-loop mode: torque control using voltage.
What’s Different From Open-Loop?
- Open-loop: Spins motor at estimated angle, no feedback
- Closed-loop: Uses sensor feedback to control torque precisely
- Advantage: Stable, responsive, works across speed ranges
See motion control documentation for more details on control types and how/when to switch between them.
Select Your Motor + Driver + Sensor Combination
Sketch Template BLDC + 3PWM Driver + Encoder Stepper + 2PWM Driver + Encoder
Here is a template with TODO entries you can customize:
#include <SimpleFOC.h>
// TODO: motor instance
// TODO: driver instance
// TODO: sensor instance
// instantiate the commander
Commander command = Commander(Serial);
void doMotor(char* cmd) { command.motor(&motor, cmd); }
void setup() {
// use monitoring with serial
Serial.begin(115200);
// enable more verbose output for debugging
// comment out if not needed
SimpleFOCDebug::enable(&Serial);
// TODO: sensor config
// init the sensor
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// TODO: driver config
// init the driver
if(!driver.init()){
Serial.println("Driver init failed!");
return;
}
// link driver
motor.linkDriver(&driver);
// TODO: motor voltage alignment config
// This voltage is used to align sensor with motor
motor.voltage_sensor_align = 3; // start conservatively
// set motion control loop to be used
motor.torque_controller = TorqueControlType::voltage;
motor.controller = MotionControlType::torque;
// use monitoring with serial
// comment out if not needed
motor.useMonitoring(Serial);
// initialize motor
if(!motor.init()){
Serial.println("Motor init failed!");
return;
}
// align sensor and start FOC
if(!motor.initFOC()){
Serial.println("FOC init failed!");
return;
}
// set the initial motor target
motor.target = 2; // Volts
// add target command M
command.add('M', doMotor, "Motor");
Serial.println(F("Motor ready."));
Serial.println(F("Set the target using serial terminal and command M:"));
_delay(1000);
}
void loop() {
// main FOC algorithm function
motor.loopFOC();
// Motion control function
motor.move();
// user communication
command.run();
}
Key Concepts
Sensor Alignment (motor.voltage_sensor_align)
During motor.initFOC(), the motor briefly spins to determine the sensor’s electrical zero position. The voltage used for this determines the alignment current.
- Too low (~0.5V): May not rotate enough to align
- Safe range (2-5V): Works for gimbal and small motors
- Too high: Can draw excessive current
- Start with 3V and adjust if needed
Motion Control Types
Once closed-loop works, you can switch modes with serial commands:
MC0 = Torque mode
MC1 = Velocity mode
MC2 = Angle mode
Then use M<value> to set target:
- Torque:
M2= 2 Volts - Velocity:
M6.28= 1 rotation/second - Angle:
M3.14= half rotation
Testing
✓ What to expect
- During setup, motor will briefly spin (sensor alignment)
- Serial output:
Motor ready.(notFOC init failed!)- Motor smoothly responds to voltage changes via serial
- Motor feels firm (resistance) when you try to hold it
Basic Test
- Open serial terminal (115200 baud)
- Type
M0- motor should go to zero torque (no resistance) - Type
M1- motor should produce light torque (you can feel it) - Type
M2- motor should produce more torque - Type
M0again - torque disappears
Velocity Control Test
- Type
MC1to switch to velocity modeIf motor unstable (or very noisy) it will need velocity PI tuning (see troubleshooting below)
- Type
M6.28to spin 1 rotation/second - Type
M0to stop - Motor should accelerate smoothly and maintain speed
Angle Control Test
- Type
MC2to switch to angle modeIf motor unstable (or very noisy) it will need angle P tuning (see troubleshooting below)
- Type
M3.14to rotate half turn - Motor should move to that angle and hold it
Troubleshooting
FOC init failed?
- Check sensor is working (from previous test)
- Sensor alignment voltage too low: try increasing
motor.voltage_sensor_align - Pole pair number wrong: verify from open-loop test
- Sensor not aligned: see serial debug output for hints
Motor spins but is unstable/noisy?
- Motor/driver connection loose: verify wiring
- Velocity PI tuning needed: decrease
motor.PID_velocity.Pandmotor.PID_velocity.I- see full tuning guide in Motion Control documentation - Angle P tuning needed: decrease
motor.P_angle- see full tuning guide in Motion Control documentation
Motor doesn’t spin at all?
- Check that driver initialized (look for
Driver init failed!) - Verify sensor is reading (check debug output)
- Pole pair number wrong: double-check from previous test
- Try increasing
motor.voltage_sensor_alignto 1-2V minimum
Current too high during alignment?
- Reduce
motor.voltage_sensor_align - Try setting it with the phase resistance in mind:
- If you motor has a phase resistance of 0.5 Ohms, then 3V will draw 6A during alignment (I = V/R). If this is too high for your motor or driver, reduce the voltage accordingly.
- If resistance unknown, try measuring it - measuring guide
In torque mode, motor spins faster in one direction than the other?
- This is usually the issue with the sensor alignment. Try increasing
motor.voltage_sensor_alignto ensure it fully aligns.
Some specific issues
- AS5600 magnet polarisation issue - example issue - need to replace the magnet
Still having issues?
Browse throught the SimpleFOC community forum, there might already be a solution for your specific hardware or issue. Also don’t hesitate to ask for help there!
What’s Next?
You now have a fully functional voltage based control system! If the perfrormance of this control mode is sufficient for your application, you can start building on top of it with motion profiles, trajectory planning, and higher level feedback loops.
For Robotics/Automation
- See Motion Control docs
- Implement feedback loops in your application code
For Precision Applications
- Tune PID parameters for your motor
- Use angle mode for position control
- See PID tuning guide
For Learning
- Explore the SimpleFOC library examples
- Read about FOC theory and source code
- For debugging, monitoring, and communication docs, see Communication and Debugging sections
More advanced control schemes
With voltage-based torque control working, you have a solid foundation! For more advanced control, current sensing or motor model based current estimation can improve overall performance a lot.
Once this works:
- You don’t have current sensing? :
Estimated current control setup guide - You have current sensing? :
FOC control setup guide
Relevant Documentation
- Motion control documentation
- Torque control documentation
- Current sensing documentation
- Practical guides
- Digging deeper