Angle Control with Torque Limiting

Hello Everyone,

First I would like to thank the developer of the simple FOC library for making an awesome library and also to the member of this community for providing their feedback on different applications and circuits.

Currently, the library works perfectly fine, I have tested all the examples except current sensing ( I am in process of adding an inline sensor to my setup) and they work fine.

Now I am unable to figure out torque limiting in the angle control setup. I set the target angel and the motor rotates to that angle. Now when I manually try to rotate the motor it rotates will very low resistance and then comes back to its previous position very slowly.

When I change the voltage. limit in the code, the result is the same. I can easily rotate the motor.

I am looking to control the motor in a way that when the target angle is given to it the motor move to the desired angle with high torque so it is hard to rotate manually.

My Set up: 50 W, 8 Pole BLDC motor with build Hall sensor, ST32 F030R MC, DRV8302 BLDC Driver, Voltage supply 20 V,

The code:

#include <SimpleFOC.h>

#define INH_A 9
#define INH_B 10
#define INH_C 11

#define EN_GATE 8
#define M_PWM A1 
#define M_OC A2
#define OC_ADJ A3

BLDCMotor motor = BLDCMotor(8);

HallSensor sensor = HallSensor(2, 3, 21, 8);

BLDCDriver3PWM driver = BLDCDriver3PWM(INH_A, INH_B, INH_C, EN_GATE);



void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

float target_angle = 0;

Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }

void setup() {
  
  // initialize sensor hardware
   sensor.pullup = Pullup::USE_EXTERN;
  sensor.init();
  sensor.enableInterrupts(doA, doB, doC); 

  motor.linkSensor(&sensor);

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 20;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);


  // aligning voltage [V]
  motor.voltage_sensor_align = 0.7;
  // index search velocity [rad/s]
  motor.velocity_index_search = 3;

  // set motion control loop to be used
  motor.controller = MotionControlType::angle;



  // velocity PI controller parameters (With these Values the motor runs smoothly)
  motor.PID_velocity.P = 0.05;
  motor.PID_velocity.I = 0.05;
  motor.PID_velocity.D = 0.0001;
  // default voltage_power_supply
  motor.voltage_limit = 3;

  motor.PID_velocity.output_ramp = 1000;
 
  // velocity low pass filtering time constant
  motor.LPF_velocity.Tf = 0.01;

  // angle P controller
  motor.P_angle.P = 2.5;
  //  maximal velocity of the position control
  motor.velocity_limit = 50;


  
  Serial.begin(115200);
  
  motor.useMonitoring(Serial);
  
  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

  // add target command T
  command.add('T', doTarget, "target angle");

  Serial.println(F("Motor ready."));
  Serial.println(F("Set the target angle using serial terminal:"));
  _delay(1000);
}

void loop() {

  motor.loopFOC();


  motor.move(target_angle);

  
  command.run();
  motor.monitor();
}

Thanks

Hey, a few comments:

  • your motor.voltage_limit is set to 3V - this will limit the torque it can develop
  • your velocity P, I and angle P values all seem a bit low. I usually have higher values, but this depends on your motor and driver of course.

Could you give a picture of your motor or describe its type?

Thanks for your reply.

With higher values of velocity, P, and I the motors vibrate quite heavily. The motor I am using is 8 poles, delta winding having an internal resistance of 0.73 ohm.

Is it an in-runner or out-runner? 8PP is an unusual number… that would imply 16 poles.

It’s an in-runner. Specs of motor are:

Ok, I would say from that datasheet that the motor has 8 poles and therefore 4 pole-pairs…
The parameter to the BLDCMotor constructor is the number of pole-pairs.

What happens if you change the parameter of BLDCMotor (and re-tune the PIDs)?

BLDCMotor motor = BLDCMotor(4); // 8 poles == 4 pole-pairs

OO, I was running the motors with pp :8. It seems I was wrong. Thanks for correcting me. I will change the pp to 4 and will tune the PID values. Thanks

I turned the motor with new PID values P 0.90, I 0.1, D 0.005 but still I am unable to achieve the holding torque on the motors.
I set the target angle to 10 and I can easily rotate the motor, Can you advise how to achieve holding torque in angle control.
Thanls

If angle control mode works it means that the set-up is working. Holding torque is there most likely, but very low. Would you share a video so we understand what is happening?

Have you tried increasing the voltage limit?

Yes, I increased the voltage limit from 3 volts to 6 volts but the same result. I will make a video today and upload it here.

https://www.youtube.com/watch?v=9B2qLc6SOVw

After changing the voltage limit. I experienced the same result.

Looks like position control is working and you have some holding torque. Does the motor get hot while the error is 0? does the motor get hot if you keep the rotor out of the set-point (fighting the generated torque) after a few seconds/minutes?

It has a holding torque but a minimum one. I wanted to increase the holding torque. I will check tomorrow the motor temperature when I move it manually. Thanks

hmmm ok, I see what you mean - hardly any torque, not very fast movement back to the set-point, and its also very noisy it seems to me?

I hate to ask again, but do you have the
lib_archive = false
option set in platformio?

I switched to STM32duino as in platform IO I was unable to change the PWM frequency, and the noise is from the back freezer in the lab. Sorry for that. I tried to hold the motor manually and after some time the motor gets warm but still, I am unable to increase the holding torque by changing the voltage limit. Kindly, if you can advise, what am I missing. Thanks.

Hey @MoidKhan,

Your Integration gain I is really really low. It should go above 10 maybe be closer to 30. The P gain you can raise a bit also if there are some osculations.

if your integrative gain is very low then it will take a long long time for the motor to reach the torque limit. basically the higher the I value the faster the limiting torque will be reached.

Many thanks for your reply.

I tuned the PID parameter and with Higher, I value I was about to attain the holding torque. Now with lowering down the voltage limit the holding torque decreases and with a higher voltage limit the torque increase.

But when I try to change the voltage limit value in the loop, using the serial commander function, the torque remains the same. So, we can’t change the voltage limit in the loop. I has to be pre-defined in the setup function.

I am happy to hear that you found your solution. :smiley:
You can change it easily using the commander interface.

If you add your motor to the commander:


....
// defined wrapper for generic callback
void onMotor(char* cmd){commander.motor(&motor, cmd);}
...
void setup(){
  ...
  commander.add('M',onMotor,"my motor");
  ...
}
void loop(){
  ...
  commander.run();
}

And then in the serial terminal you can read and write it using MLU command.

MLU     # get voltage limit
MLU10 # set voltage limit to 10V