Current output 1/5 of what Odrive measures

Odrive 3.6 56V, 36V supply driving Segway Ninebot motors. I’ve been setting up these motors for a couple months and thought I had the Odrive sorted. Started using it with Ardurover to drive my autonomous lawnmower, and have been unable to get enough torque to do pivot turns. Odrive says it is putting out 20A on each motor, which is the limit I set, and the Ardurover is measuring only 6-10A combined!! I verified the Ardurover 6-10 measurement with an external current meter.

Why is the Odrive over-measuring the output current???

Here is the full screen capture of Odrive using command

start_liveplotter(lambda: [odrv0.axis0.motor.current_control.Iq_measured,  odrv0.axis1.motor.current_control.Iq_measured])

and the Tuning plot of current in Mission Planner:

Here is my config:

{
  "axis0": {
    "acim_estimator": {
      "config": {
        "slip_velocity": 14.706000328063965
      }
    },
    "config": {
      "dir_gpio_pin": 2,
      "enable_sensorless_mode": false,
      "enable_step_dir": false,
      "enable_watchdog": false,
      "startup_closed_loop_control": true,
      "startup_encoder_index_search": false,
      "startup_encoder_offset_calibration": false,
      "startup_homing": false,
      "startup_motor_calibration": false,
      "step_dir_always_on": false,
      "step_gpio_pin": 1,
      "watchdog_timeout": 0.0,
      "calibration_lockin": {
        "accel": 20.0,
        "current": 10.0,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 40.0
      },
      "can": {
        "bus_vi_rate_ms": 0,
        "controller_error_rate_ms": 0,
        "encoder_count_rate_ms": 0,
        "encoder_error_rate_ms": 0,
        "encoder_rate_ms": 10,
        "heartbeat_rate_ms": 100,
        "iq_rate_ms": 0,
        "is_extended": false,
        "motor_error_rate_ms": 0,
        "node_id": 0,
        "sensorless_error_rate_ms": 0,
        "sensorless_rate_ms": 0
      },
      "general_lockin": {
        "accel": 20.0,
        "current": 10.0,
        "finish_distance": 100.0,
        "finish_on_distance": false,
        "finish_on_enc_idx": false,
        "finish_on_vel": false,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 40.0
      },
      "sensorless_ramp": {
        "accel": 200.0,
        "current": 10.0,
        "finish_distance": 100.0,
        "finish_on_distance": false,
        "finish_on_enc_idx": false,
        "finish_on_vel": true,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 400.0
      }
    },
    "controller": {
      "config": {
        "axis_to_mirror": 255,
        "circular_setpoint_range": 1.0,
        "circular_setpoints": false,
        "control_mode": 2,
        "electrical_power_bandwidth": 20.0,
        "enable_gain_scheduling": false,
        "enable_overspeed_error": true,
        "enable_torque_mode_vel_limit": true,
        "enable_vel_limit": true,
        "gain_scheduling_width": 10.0,
        "homing_speed": 0.25,
        "inertia": 0.0,
        "input_filter_bandwidth": 2.0,
        "input_mode": 1,
        "load_encoder_axis": 0,
        "mechanical_power_bandwidth": 20.0,
        "mirror_ratio": 1.0,
        "pos_gain": 1.5,
        "spinout_electrical_power_threshold": 1000.0,
        "spinout_mechanical_power_threshold": -1000.0,
        "steps_per_circular_range": 1024,
        "torque_mirror_ratio": 0.0,
        "torque_ramp_rate": 0.009999999776482582,
        "vel_gain": 15.0,
        "vel_integrator_gain": 20.0,
        "vel_integrator_limit": Infinity,
        "vel_limit": 15.0,
        "vel_limit_tolerance": 1.2000000476837158,
        "vel_ramp_rate": 1.0,
        "anticogging": {
          "anticogging_enabled": true,
          "calib_anticogging": false,
          "calib_pos_threshold": 1.0,
          "calib_vel_threshold": 1.0,
          "cogging_ratio": 1.0,
          "index": 0,
          "pre_calibrated": false
        }
      }
    },
    "encoder": {
      "config": {
        "abs_spi_cs_gpio_pin": 1,
        "bandwidth": 100.0,
        "calib_range": 0.019999999552965164,
        "calib_scan_distance": 150.0,
        "calib_scan_omega": 12.566370964050293,
        "cpr": 90,
        "direction": -1,
        "enable_phase_interpolation": true,
        "find_idx_on_lockin_only": false,
        "hall_polarity_calibrated": true,
        "hall_polarity": 0,
        "ignore_illegal_hall_state": false,
        "index_offset": 0.0,
        "mode": 1,
        "phase_offset_float": -0.42729026079177856,
        "phase_offset": -44,
        "pre_calibrated": true,
        "sincos_gpio_pin_cos": 4,
        "sincos_gpio_pin_sin": 3,
        "use_index_offset": true,
        "use_index": false
      }
    },
    "max_endstop": {
      "config": {
        "debounce_ms": 50,
        "enabled": false,
        "gpio_num": 0,
        "is_active_high": false,
        "offset": 0.0
      }
    },
    "mechanical_brake": {
      "config": {
        "gpio_num": 0,
        "is_active_low": true
      }
    },
    "min_endstop": {
      "config": {
        "debounce_ms": 50,
        "enabled": false,
        "gpio_num": 0,
        "is_active_high": false,
        "offset": 0.0
      }
    },
    "motor": {
      "config": {
        "I_bus_hard_max": Infinity,
        "I_bus_hard_min": -Infinity,
        "I_leak_max": 0.10000000149011612,
        "R_wL_FF_enable": false,
        "acim_autoflux_attack_gain": 10.0,
        "acim_autoflux_decay_gain": 1.0,
        "acim_autoflux_enable": false,
        "acim_autoflux_min_Id": 10.0,
        "acim_gain_min_flux": 10.0,
        "bEMF_FF_enable": false,
        "calibration_current": 10.0,
        "current_control_bandwidth": 1000.0,
        "current_lim_margin": 8.0,
        "current_lim": 20.0,
        "dc_calib_tau": 0.20000000298023224,
        "inverter_temp_limit_lower": 100.0,
        "inverter_temp_limit_upper": 120.0,
        "motor_type": 0,
        "phase_inductance": 0.0003974497376475483,
        "phase_resistance": 0.17622026801109314,
        "pole_pairs": 15,
        "pre_calibrated": true,
        "requested_current_range": 40.0,
        "resistance_calib_max_voltage": 4.0,
        "torque_constant": 0.5168750286102295,
        "torque_lim": Infinity
      },
      "fet_thermistor": {
        "config": {
          "enabled": true,
          "temp_limit_lower": 100.0,
          "temp_limit_upper": 120.0
        }
      },
      "motor_thermistor": {
        "config": {
          "enabled": false,
          "gpio_pin": 4,
          "poly_coefficient_0": 0.0,
          "poly_coefficient_1": 0.0,
          "poly_coefficient_2": 0.0,
          "poly_coefficient_3": 0.0,
          "temp_limit_lower": 100.0,
          "temp_limit_upper": 120.0
        }
      }
    },
    "sensorless_estimator": {
      "config": {
        "observer_gain": 1000.0,
        "pll_bandwidth": 1000.0,
        "pm_flux_linkage": 0.0015800000401213765
      }
    },
    "trap_traj": {
      "config": {
        "accel_limit": 0.5,
        "decel_limit": 0.5,
        "vel_limit": 2.0
      }
    }
  },
  "axis1": {
    "acim_estimator": {
      "config": {
        "slip_velocity": 14.706000328063965
      }
    },
    "config": {
      "dir_gpio_pin": 8,
      "enable_sensorless_mode": false,
      "enable_step_dir": false,
      "enable_watchdog": false,
      "startup_closed_loop_control": true,
      "startup_encoder_index_search": false,
      "startup_encoder_offset_calibration": false,
      "startup_homing": false,
      "startup_motor_calibration": false,
      "step_dir_always_on": false,
      "step_gpio_pin": 7,
      "watchdog_timeout": 0.0,
      "calibration_lockin": {
        "accel": 20.0,
        "current": 10.0,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 40.0
      },
      "can": {
        "bus_vi_rate_ms": 0,
        "controller_error_rate_ms": 0,
        "encoder_count_rate_ms": 0,
        "encoder_error_rate_ms": 0,
        "encoder_rate_ms": 10,
        "heartbeat_rate_ms": 100,
        "iq_rate_ms": 0,
        "is_extended": false,
        "motor_error_rate_ms": 0,
        "node_id": 1,
        "sensorless_error_rate_ms": 0,
        "sensorless_rate_ms": 0
      },
      "general_lockin": {
        "accel": 20.0,
        "current": 10.0,
        "finish_distance": 100.0,
        "finish_on_distance": false,
        "finish_on_enc_idx": false,
        "finish_on_vel": false,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 40.0
      },
      "sensorless_ramp": {
        "accel": 200.0,
        "current": 10.0,
        "finish_distance": 100.0,
        "finish_on_distance": false,
        "finish_on_enc_idx": false,
        "finish_on_vel": true,
        "ramp_distance": 3.1415927410125732,
        "ramp_time": 0.4000000059604645,
        "vel": 400.0
      }
    },
    "controller": {
      "config": {
        "axis_to_mirror": 255,
        "circular_setpoint_range": 1.0,
        "circular_setpoints": false,
        "control_mode": 2,
        "electrical_power_bandwidth": 20.0,
        "enable_gain_scheduling": false,
        "enable_overspeed_error": true,
        "enable_torque_mode_vel_limit": true,
        "enable_vel_limit": true,
        "gain_scheduling_width": 10.0,
        "homing_speed": 0.25,
        "inertia": 0.0,
        "input_filter_bandwidth": 2.0,
        "input_mode": 1,
        "load_encoder_axis": 1,
        "mechanical_power_bandwidth": 20.0,
        "mirror_ratio": 1.0,
        "pos_gain": 1.5,
        "spinout_electrical_power_threshold": 1000.0,
        "spinout_mechanical_power_threshold": -1000.0,
        "steps_per_circular_range": 1024,
        "torque_mirror_ratio": 0.0,
        "torque_ramp_rate": 0.009999999776482582,
        "vel_gain": 15.0,
        "vel_integrator_gain": 0.5,
        "vel_integrator_limit": Infinity,
        "vel_limit": 15.0,
        "vel_limit_tolerance": 1.2000000476837158,
        "vel_ramp_rate": 1.0,
        "anticogging": {
          "anticogging_enabled": true,
          "calib_anticogging": false,
          "calib_pos_threshold": 1.0,
          "calib_vel_threshold": 1.0,
          "cogging_ratio": 1.0,
          "index": 0,
          "pre_calibrated": false
        }
      }
    },
    "encoder": {
      "config": {
        "abs_spi_cs_gpio_pin": 1,
        "bandwidth": 100.0,
        "calib_range": 0.019999999552965164,
        "calib_scan_distance": 150.0,
        "calib_scan_omega": 12.566370964050293,
        "cpr": 90,
        "direction": -1,
        "enable_phase_interpolation": true,
        "find_idx_on_lockin_only": false,
        "hall_polarity_calibrated": true,
        "hall_polarity": 0,
        "ignore_illegal_hall_state": false,
        "index_offset": 0.0,
        "mode": 1,
        "phase_offset_float": -0.4360489249229431,
        "phase_offset": -20,
        "pre_calibrated": true,
        "sincos_gpio_pin_cos": 4,
        "sincos_gpio_pin_sin": 3,
        "use_index_offset": true,
        "use_index": false
      }
    },
    "max_endstop": {
      "config": {
        "debounce_ms": 50,
        "enabled": false,
        "gpio_num": 0,
        "is_active_high": false,
        "offset": 0.0
      }
    },
    "mechanical_brake": {
      "config": {
        "gpio_num": 0,
        "is_active_low": true
      }
    },
    "min_endstop": {
      "config": {
        "debounce_ms": 50,
        "enabled": false,
        "gpio_num": 0,
        "is_active_high": false,
        "offset": 0.0
      }
    },
    "motor": {
      "config": {
        "I_bus_hard_max": Infinity,
        "I_bus_hard_min": -Infinity,
        "I_leak_max": 0.10000000149011612,
        "R_wL_FF_enable": false,
        "acim_autoflux_attack_gain": 10.0,
        "acim_autoflux_decay_gain": 1.0,
        "acim_autoflux_enable": false,
        "acim_autoflux_min_Id": 10.0,
        "acim_gain_min_flux": 10.0,
        "bEMF_FF_enable": false,
        "calibration_current": 10.0,
        "current_control_bandwidth": 1000.0,
        "current_lim_margin": 8.0,
        "current_lim": 20.0,
        "dc_calib_tau": 0.20000000298023224,
        "inverter_temp_limit_lower": 100.0,
        "inverter_temp_limit_upper": 120.0,
        "motor_type": 0,
        "phase_inductance": 0.00037345653981901705,
        "phase_resistance": 0.1626671403646469,
        "pole_pairs": 15,
        "pre_calibrated": true,
        "requested_current_range": 40.0,
        "resistance_calib_max_voltage": 4.0,
        "torque_constant": 0.5168750286102295,
        "torque_lim": Infinity
      },
      "fet_thermistor": {
        "config": {
          "enabled": true,
          "temp_limit_lower": 100.0,
          "temp_limit_upper": 120.0
        }
      },
      "motor_thermistor": {
        "config": {
          "enabled": false,
          "gpio_pin": 4,
          "poly_coefficient_0": 0.0,
          "poly_coefficient_1": 0.0,
          "poly_coefficient_2": 0.0,
          "poly_coefficient_3": 0.0,
          "temp_limit_lower": 100.0,
          "temp_limit_upper": 120.0
        }
      }
    },
    "sensorless_estimator": {
      "config": {
        "observer_gain": 1000.0,
        "pll_bandwidth": 1000.0,
        "pm_flux_linkage": 0.0015800000401213765
      }
    },
    "trap_traj": {
      "config": {
        "accel_limit": 0.5,
        "decel_limit": 0.5,
        "vel_limit": 2.0
      }
    }
  },
  "can": {
    "config": {
      "baud_rate": 250000,
      "protocol": 1
    }
  },
  "config": {
    "brake_resistance": 2.0,
    "dc_bus_overvoltage_ramp_end": 59.92000198364258,
    "dc_bus_overvoltage_ramp_start": 59.92000198364258,
    "dc_bus_overvoltage_trip_level": 59.92000198364258,
    "dc_bus_undervoltage_trip_level": 8.0,
    "dc_max_negative_current": -10.0,
    "dc_max_positive_current": Infinity,
    "enable_brake_resistor": false,
    "enable_can_a": true,
    "enable_dc_bus_overvoltage_ramp": false,
    "enable_i2c_a": false,
    "enable_uart_a": true,
    "enable_uart_b": false,
    "enable_uart_c": false,
    "error_gpio_pin": 0,
    "gpio10_mode": 11,
    "gpio11_mode": 2,
    "gpio12_mode": 12,
    "gpio13_mode": 12,
    "gpio14_mode": 2,
    "gpio15_mode": 7,
    "gpio16_mode": 7,
    "gpio1_mode": 4,
    "gpio2_mode": 4,
    "gpio3_mode": 10,
    "gpio4_mode": 10,
    "gpio5_mode": 3,
    "gpio6_mode": 0,
    "gpio7_mode": 0,
    "gpio8_mode": 0,
    "gpio9_mode": 11,
    "max_regen_current": -10.0,
    "uart0_protocol": 3,
    "uart1_protocol": 3,
    "uart2_protocol": 3,
    "uart_a_baudrate": 115200,
    "uart_b_baudrate": 115200,
    "uart_c_baudrate": 115200,
    "usb_cdc_protocol": 3,
    "gpio1_pwm_mapping": {
      "endpoint": null,
      "max": 0.0,
      "min": 0.0
    },
    "gpio2_pwm_mapping": {
      "endpoint": null,
      "max": 0.0,
      "min": 0.0
    },
    "gpio3_analog_mapping": {
      "endpoint": null,
      "max": 0.0,
      "min": 0.0
    },
    "gpio3_pwm_mapping": {
      "endpoint": "axis0.controller.input_vel",
      "max": 2.0,
      "min": -2.0
    },
    "gpio4_analog_mapping": {
      "endpoint": null,
      "max": 0.0,
      "min": 0.0
    },
    "gpio4_pwm_mapping": {
      "endpoint": "axis1.controller.input_vel",
      "max": 2.0,
      "min": -2.0
    }
  }
}

