Reverse Direction of Rotational Resistance for Current_lim

I want to have my motor be able to resist a force up to a certain current limit in two different directions. The following code works to resist force in one direction:

if (c == '7') {
      float arm_strength = 34.0;                                                  //lbf applied at wrist
      int requested_state;
      requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';  //put into closed loop control
      if(!odrive.run_state(0, requested_state, false /*don't wait*/)) return;
      
      odrive_serial << "w axis0.controller.config.control_mode " << 3 << "\n";  //Control Mode 3 is poisiton control
      odrive_serial << "w axis0.controller.config.input_mode " << 1 << "\n";    //Input mode 1 is pass through

      float current_req = arm_strength / (ARM_LENGTH/12) / GEAR_RATIO / TORQUE_CONST; //convert force applied at wrist to current
      odrive_serial << "w axis0.motor.config.current_lim " << current_req << '\n';    //set the current lim (torque)
      lcd.setCursor(0, 0);
      lcd.print("Req lbf: 34.00");
      static const unsigned long duration = 30000;                              //Prints to the display for 10s
      unsigned long start = millis();
      float maxForce = 0.0;
      while(millis() - start < duration) {                                      //10s loop
        odrive_serial << "r axis0.motor.current_control.Iq_setpoint\n";         //Reads the current being supplied to the current
        float Iq_sentpoint = odrive.readFloat();
        Serial << Iq_sentpoint << '\n';
        float curForce = -Iq_sentpoint * TORQUE_CONST * GEAR_RATIO * ARM_LENGTH/12;         // Convert current to force applied at wrist
        lcd.setCursor(0, 1);
        lcd.print("Max lbf: ");
        if (curForce > maxForce) {                                          //only print the maximum Force
          maxForce = curForce;
        }
        lcd.print(maxForce);
      }
    }

I would like to add another if statement such that if

c=='8'

the motor resists the force in the opposite direction of rotation. However, when I add a negative sign and try

odrive_serial << "w axis0.motor.config.current_lim " << -current_req << '\n';

nothing changes. Every other way I have also tried has failed.

Does anyone know a way to have the motor resist force in a different direction depending on different inputs to an if statement?

You’d need to hack the ODrive firmware to do this.

I would suggest that you modify the velocity controller to limit its current demand based on direction.
i.e. modify the “torque limit” in controller.cpp to have positive and negative limits

    // Torque limiting
    bool limited = false;
    float Tlim = axis_->motor_.max_available_torque();
    if (torque > Tlim) {
        limited = true;
        torque = Tlim;
    }
    if (torque < -Tlim) {
        limited = true;
        torque = -Tlim;
    }

could be changed to:

    // Torque limiting
    bool limited = false;
    float TlimP = axis_->motor_.max_available_positive_torque();
    float TlimN = axis_->motor_.max_available_negative_torque();
    if (torque > TlimP) {
        limited = true;
        torque = TlimP;
    }
    if (torque < TlimN) {
        limited = true;
        torque = TlimN;
    }

You’d need to define new functions i.e. max_available_positive_torque(); in motor.cpp/motor.hpp and add the properties to odrive_interface.yaml

1 Like

Thanks for the response! So first I would make that edit to controller.cpp, and then change float Motor::max_available_torque() { to float Motor::max_available_positive_torque() { and float Motor::max_available_negative_torque() { in both motor.cpp and motor.hpp and define the functions. Then would I need to change the torque_lim property in odrive_interface.yaml to be pos_torque_lim and neg_torque_lim?

Also, how would I then implement this in Arduino code to have the motor resist force in both directions? It seems like there should be a way to simply resist torque in two directions without making firmware edits.