Unable to increase motor velocity past 18 rad/s

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);
  }
}

@jbuzhar

Welcome to the community.

Consider upgrading your MCU, 16 MHz is way too slow.

Cheers,
Valentine