Arduino motor calibration takes minutes

I have a sensorless motor attached to my drive and am trying to control it through an Arduino Mega. when I request AXIS_STATE_MOTOR_CALIBRATION the motor beeps after 10 seconds and then sits still for around 2 minute before requesting senseless mode and spinning up.

is there a way to skip sensorless calibration and start the motor running straight away or is there something I’m missing that is causing the motor to take a large amount of time to calibrate.

thanks in advance.

#include <ODriveArduino.h>

// Printing with stream operator
template<class T> inline Print& operator <<(Print &obj,     T arg) { obj.print(arg);    return obj; }
template<>        inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; }

// Serial to the ODrive
SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
// Note: you must also connect GND on ODrive to GND on Arduino!

// ODrive object
ODriveArduino odrive(odrive_serial);

void setup() {
  // ODrive uses 115200 baud
  odrive_serial.begin(115200);

  // Serial to PC
  Serial.begin(115200);
  while (!Serial) ; // wait for Arduino Serial Monitor to open

  Serial.println("ODriveArduino");
  Serial.println("Setting parameters...");

  // In this example we set the same parameters to both motors.
  // You can of course set them different if you want.
  // See the documentation or play around in odrivetool to see the available parameters
  /*for (int axis = 0; axis < 2; ++axis) {
    odrive_serial << "w axis" << axis << ".controller.config.vel_limit " << 22000.0f << '\n';
    odrive_serial << "w axis" << axis << ".motor.config.current_lim " << 22.0f << '\n';
    odrive_serial << "w axis" << axis << ".motor.config.pole_pairs " << 3.0f << '\n';
    odrive_serial << "w axis" << axis << ".config.spin_up_current " << 20.0f << '\n';
    odrive_serial << "w axis" << axis << ".config.spin_up_acceleration " << 1000.0f << '\n';
    odrive_serial << "w axis" << axis << ".config.spin_up_target_vel " << 300.0f << '\n';
    odrive_serial << "w axis" << axis << ".controller.config.vel_integrator_gain " << 0.05f << '\n';
    odrive_serial << "w axis" << axis << ".sensorless_estimator.config.pm_flux_linkage " << 0.000471221278f << '\n';
    odrive_serial << "w axis" << axis << ".controller.config.vel_gain " << 0.01f << '\n';
    odrive_serial << "w axis" << axis << ".controller.config.control_mode " << 2.0f << '\n';
    odrive_serial << "w axis" << axis << ".controller.vel_setpoint " << 400.0f << '\n';
    odrive_serial << "w axis" << axis << ".save_configuration() " << '\n';
    //odrive_serial << "w axis" << axis << ".controller.set_vel_setpoint " << 1000, 0.2 << '\n';
    // This ends up writing something like "w axis0.motor.config.current_lim 10.0\n"
  }*/

  Serial.println("Ready!");
  Serial.println("Send the character '0' or '1' to calibrate respective motor (you must do this before you can command movement)");
  Serial.println("Send the character 's' to exectue test move");
  Serial.println("Send the character 'b' to read bus voltage");
  Serial.println("Send the character 'p' to read motor positions in a 10s loop");
}

void loop() {

  if (Serial.available()) {
    char c = Serial.read();

    // Run calibration sequence
    if (c == '0' || c == '1') {
      int motornum = c-'0';
      int requested_state;

      requested_state = ODriveArduino::AXIS_STATE_MOTOR_CALIBRATION;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
      odrive.run_state(motornum, requested_state, true);

      requested_state = ODriveArduino::AXIS_STATE_SENSORLESS_CONTROL;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
      odrive.run_state(motornum, requested_state, false);

    }

    // 
    if (c == 's') {
      Serial.println("Executing test move");
        odrive.SetVelocity(0, 4000);
        delay(5);
      
    }

    // Read bus voltage
    if (c == 'b') {
      Serial.println("Executing test move");
        odrive.SetVelocity(0, 300);
        delay(5);
    }

    // print motor positions in a 10s loop
    if (c == 'p') {
      Serial.println("Executing test move");
        odrive.SetVelocity(0, -300);
        delay(300);
        odrive.SetVelocity(0, -2000);
       // delay(50);
        //odrive.SetVelocity(0, -2000);
      }
        Serial << '\n';
      }
    }
  

solved my own problem. I was trying to set parameters and config from the Arduino.

I needed to run AXIS_STATE_MOTOR_CALIBRATION in the odrivetool and then set .motor.config.pre_calibrated to true. then in the Arduino only sensorless mode must be called to start the motor.

I’m unsure why calibrating in the Arduino took so long but I’ve managed to get past it by not calibrating the motor on start up.

1 Like