Hi! The ODrive Iq_measured is the current through the motor, while I’m guessing your current sensor is on the ODrive power input, which would be the bus current – the ODrive exposes this too, as the odrv0.ibus property.

In motor control, bus current and motor current are very rarely the same – here’s a good article on it, happy to explain more if desired! Things in Motion: How to select the right power source for a hobby BLDC (PMSM) motor

Generally if the ODrive says it’s putting out 20A (via Iq_measured), I’d generally trust that that’s the actual current going through the motor. I’m not too surprised you’re having issue with pivot turns – hoverboard motors aren’t that high torque, especially offroad. You could maybe “blip” them up to very high current for a split second (maybe ~30-40A), just to get them moving and break static friction.

Well that explains some things, but I had assumed that bus current would ~= M0 + M1 Iq_measured.
Saw in another post that Wetmelon had said that Total current through the windings is

sqrt(motor.current_control.Iq_measured^2 + motor.current_control.Id_measured^2)

I hadn’t actually thought it through, that the Odrive must chop the voltage, or has a switching front end. I looked for a while though to find a parameter that shows voltage applied to motor and couldn’t find any, so figured the Odrive is essentially switching battery voltage on/off with the PWM to get the desired power. But as low resistance as the windings are, current would be through the roof.

I have current_lim_margin = 8.0, but don’t see that being hit on the Iq_measured waveforms, only the 20A from current_lim
Guess I’ll just bump up my motor.config.curren_lim up to 30-40A as you say, it definitely sounds safe.

Saw this in a post by jxb167

The motor behaves like a buck converter when controlling current in the phase. The voltage requirement at the phase is lower than the power supply voltage, and the motor behaves as the inductor in a buck converter.

That seems to answer my question about the Odrive chopping or having a switching front end.

This is correct! The motor current is regulated through chopping, the inductance in the motor causes a smooth current to flow even though the input is the bus voltage PWM’d (at about 24kHz). So it’s effectively a buck regulator, where the output “voltage” (to the motor) is the motor’s speed * KV plus current * winding resistance – simplified, but essentially the amount of voltage needed to overcome back-emf plus the amount of voltage needed to put the desired amount of current through the coils.

Oh - voltage applied to motor is sqrt(motor.current_control.final_v_alpha^2 + motor.current_control.final_v_beta^2).

Have set odrv0.axis0.motor.config.current_lim = 30 (also axis1) and pivot turns are working nicely!

Great to hear!!