Motor in closed-loop voltage control slowly stops spinning

Hello all, I am new to the FOC community and I have a few with regards to closed loop operation of a BLDC motor. I have a Motor ( 14 pole 2216 BLDC) fitted with an absolute position encoder with ( 1024 PPR, SPI as well as quadrature outputs). I have gone through a bunch of the setup testing the encoder, as well as running the motor in open loop mode; all these tests were successful.

I moved on to testing the motor in closed-loop velocity mode. I found that the PID variables were rater hard to tune. The motor would either oscillate, or while running at about 20rad/s, would slow down while the motor current would rapidly rise to the max power allocated to the motor.

I then moved to voltage controlled torque mode ( I put PID tuning on hold ). The issue that I am having is I can get the motor to spin in closed loop mode for about 10 seconds, but then the motor starts to slow down and then stops spinning. I can boost the voltage and a similar fate happens. Can anyone please point me in the right direction on where to look to solve such a problem so I can ensure the system works.
Thank you all in advance

Hardware.
Controller - Arduino Uno
Driver - simplefoc shield v2.03
Motor - generic RC BLDC motor
Encoder - AMT203 ( just running in quadrature mode )

Notes:
The driver Is not overheating
Voltage limits set to not burn out the driver and motor.
I am monitoring the current with my power supply and it is limited to an appropriate value.

1 Like

Welcome, @CLIXXCLIXX !

Hmmm… the setup you describe is actually well-tested. The Arduino Uno is not the most powerful MCU, so your performance will be limited by this, but normal operation should be possible.

Are you using Arduino IDE?
Could you check the iteration speed of your main loop, i.e. how many times you are calling loopFOC() per second?
What is the phase resistance of your motor?
Would you mind sharing the code you’re using? Maybe someone on this forum can spot the problem if it is in the code…

One thought I have based on your description is that the sensor is somehow losing the motor’s position, for example because encoder impulses are missed, or the sensor is slipping on the motor shaft. That would probably cause issues like you describe…

1 Like

I see, I had a feeling the Arduino would have some issues due to the flash utilization.

I can check the iteration speed later on today when I do some more tests. I do have other hardware to run this on though ( more capable hardware) should this be an issue. I am using the Arduino IDE, I figured it would be the fastest way to get up and running. The Phase resistance is about 0.1 Ohms, It is a little low, so I just limited the voltage to the motor so that it maintains about 800mA - 1A.

I can check the sensor later on tonight with my oscilloscope, I don think the encoder is slipping, I clamped it on rather tightly with the mounting kit.

Here is my test code, some of the PID code is commented out from when I switched from PID control to voltage control.

Thank you very much for your help :slight_smile:

#include <SimpleFOC.h>

// BLDCMotor(int pole_pairs)
BLDCMotor motor = BLDCMotor(7);//7

// set up pldc driver
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// Encoder(pin_A, pin_B, PPR)
Encoder sensor = Encoder(3, 2, 1024);

// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}

//InlineCurrentSense current_sense = InlineCurrentSense(0.004, 50, A0, A2);

//instantiate commander
Commander command = Commander(Serial);
void doMotor(char* cmd){command.motor(&motor, cmd);}

void setup() {
  // put your setup code here, to run once:
  // initialize encoder hardware
  sensor.init();
  // hardware interrupt enable
  sensor.enableInterrupts(doA, doB);

  motor.linkSensor(&sensor);

  // power supply voltage
  driver.voltage_power_supply = 12;
  // driver init
  driver.init();

  motor.linkDriver(&driver);
  

  //current_sense.init();

  //motor.linkCurrentSense(&current_sense);

  Serial.begin(115200);
  // monitoring port
  motor.useMonitoring(Serial);

  //motor.controller = MotionControlType::voltage;
  motor.controller = MotionControlType::torque;
/*
  // contoller configuration based on the control type 
  motor.PID_velocity.P = 0.1; // 0.1
  motor.PID_velocity.I = 5.0;  // 5.0
  motor.PID_velocity.D = 0.0000;//0.00001
  // default voltage_power_supply
  //motor.voltage_limit = 2;
*/
  // velocity low pass filtering time constant
  motor.LPF_velocity.Tf = 0.0001;

  // angle loop controller
  //motor.P_angle.P = 50;
  // angle loop velocity limit
  //motor.velocity_limit = 50;

  // subscribe motor to the commands
  command.add('M',doMotor,"motor");

  motor.voltage_limit =3;

  motor.init();

  motor.initFOC();

  // Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
  Serial.println(F("Motor commands sketch | Initial motion control > velocity : target 2rad."));
  
}

void loop() {
  motor.loopFOC();

  motor.move();
  motor.monitor();
  command.run();
  // put your main code here, to run repeatedly:

}

I don’t see where you set the target :slight_smile:
Also, just to be on the safe side, you might want to add a motor.torque_controller = TorqueControlType::voltage line (but I guess it’s the default mode anyway).

Hmmm - at first glance things look ok… I guess you set the target via the controller?

You might want to set a driver.voltage_limit since the phase resistance is fairly low. I know you have motor.voltage_limit, but this has a slightly different effect.

On an Arduino UNO you probably want to set the motor.LPF_velocity.Tf a little higher, maybe 0.01… UNO isn’t the fastest MCU…

Otherwise I’m not sure what’s going on… perhaps the oscilloscope can provide some clues. Another thing you could try is the SimpleFOC studio, which is a python GUI for your PC which can help to visualize what is going on.