Gimbal motor stops after 14 minutes in velocity_openloop

Hi everybody!
When the gimbal motor runs slowly in ControlType::velocity_openloop with velocity 0.5 rad/s, it stops running after about 14 minutes and 10 seconds.

This is my setup:

  • SimpleFOClibrary version : 2.0,
  • motor : gimbal T-Motor GB2208
  • board : F446RE
  • motor driver : simpleFOCshield
  • Controll mode : ControlType::velocity_openloop
  • speed : 0.5 rad/s
  • main motor voltage : 12 V

There is still power at the motor, as the motor keeps being hot and has cogging torque, but no more movement.
The L6234 is still cold on the simpleFOCshield.
When I adjust the speed higher to 20 rad/s, the motor moves again.
If I reduce the speed then to 0.5 rad/s, the motor stops again.
If I reload the program from the ARDUINO IDE to the F446RE, the motor starts running immediately at at 0.5 rad/s.
It seems, that the problem is not located at the motor or the F446RE board (as I can still change the speed over the console), but inside the software.

Tried already to raise the motor.voltage_limit in order to get higher torques, but unfortunately the motor got very hot.
Therefore, I still use motor.voltage_limit = 3 and driver.voltage_power_supply = 12, using 12V dc for the motor.
Even with motor.voltage_limit = 3, the motor becomes very hot after a minute or so.

Since I am using ControlType::velocity_openloop, I don’t think I can use ControlType::voltage as David_Gonzalez suggested, because I don’t have an encoder for this motor.
If I am wrong, please let me know, and I will check.

Below I enclose the ARDUINO source code of the example I am using.

Cheers,
Juergen

######################################

// Open loop motor control example
 #include <SimpleFOC.h>

// motor instance
//  BLDCMotor( phA, phB, phC, pp, (en optional))
//  BLDCMotor motor = BLDCMotor(9, 10, 6, 7, 8);
//  BLDCMotor motor = BLDCMotor(3, 5, 11, 7, 7);
BLDCMotor motor = BLDCMotor(7); // just pole pairs
BLDCDriver3PWM driver = BLDCDriver3PWM(3,5,11,7); // all the hardware pins

void setup()
{
  // power supply voltage - default 12V
  driver.voltage_power_supply = 12;
  driver.init();
  motor.linkDriver(&driver);

  // limiting motor movements
  motor.voltage_limit = 3;   // rad/s - default 3
  motor.velocity_limit = 100; // rad/s - default 20 (60rpm = 6.2832rad/sek)

  // open loop control config
  motor.controller = ControlType::velocity_openloop;

  // default modulation is SinePWM
  motor.foc_modulation = FOCModulationType::SinePWM;
  // or
  //motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  _delay(1000);
}

float target_velocity = 0.5; // rad/s

void loop()
{
  // open loop velocity movement
  // using motor.voltage_limit and motor.velocity_limit
  motor.move(target_velocity);

  // receive the used commands from serial
  serialReceiveUserCommand();
}

// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand()
{
  // a string to hold incoming data
  static String received_chars;

  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {

      // change the motor target
      target_velocity = received_chars.toFloat();
      Serial.print("Target velocity ");
      Serial.println(target_velocity);

      // reset the command buffer
      received_chars = "";
    }
  }
}

Is the 14 mins 10 seconds repeatable?
Perhaps the float is rolling over. Can you print motor.shaft_angle and see if it does something funny (e.g. goes negative) at failure.

The failure is repeatable, this time the motor stoped at 14m:08s without “Serial.println(motor.shaft_angle);” and at 14m:12s including “Serial.println(motor.shaft_angle);”.

When the program is started, the motor.shaft_angle starts at 1.00 and goes up until 512,00, then the motor stops.
When the motor stops, the program is still running, but the motor.shaft_angle stays at 512,00 and doesn’t raise any more.

After checking the source code, I found the problem at BLDCMotor::velocityOpenloop(float target_velocity).
The line “shaft_angle += target_velocity*Ts;” produces an error due to insufficient precision if shaft_angle reaches 512.
Therefore, I forked Arduino-FOC and added an if statement, which resets shaft_angle after 4 rounds (4 * 2PI), and opened a pull request for the change :“check for floating point error due to insufficient precision”.
With the change, I checked the program again and the motor runs now for more than 2 hours without stopping :wink: .

Cheers,
Juergen

1 Like

Nice work! Can you create a pull request so that we can get your fix into next release.

Thanks, the pull request is already opened: check for floating point error due to insufficient precision

3 Likes

Great find! This is similar to a bug we have in closed loop that we are already working on.

Thank you very much @Juergen_Abel !

The next release will definitely have a fix for both.