B_g431_esc not enough torque in certain modes

Hello,

Im pretty new to this so please bear with me :smiley:

I am using the b_g431_esc board and as5048A sensor (PWM)

Why is it that I can use the code pasted below to get my motor to turn with good torque resistance (e.g. when the motor is spinning at target_velocity and I try to stop it with my hands, I feel strong torque and the current draw from my power supply nears the motor.current_limit).

But when I use code shown here which uses foc_current torque control (not mine): github link
the target velocity is reached but with very little resistance when I try to stop it with my hands.

In addition, when I use the code pasted below, sure there’s good torque resistance, but the max speed seems to be around target_velocity = 35-40 rad/s. Beyond this speed, the motor stutters slightly and the no-load current draw increases substantially (from 0.1A to 1A for instance). Are these a PID tuning issue? or…? Anything helps, thank you.

#include <Arduino.h>
#include "SimpleFOC.h"

BLDCMotor motor = BLDCMotor(12, 1.5);
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
LowsideCurrentSense currentSense = LowsideCurrentSense(0.003f, -64.0f/7.0f, A_OP1_OUT, A_OP2_OUT, A_OP3_OUT);
MagneticSensorPWM sensor = MagneticSensorPWM(A_HALL1, 2, 925);

void doPWM(){sensor.handlePWM();}

// angle set point variable
float target_angle = 0;

// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }
void doCommand(char* cmd) { command.motor(&motor, cmd); }


void sensor_test(void)
{
	//sensor.update();
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
}

void setup() {
  
  // initialise magnetic sensor hardware
  sensor.init();
  sensor.enableInterrupt(doPWM);
  motor.linkSensor(&sensor);
  
  driver.voltage_power_supply = 14.8;
  driver.init();

  motor.linkDriver(&driver);
  //currentSense.linkDriver(&driver);

  //currentSense.init();

  //currentSense.skip_align = true;
  //motor.linkCurrentSense(&currentSense);

  motor.voltage_sensor_align = 1;
  motor.velocity_index_search = 3;
  motor.controller = MotionControlType::velocity;

  // velocity PI controller parameters
  motor.PID_velocity.P = 0.08;
  //0.08
  motor.PID_velocity.I = 1;
  // default voltage_power_supply
  motor.voltage_limit = 14.8;
  // jerk control using voltage voltage ramp
  // default value is 300 volts per sec  ~ 0.3V per millisecond
  motor.PID_velocity.output_ramp = 500;
 
  // velocity low pass filtering time constant
  motor.LPF_velocity.Tf = 0.08;

  // angle P controller
  motor.P_angle.P = 5;
  //  maximal velocity of the position control
  //motor.velocity_limit = 12;
  motor.current_limit = 1.6;


  // use monitoring with serial 
  //Serial.begin(115200);
  // comment out if not needed
  //motor.useMonitoring(Serial);
  
  // initialize motor
  motor.init();
  // align encoder 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(500);
}

// velocity set point variable
float target_velocity = 45; // 2Rad/s ~ 20rpm

void loop() {

  #if 1
  // main FOC algorithm function
  motor.loopFOC();

  // Motion control function
  motor.move(target_velocity);

  #endif
}

Hey @Sean_C , welcome to SimpleFOC!

It’s hard to say exactly based on your description. The code you link is significantly different to yours.

Assuming you adjust it to match your motor parameters and use the same mode, the principle difference would be the use of current sensing.

So I would assume the difference is down to tuning in the end, and the PID parameters and filter timings have to be fine tuned to your setup.

Thanks for the reply @runger ! In that case, how does one approach tuning, let’s say,
the MotionControlType::velocity PID parameters along with the TorqueControlType::dc_current PID parameters? I’d imagine that they somewhat affect each other in terms of the behavior in reaching the target velocity.

I do understand that a quick way to do it is to increase the P->I->D values incrementally until the response looks good but tuning the PID_current_q isn’t as intuitive, especially when simultanously dealing with the PID_velocity values.

Again, this is with the goal of smooth transitions between different target velocities with maximum available torque when needed/when load applied, and the problem is that the TorqueControlType::dc_current and TorqueControlType::foc_current modes don’t provide much torque. I’ve fiddled around with the PID values; haven’t kept them default, but nothing seems to help.

Hope this makes sense. Thanks!

I’d first use torque mode, and tune the current PID without the velocity PID involved. Once you’re happy with that, change to velocity mode and tune the velocity PID. You may need to go back and iterate. The loop timings also play a role, together with the low pass filter values, so as you add to your code (if you do) you may also need to re-tune.

it does make sense, unfortunately I can’t offer a easy solution. There are many variables and parameters and so it can be a bit of a pain to get it right. Certainly, making sure the external factors are as optimal as you can get them (good sensor signal, decent loop times, some kind of tool to visualise the effect of changing things) is important to making the tuning job easier…

If you can never get any torque out of them (even in torque-current mode when you set larger currents) then there may be something else wrong? Perhaps your gain values are off somehow, so the measured current is higher than the actual one?

1 Like