Hi there, I recently switched to STM32-NUCLEO for work on FOC with BLDC. After I got things up and running, I noticed that Even at motor.voltage_limit=0 (0 commanded voltage to motor), I was drawing higher than expected current from the battery. I checked the U, V, W phases and found that the “W” phase has a shift from the other phases.
// PHASE U=GPIO9, V=GPIO5, W=GPIO6, En=GPIO8
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
I checked the GPIO output driving the phase, and sure enough, while the U and V outputs are in perfect sync, the W phase (driving by GPIO#6) is shifted by quite a bit (see below). I tried switching from GPIO#6 to another GPIO, and the problems follows to whichever GPIO I choose.
Scope trace of GPIO phase outputs
driver.voltage_power_supply = 12;
driver.voltage_limit = 12;
motor.voltage_limit = 0
YELLOW=U and V phase drive (GPIO 5,9)
BLUE = W phase drive (GPIO 6)
#include <SimpleFOC.h>
//#define CURSENS
// encoder instance
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
BLDCMotor motor = BLDCMotor(7, 1, 2500);
// PHASE U V W En
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
#ifdef CURSENS
// inline current sensor instance
InlineCurrentSense current_sense = InlineCurrentSense(0.01f, 50.0f, A0, A2, _NC);
#endif
// commander communication instance
Commander command = Commander(Serial);
// void doMotor(char* cmd) { command.motor(&motor, cmd); }
void doTarget(char* cmd) {command.scalar(&motor.target, cmd);}
void doLimit(char* cmd) {command.scalar(&motor.voltage_limit, cmd);}
void doMotor(char* cmd) { command.motor(&motor, cmd); }
void setup() {
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.voltage_limit = 12;
driver.init();
// link driver
motor.linkDriver(&driver);
// link current sense and the driver
#ifdef CURSENS
current_sense.linkDriver(&driver);
// current sense init and linking
current_sense.init();
motor.linkCurrentSense(¤t_sense);
motor.torque_controller = TorqueControlType::foc_current;
// Q
motor.PID_current_q.P = 50;
motor.PID_current_q.I = 100;
motor.PID_current_q.D = 0;
motor.PID_current_q.limit = 10;
motor.PID_current_q.output_ramp = 500;
motor.LPF_current_q.Tf = 0.1;
// D
motor.PID_current_d.P = 0;
motor.PID_current_d.I = 0;
motor.PID_current_d.D = 0;
motor.PID_current_d.limit = 10;
motor.PID_current_d.output_ramp = 500;
motor.LPF_current_d.Tf = 0.1;
#endif
//motor.controller = MotionControlType::torque;
motor.controller = MotionControlType::velocity
// default voltage_power_supply
motor.voltage_sensor_align = 2;
motor.voltage_limit = 1;
motor.current_limit = 10;
motor.velocity_limit = 40;
// contoller configuration based on the controll type
motor.PID_velocity.P = 0.1;
motor.PID_velocity.I = 0.1;
motor.PID_velocity.D = 0;
motor.PID_velocity.output_ramp = 1000;
motor.PID_velocity.limit = 12;
// angle loop controller
motor.P_angle.P = 10;
motor.LPF_velocity.Tf = 0.01;
// set the inital target value
motor.target = 0;
Serial.begin(921600); // WARNING: low value like 115200 cause distorted FOC
motor.useMonitoring(Serial);
motor.monitor_variables = _MON_TARGET | _MON_VOLT_Q | _MON_VOLT_D | _MON_CURR_Q | _MON_CURR_D | _MON_VEL | _MON_ANGLE; // monitor target velocity and angle
//motor.foc_modulation = SpaceVectorPWM;
// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();
// commnads
command.add(‘T’, doTarget, “target”); // ssss space
command.add(‘L’, doLimit, “voltage limit”);
command.add(‘M’,doMotor,“motor”);
_delay(1000);
}
void loop() {
// iterative setting FOC phase voltage
motor.loopFOC();
// iterative function setting the outter loop target
motor.move();
// motor monitoring
motor.monitor();
// user communication
command.run();
}