Hi,
I am trying to control this 380kv motor using the SimpleFOC library on the Infineon IFX007T BLDC shield using an Arduino micro as the MCU and the AMT103-V encoder for sensing. I’m trying to control the motor in closed loop velocity control mode, specifying the motor phase resistance and Kv values.
I’m able to get good velocity control at low speeds (0-10 rad/s), but not at higher speeds (>15 rad/s). At higher speeds, the speed measurements begin to oscillate rapidly and then decrease to a much lower speed before the target speed is reached (see attached graph of speed measurements with target_velocity -20 rad/s). I’ve spent a while trying to tune the PID gains, PID ramp limit, and low pass filter constant, but there still seems to be some instability.
I’ve also tried increasing the motor.current_limit to 12 A and the motor.velocity_limit to 30 rad/s, as suggested in other threads. This didn’t seem to help. The maximum speed that I’m able to track reliably is around 17 rad/s. Above this, the controller becomes unstable.
Do you have any suggestions on how I can reliably track higher speeds? For the application, we are hoping to be able to reach at least 30-40 rad/s and possibly higher. Thanks in advance for any advice.
Here is the code that I am using (mostly following the velocity motion control example in the docs).
#include <SimpleFOC.h>
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(12,0.25,380);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 10, 11, 3, 5, 6);
// encoder instance
Encoder encoder = Encoder(0, 1, 2048);
// Interrupt routine intialisation
// channel A and B callbacks
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
// velocity set point variable
float target_velocity = 20;
unsigned long elapsed;
unsigned long t0;
void setup() {
// initialize encoder sensor hardware
encoder.init();
encoder.enableInterrupts(doA, doB);
// link the motor to the sensor
motor.linkSensor(&encoder);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 12;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// aligning voltage [V]
motor.voltage_sensor_align = 2;
// set motion control loop to be used
motor.controller = MotionControlType::velocity;
// contoller configuration
motor.PID_velocity.P = 1.5f;
motor.PID_velocity.I = 25.0f;
motor.PID_velocity.D = 0.0f;
// default voltage_power_supply
motor.voltage_limit = 12;
motor.current_limit = 12.0; // something we added
motor.velocity_limit = 30.0;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 2000;
// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01f;
// use monitoring with serial
Serial.begin(115200);
// comment out if not needed
// motor.useMonitoring(Serial);
// motor.monitor_variables = _MON_VOLT_Q | _MON_CURR_Q ;
// initialize motor
motor.init();
// align sensor and start FOC
motor.initFOC();
Serial.println(F("Motor ready."));
_delay(1000);
t0 = millis();
}
void loop() {
elapsed = millis() - t0;
motor.loopFOC();
if (elapsed < 160000){
motor.move(target_velocity);
Serial.print(encoder.getVelocity());
Serial.println();
}
else{
motor.move(0);
}
}