I have SimpleFOC setup of
- 5010 BLDC Motor (7 Pole Pair, 360KV)
- B-G431B-ESC1 Driver
- AS5600 Sensor
I am trying to do Position control with Voltage Control mode.
The issue I am facing is that the motor is going to target position 6/10 times,
rest 4/10 times it just doesn’t move after entering target in the terminal and then when I give just a little push to motor with my finger, it comes to the target angle by itself.
the resisting force by motor is felt very weak on my fingers.
It is consuming so less voltage and current to apply torque to comeback to it target position while I have entered in the code that use full 12Volts.
What Should I change for it to apply more torque.
In the closeloop velocity voltage control test, the PID value were working properly was
motor.PID_velocity.P = 0.1;
motor.PID_velocity.I = 2.0;
motor.PID_velocity.D = 0.0;
Now, in close loop voltage based position control, it gives a good results than Previous values.
motor.PID_velocity.P = 1.2; ( increasing above 1.2 it start oscillating)
motor.PID_velocity.I = 40.0;
motor.PID_velocity.D = 0.0;
Increasing I value above 50 it starts little bit overshooting, but start no improvement torque.
The force I fee in fingers by motor has no difference.
I am from a mechanical background and have limited electronics/control knowledge, please correct me if I am misunderstanding something.
I have attached my code, terminal output, and a video showing the issue. Any suggestions would be greatly appreciated!
PlatformIO.ini -
[env:disco_b_g431b_esc1]
platform = ststm32
board = disco_b_g431b_esc1
framework = arduino
monitor_speed = 115200
build_flags =
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D PIO_FRAMEWORK_ARDUINO_NANOLIB_FLOAT_PRINTF
-D PIO_FRAMEWORK_ARDUINO_USB_HIGHSPEED_FULL_MODE
lib_deps =
https://github.com/simplefoc/Arduino-FOC
simplefoc/SimpleFOCDrivers@^1.0.9
Main -
#include <Arduino.h>
#include <SimpleFOC.h>
#include <Wire.h>
// ---------------- I2C ----------------
TwoWire Wire1(PB7, PB8);
MagneticSensorI2C sensor(AS5600_I2C);
// ---------------- Motor ----------------
BLDCMotor motor = BLDCMotor(7, 0.21f, 360); // pole pairs, phase resistance, KV
// ---------------- Driver ----------------
BLDCDriver6PWM driver(
A_PHASE_UH, A_PHASE_UL,
A_PHASE_VH, A_PHASE_VL,
A_PHASE_WH, A_PHASE_WL
);
// ---------------- Control Variables ----------------
float target = 0.0;
float zero_offset = 0.0;
bool motor_enabled = false;
// ---------------- Commander ----------------
Commander command = Commander(Serial2);
// ---------------- Debug ----------------
unsigned long lastPrint = 0;
int printInterval = 500;
// ==========================================================
// ---------------- COMMANDS ----------------
// ==========================================================
void doTarget(char* cmd) {
float deg = atof(cmd);
target = deg * _PI / 180.0;
Serial2.print("Target(deg): ");
Serial2.println(deg);
}
void doZero(char* cmd) {
zero_offset = motor.shaftAngle();
Serial2.println("Zero position SET!");
}
void doEnable(char* cmd) {
motor_enabled = true;
// Sync target → prevents jerk
target = motor.shaftAngle() - zero_offset;
Serial2.println("Motor ENABLED");
}
void doDisable(char* cmd) {
motor_enabled = false;
motor.move(0);
Serial2.println("Motor DISABLED");
}
// Voltage = torque control
void doTorque(char* cmd) {
command.scalar(&motor.voltage_limit, cmd);
}
// Limits
void doVelocity(char* cmd) {
command.scalar(&motor.velocity_limit, cmd);
}
// PID tuning
void doVP(char* cmd) { command.scalar(&motor.PID_velocity.P, cmd); }
void doVI(char* cmd) { command.scalar(&motor.PID_velocity.I, cmd); }
void doVD(char* cmd) { command.scalar(&motor.PID_velocity.D, cmd); }
void doAP(char* cmd) { command.scalar(&motor.P_angle.P, cmd); }
// ==========================================================
// ---------------- SETUP ----------------
// ==========================================================
void setup() {
Serial2.begin(115200);
delay(1000);
Serial2.println("==== CLEAN ACTUATOR CONTROL ====");
// I2C
Wire1.begin();
sensor.init(&Wire1);
motor.linkSensor(&sensor);
// Driver
driver.voltage_power_supply = 12;
driver.pwm_frequency = 20000;
if (!driver.init()) {
Serial2.println("Driver init failed!");
return;
}
motor.linkDriver(&driver);
// ---------------- CONTROL MODE ----------------
motor.torque_controller = TorqueControlType::voltage;
motor.controller = MotionControlType::angle;
// ---------------- LIMITS ----------------
motor.voltage_limit = 12.0;
motor.velocity_limit = 25;
// ---------------- ALIGNMENT ----------------
motor.voltage_sensor_align = 1.5; // voltage to apply to the motor for sensor alignment RANGE: [0, supply voltage]
motor.sensor_direction = Direction::CCW;
// ---------------- VELOCITY LOOP (MOST IMPORTANT) ----------------
motor.PID_velocity.P = 1.2;
motor.PID_velocity.I = 40.0;
motor.PID_velocity.D = 0.02;
// Allow fast torque response
motor.PID_velocity.output_ramp = 1000;
// Filtering
motor.LPF_velocity.Tf = 0.01;
// ---------------- ANGLE LOOP ----------------
motor.P_angle.P = 50.0;
motor.LPF_angle.Tf = 0.01;
// ---------------- MONITOR ----------------
motor.useMonitoring(Serial2);
motor.monitor_downsample = 100;
// ---------------- INIT ----------------
if (!motor.init()) {
Serial2.println("Motor init failed!");
return;
}
if (!motor.initFOC()) {
Serial2.println("FOC init failed!");
return;
}
motor_enabled = false;
// ---------------- COMMANDS ----------------
command.add('T', doTarget);
command.add('Z', doZero);
command.add('E', doEnable);
command.add('X', doDisable);
command.add('C', doTorque);
command.add('V', doVelocity);
command.add('P', doVP);
command.add('I', doVI);
command.add('D', doVD);
command.add('A', doAP);
Serial2.println("====== READY ======");
Serial2.println("Z → set zero");
Serial2.println("E → enable");
Serial2.println("X → disable");
Serial2.println("T <deg> → move");
Serial2.println("C <V> → torque");
delay(1000);
}
void loop() {
motor.loopFOC();
if (motor_enabled) {
// Correct usage (no hacks)
motor.move(target + zero_offset);
}
command.run();
// -------- Debug --------
if (millis() - lastPrint > printInterval) {
float angle = motor.shaftAngle() - zero_offset;
Serial2.print("Target: ");
Serial2.print(target * 180.0 / _PI);
Serial2.print(" | Angle: ");
Serial2.print(angle * 180.0 / _PI);
Serial2.print(" | Vel: ");
Serial2.print(motor.shaftVelocity());
Serial2.print(" | Volt: ");
Serial2.print(motor.voltage.q);
Serial2.print(" | Enabled: ");
Serial2.print(motor_enabled);
Serial2.println();
lastPrint = millis();
}
motor.monitor(); // Print target angle, Voltage, velocity, current angle
}
Outputs-

Thanks, dekutree64. Got it. I'll keep motor.voltage_limit below 6 and experiment with different P and I values. Initially, I increased volt_limit above 3 to get more torque, but it didn't help. The heating occurs only in closed-loop velocity control at different RPMs. The maximum current is about 0.5 A, and the motor gets hot after 10–15 minutes. But in Voltage based Position control my motor or driver never gets hot. I've seen online same motor work in volt control with a DRV8308 board. In my case it control works, but the torque is too low to overcome the motor's magnetic poles.
– SachinK