Hello everyone,
I’ve been trying for weeks to get SimpleFOC working in MotionControlType::angle mode, but I’m not getting the correct motor behavior and have already tried all the solutions I found on this forum.
I’m really asking for help to figure out what the issue is.
I have:
- B-G431B-ESC1
- A lab power supply set to output 12V and 0.7A
- A 2807 1300KV BLDC motor with 7 pole pairs
- An AS5048A encoder connected in PWM mode
- Arduino IDE 2.0, where the STM32 Discovery board with part number B-G431B-ESC1 is available on COM4
- Simple FOC library version 2.3.4
In the sketch provided below, the mode is set to MotionControlType::angle, and the motor should rotate to 90 degrees and return to 0 degrees every 2 seconds.
However, depending on the motor’s initial position, it either moves to an incorrect angle, doesn’t move at all, or exhibits unstable jittering.
Interestingly, the motor holds its position relative to some angle, but switching angles doesn’t happen.
Somehow, the algorithm does not move the motor to the specified Target angle, even though both the Angle encoder and Angle shaft differ from the set value.
Here’s a video of the incorrect behavior MotionControlType::angle https://youtu.be/5b5FqBA_Vbc
Here’s a photo of the wiring:
I checked and separately output the encoder readings to the serial port, and if I’m not mistaken, the direction and angle are correct. When I rotate it by hand, the value changes within 3.14 radians per rotation.
In motor.controller = MotionControlType::velocity mode, the behavior is also incorrect: the motor holds its position but doesn’t rotate or doesn’t resist at all.
In motor.controller = MotionControlType::velocity_openloop mode, everything works successfully, and despite the rapid temperature rise of the MOSFETs, the rotation is stable and consistent.
Here’s a video of the correct behavior MotionControlType::velocity_openloop https://youtu.be/IIp-zh_hLyQ
All parameters are always the same; I only change motor.controller.
Here’s the sketch and Serial monitor data:
#include <SimpleFOC.h>
float targetAngle = 0; // start angle (0 rad)
bool moveTo90 = true; // Flag for switching between 0 and 90 degrees
unsigned long lastSwitchTime = 0;
double temp = 0;
unsigned long time_stamp = 0;
BLDCMotor motor = BLDCMotor(7, 0.35, 1300); // 2807 : 7 poles pairs, 0.35 16 , 1300 KV
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
MagneticSensorPWM sensor = MagneticSensorPWM(A_HALL1, 1, 1024); // PWM mode , encoder on A_HALL1
void doPWM() { sensor.handlePWM(); }
void setup() {
Serial.begin(115200);
pinMode(A_TEMPERATURE, INPUT);
// init sensor
sensor.init();
sensor.enableInterrupt(doPWM);
motor.linkSensor(&sensor);
// init driver
driver.voltage_power_supply = 12;
driver.voltage_limit = 12;
driver.pwm_frequency = 30000;
driver.init();
motor.linkDriver(&driver);
// 🔧 velocity settings PID
motor.PID_velocity.P = 0.1; // Increase if the motor is sluggish.
motor.PID_velocity.I = 0; // Eliminates speed error
// motor.PID_velocity.D = 0.0001; // Smooths out oscillations
motor.PID_velocity.output_ramp = 300; // Smooth acceleration
// Speed filter (reduces noise)
motor.LPF_velocity.Tf = 0.01;
// ⚠️ Limits
motor.velocity_limit = 300; // Max. speed (rad/s)
motor.voltage_limit = 6; // Voltage
motor.current_limit = 2.0; // Max. current (A)
motor.controller = MotionControlType::angle;
// motor.controller = MotionControlType::angle;
// motor.controller = MotionControlType::velocity_openloop;
motor.foc_modulation = FOCModulationType::SinePWM;
motor.sensor_direction = Direction::CW;
// Monitoring in Serial
motor.useMonitoring(Serial);
// init FOC
motor.init();
if (motor.initFOC()) {
Serial.println("FOC OK! The motor is ready.");
Serial.print("Zero Electric Angle: "); Serial.println(motor.zero_electric_angle);
Serial.print("Direction: "); Serial.println(motor.sensor_direction == Direction::CW ? "CW" : "CCW");
} else {
Serial.println("FOC Error!");
while (1);
}
}
void loop() {
motor.loopFOC();
// Automatic angle switching every 2 seconds (2000 ms)
if (millis() - lastSwitchTime > 2000) {
lastSwitchTime = millis();
if (moveTo90) {
targetAngle = 1.57; // 90 degrees (π/2 radians)
Serial.println("Moving to 90 degrees...");
} else {
targetAngle = 0.0; // Return to 0 degrees
Serial.println("Moving back to 0 degrees...");
}
moveTo90 = !moveTo90; // invert Flag
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // BLinking LED
}
// Motor control
motor.move(targetAngle);
// Data print every 1 second (1000 ms)
if(millis()-time_stamp > 1000) {
temp = map(analogRead(A_TEMPERATURE),0,1024,-49,125);
Serial.print("Temperature: "); Serial.print(temp); Serial.print(" degrees ");
Serial.print(" | Angle move: "); Serial.print(targetAngle);
Serial.print(" | Angle encoder: "); Serial.print(sensor.getAngle());
Serial.print(" | Angle shaft: "); Serial.print(motor.shaftAngle());
Serial.print(" | Velocity: "); Serial.print(motor.shaftVelocity());
Serial.print(" | Voltage q: "); Serial.println(motor.voltage.q);
time_stamp = millis();
}
}
Serial Monitor
15:16:28.653 → Temperature:MOT: Monitor enabled!
15:16:29.579 → MOT: Init
15:16:30.090 → MOT: Enable driver.
15:16:30.585 → MOT: Align sensor.
15:16:30.585 → MOT: Skip dir calib.
15:16:31.276 → MOT: Zero elec. angle: 1.93
15:16:31.482 → MOT: No current sense.
15:16:31.482 → MOT: Ready.
15:16:31.482 → FOC OK! The motor is ready.
15:16:31.482 → Zero Electric Angle: 1.93
15:16:31.526 → Direction: CW
15:16:31.526 → Temperature: 19.00 degrees | Angle move: 0.00 | Angle encoder: 3.87 | Angle shaft: 3.87 | Velocity: -0.07 | Voltage q: -0.11
15:16:31.572 → Moving to 90 degrees…
15:16:32.491 → Temperature: 20.00 degrees | Angle move: 1.57 | Angle encoder: 3.97 | Angle shaft: 3.97 | Velocity: -2.58 | Voltage q: -0.70
15:16:33.522 → Temperature: 21.00 degrees | Angle move: 1.57 | Angle encoder: 3.98 | Angle shaft: 3.98 | Velocity: 2.95 | Voltage q: -0.70
15:16:33.569 → Moving back to 0 degrees…
15:16:34.543 → Temperature: 21.00 degrees | Angle move: 0.00 | Angle encoder: 3.98 | Angle shaft: 3.98 | Velocity: 0.25 | Voltage q: -0.70
15:16:35.542 → Temperature: 22.00 degrees | Angle move: 0.00 | Angle encoder: 3.97 | Angle shaft: 3.97 | Velocity: -0.16 | Voltage q: -0.70
15:16:35.589 → Moving to 90 degrees…
15:16:36.510 → Temperature: 23.00 degrees | Angle move: 1.57 | Angle encoder: 3.97 | Angle shaft: 3.97 | Velocity: -0.10 | Voltage q: -0.70
15:16:37.515 → Temperature: 24.00 degrees | Angle move: 1.57 | Angle encoder: 3.96 | Angle shaft: 3.96 | Velocity: -0.45 | Voltage q: -0.70
15:16:37.548 → Moving back to 0 degrees…
15:16:38.565 → Temperature: 24.00 degrees | Angle move: 0.00 | Angle encoder: 3.98 | Angle shaft: 3.98 | Velocity: 0.33 | Voltage q: -0.70
15:16:39.525 → Temperature: 25.00 degrees | Angle move: 0.00 | Angle encoder: 3.98 | Angle shaft: 3.98 | Velocity: 4.02 | Voltage q: -0.70
15:16:39.567 → Moving to 90 degrees…
15:16:40.530 → Temperature: 25.00 degrees | Angle move: 1.57 | Angle encoder: 3.97 | Angle shaft: 3.97 | Velocity: -0.07 | Voltage q: -0.70
15:16:41.535 → Temperature: 26.00 degrees | Angle move: 1.57 | Angle encoder: 3.97 | Angle shaft: 3.97 | Velocity: 5.00 | Voltage q: -0.70