High performance motor control
The release index here on GitHub only includes firmware for ODrive v3.x (NRND). Firmware for newer generation ODrives (Pro, S1, Micro, ...) is available here: https://docs.odriverobotics.com/releases/firmware.
Full Changelog: https://github.com/odriverobotics/ODrive/compare/fw-v0.5.5...fw-v0.5.6
This firmware is supported by and can be flashed with odrivetool
0.6.3
input_xxx
as a DC offset in tuning modesteps_
with input pos.Full Changelog: https://github.com/odriverobotics/ODrive/compare/fw-v0.5.4...fw-v0.5.5
w axis0.requested_state 4
) resulted in not implemented
due to an issue with the CI compiler. A workaround was made to fix this.r axis0.error
returned 0d
instead of 0
).<axis>.controller.config.vel_integrator_limit
i
, h
) now return the expected response (in v0.5.2 the response was corrupted)<Task pending coro=... running at ...>
when closingis_homed == True
even if it failed for some reasonbrake_resistor_current
added to interface for reading the commanded brake resistor currentodrivetool generate-code
. This feature was broken in 0.5.2. Use interface_generator.py
instead (see Tupfile.lua for examples).input_pos
doesodrivetool dfu
works properly when an ODrive is flashed with the dfu
switch set to "dfu".odrivetool dfu
now erases the entire flash memory before flashing firmware. This ensures that old configuration parameters are erased.odrv0.config.uart0_protocol
and the STREAM_PROTOCOL_TYPE
enums for details.sc
command to ascii protocol to run odrv.clear_errors()
mechanical_power_bandwidth
, electrical_power_bandwidth
, spinout_electrical_power_threshold
, spinout_mechanical_power_threshold
added to controller.config
for spinout detection.mechanical_power
and electrical_power
added to controller
.<odrv>.config.gpioX_mode
.sample_cb()
to sample all timing critical inputs (currently only encoder state).control_loop_cb()
which updates all components (encoders, estimators, torque controllers, etc). The data paths between the components are configured by the Axis threads based on the requested state. This replaces the previous architecture where the components were updated inside the Axis threads in Axis::run_control_loop()
.pwm_update_cb
on both motors to make them update their PWM timing registers.PhaseControlLaw
interface. Three components currently inherit this interface: FieldOrientedController
, ResistanceMeasurementControlLaw
and InductanceMeasurementControlLaw
.<odrv>.acim_estimator
.<axis>.enable_sensorless_mode
to disable the use of an encoder.torque_mirror_ratio
and use it to feed-forward controller_.torque_output
in INPUT_MODE_MIRROR
axis.config.turns_per_step
changed to axis.controller.config.steps_per_circular_range
odrive.axis.fet_thermistor
, odrive.axis.motor_thermistor
moved to odrive.axis.motor
objectenable_uart
and uart_baudrate
were renamed to enable_uart0
and uart0_baudrate
.enable_i2c_instead_of_can
was replaced by the separate settings enable_i2c0
and enable_can0
.<axis>.motor.gate_driver
was moved to <axis>.gate_driver
.<axis>.min_endstop.pullup
and <axis>.max_endstop.pullup
were removed. Use <odrv>.config.gpioX_mode = GPIO_MODE_DIGITAL / GPIO_MODE_DIGITAL_PULL_UP / GPIO_MODE_DIGITAL_PULL_DOWN
instead.<axis>.config.can_node_id
was moved to <axis>.config.can.node_id
<axis>.config.can_node_id_extended
was moved to <axis>.config.can.is_extended
<axis>.config.can_heartbeat_rate_ms
was moved to <axis>.config.can.heartbeat_rate_ms
<odrv>.get_oscilloscope_val()
was moved to <odrv>.oscilloscope.get_val()
.<odrv>.<axis>.error
were removed. Some were moved to <odrv>.error
and some are no longer relevant because implementation details changed.<odrv>.<axis>.motor.error
were removed. Some were moved to <odrv>.error
and some are no longer relevant because implementation details changed.<axis>.lockin_state
was removed as the lockin implementation was replaced by a more general open loop control block (currently not exposed on the API).AXIS_STATE_SENSORLESS_CONTROL
was removed. Use AXIS_STATE_CLOSED_LOOP_CONTROL
instead with <odrv>.enable_sensorless_mode = True
.<axis>.config.startup_sensorless_control
was removed. Use <axis>.config.startup_closed_loop_control
instead with <odrv>.enable_sensorless_mode = True
.<axis>.clear_errors()
was replaced by the system-wide function <odrv>.clear_errors()
.<axis>.armed_state
was replaced by <axis>.is_armed
.<axis>.motor.current_control
were changed to read-only.<axis>.motor.current_control.Ibus
was moved to <axis>.motor.I_bus
.<axis>.motor.current_control.max_allowed_current
was moved to <axis>.motor.max_allowed_current
.<axis>.motor.current_control.overcurrent_trip_level
was removed.<axis>.motor.current_control.acim_rotor_flux
was moved to <axis>.acim_estimator.rotor_flux
.<axis>.motor.current_control.async_phase_vel
was moved to <axis>.acim_estimator.stator_phase_vel
.<axis>.motor.current_control.async_phase_offset
was moved to <axis>.acim_estimator.phase
.<axis>.motor.timing_log
was removed in favor of <odrv>.task_times
and <odrv>.<axis>.task_times
.<axis>.motor.config.direction
was moved to <axis>.encoder.config.direction
.<axis>.motor.config.acim_slip_velocity
was moved to <axis>.acim_estimator.config.slip_velocity
.<axis>.encoder.config.offset
was renamed to ``<axis>.encoder.config.offset_float
was renamed to ``<odrv>.config.brake_resistance == 0.0
is no longer a valid way to disable the brake resistor. Use <odrv>.config.enable_brake_resistor
instead. A reboot is necessary for this to take effect.<odrv>.can.set_baud_rate()
was removed. The baudrate is now automatically updated when writing to <odrv>.can.config.baud_rate
.input_pos
doesmechanical_power_bandwidth
, electrical_power_bandwidth
, spinout_electrical_power_threshold
, spinout_mechanical_power_threshold
added to controller.config
for spinout detection.mechanical_power
and electrical_power
added to controller
.<odrv>.config.gpioX_mode
.sample_cb()
to sample all timing critical inputs (currently only encoder state).control_loop_cb()
which updates all components (encoders, estimators, torque controllers, etc). The data paths between the components are configured by the Axis threads based on the requested state. This replaces the previous architecture where the components were updated inside the Axis threads in Axis::run_control_loop()
.pwm_update_cb
on both motors to make them update their PWM timing registers.PhaseControlLaw
interface. Three components currently inherit this interface: FieldOrientedController
, ResistanceMeasurementControlLaw
and InductanceMeasurementControlLaw
.<odrv>.acim_estimator
.<axis>.enable_sensorless_mode
to disable the use of an encoder.torque_mirror_ratio
and use it to feed-forward controller_.torque_output
in INPUT_MODE_MIRROR
axis.config.turns_per_step
changed to axis.controller.config.steps_per_circular_range
odrive.axis.fet_thermistor
, odrive.axis.motor_thermistor
moved to odrive.axis.motor
objectenable_uart
and uart_baudrate
were renamed to enable_uart0
and uart0_baudrate
.enable_i2c_instead_of_can
was replaced by the separate settings enable_i2c0
and enable_can0
.<axis>.motor.gate_driver
was moved to <axis>.gate_driver
.<axis>.min_endstop.pullup
and <axis>.max_endstop.pullup
were removed. Use <odrv>.config.gpioX_mode = GPIO_MODE_DIGITAL / GPIO_MODE_DIGITAL_PULL_UP / GPIO_MODE_DIGITAL_PULL_DOWN
instead.<axis>.config.can_node_id
was moved to <axis>.config.can.node_id
<axis>.config.can_node_id_extended
was moved to <axis>.config.can.is_extended
<axis>.config.can_heartbeat_rate_ms
was moved to <axis>.config.can.heartbeat_rate_ms
<odrv>.get_oscilloscope_val()
was moved to <odrv>.oscilloscope.get_val()
.<odrv>.<axis>.error
were removed. Some were moved to <odrv>.error
and some are no longer relevant because implementation details changed.<odrv>.<axis>.motor.error
were removed. Some were moved to <odrv>.error
and some are no longer relevant because implementation details changed.<axis>.lockin_state
was removed as the lockin implementation was replaced by a more general open loop control block (currently not exposed on the API).AXIS_STATE_SENSORLESS_CONTROL
was removed. Use AXIS_STATE_CLOSED_LOOP_CONTROL
instead with <odrv>.enable_sensorless_mode = True
.<axis>.config.startup_sensorless_control
was removed. Use <axis>.config.startup_closed_loop_control
instead with <odrv>.enable_sensorless_mode = True
.<axis>.clear_errors()
was replaced by the system-wide function <odrv>.clear_errors()
.<axis>.armed_state
was replaced by <axis>.is_armed
.<axis>.motor.current_control
were changed to read-only.<axis>.motor.current_control.Ibus
was moved to <axis>.motor.I_bus
.<axis>.motor.current_control.max_allowed_current
was moved to <axis>.motor.max_allowed_current
.<axis>.motor.current_control.overcurrent_trip_level
was removed.<axis>.motor.current_control.acim_rotor_flux
was moved to <axis>.acim_estimator.rotor_flux
.<axis>.motor.current_control.async_phase_vel
was moved to <axis>.acim_estimator.stator_phase_vel
.<axis>.motor.current_control.async_phase_offset
was moved to <axis>.acim_estimator.phase
.<axis>.motor.timing_log
was removed in favor of <odrv>.task_times
and <odrv>.<axis>.task_times
.<axis>.motor.config.direction
was moved to <axis>.encoder.config.direction
.<axis>.motor.config.acim_slip_velocity
was moved to <axis>.acim_estimator.config.slip_velocity
.<axis>.encoder.config.offset
was renamed to ``<axis>.encoder.config.offset_float
was renamed to ``<odrv>.config.brake_resistance == 0.0
is no longer a valid way to disable the brake resistor. Use <odrv>.config.enable_brake_resistor
instead. A reboot is necessary for this to take effect.<odrv>.can.set_baud_rate()
was removed. The baudrate is now automatically updated when writing to <odrv>.can.config.baud_rate
.New in this release: Correct handling of infinity as a value ODrive config import/export Menu added to header Version bump of socket.io dependencies ODrive enums are now autogenerated and included on build Slider component fixes Numeric values automatically switch between decimal formatting and scientific notation
torque_constant
: units of torque are now [Nm] instead of just motor current.setting axis.<thermistor>.enabled
.odrive-interface.yaml
as a root source for the ODrive's API. odrivetool
connects much faster as a side effect.input_pos
, input_vel
, pos_estimate_linear
, pos_estimate_circular
, are now in units of [turns] or [turns/s] instead of [counts] or [counts/s]
axis.motor.thermal_current_lim
has been removed. Instead a new property is available axis.motor.effective_current_lim
which contains the effective current limit including any thermal limits.axis.motor.get_inverter_temp()
, axis.motor.inverter_temp_limit_lower
and axis.motor.inverter_temp_limit_upper
have been moved to seperate fet thermistor object under axis.fet_thermistor
. get_inverter_temp()
function has been renamed to temp
and is now a read-only property.axis.config.counts_per_step
is now axis.config.turns_per_step
axis.sensorless_estimator
are now in turns/s instead of electrical rad/smotor::update()
expecting a torque command instead of currentinput_mode
INPUT_MODE_VEL_RAMP caused by vel_setpoint
and axis.config.sensorless_ramp.vel
being in different unitsinput_pos
, input_vel
, and input_current
input_mode
to switch between different input behaviours
set_xxx_setpoint()
functions and made xxx_setpoint
variables read-onlyvel_limit
and vel_gain
max_regen_current
, in Ampsdc_max_negative_current
and dc_max_positive_current
odrv.config.dc_bus_overvoltage_ramp_start
and odrv.config.dc_bus_overvoltage_ramp_end
motor.config.current_lim_tolerance
to absolute motor.config.current_lim_margin
controller.vel_ramp_enable
to INPUT_MODE_VEL_RAMP.RuntimeWarning
that would occur every time odrivetool
was started.erase_configuration()
. This avoids unexpected behavior of a subsequent save_configuration()
call, since the configuration is only erased from NVM, not from RAM.motor.get_inverter_temp()
to use a property which was already being sampled at motor.inverter_temp