Please add a note of your changes below this heading if you make a Pull Request.
- AC Induction Motor support.
- Tracking of rotor flux through rotor time constant
- Automatic d axis current for Maximum Torque Per Amp (MTPA)
- ASCII "w" commands now execute write hooks.
- Simplified control interface ("Input Filter" branch)
- New input variables:
input_pos
,input_vel
, andinput_current
- New setting
input_mode
to switch between different input behaviours- Passthrough
- Velocity Ramp
- 2nd Order Position Filter
- Trapezoidal Trajectory Planner
- Removed
set_xxx_setpoint()
functions and madexxx_setpoint
variables read-only
- New input variables:
- Preliminary support for Absolute Encoders
- Preliminary support for endstops and homing
- CAN Communication with CANSimple stack
- Gain scheduling for anti-hunt when close to 0 position error
- Velocity Limiting in Current Control mode according to
vel_limit
andvel_gain
- Regen current limiting according to
max_regen_current
, in Amps - DC Bus hard current limiting according to
dc_max_negative_current
anddc_max_positive_current
- Brake resistor logic now attempts to clamp voltage according to
odrv.config.dc_bus_overvoltage_ramp_start
andodrv.config.dc_bus_overvoltage_ramp_end
- Unit Testing with Doctest has been started for select algorithms, see Firmware/Tests/test_runner.cpp
- Added support for Flylint VSCode Extension for static code analysis
- Using an STM32F405 .svd file allows CortexDebug to view registers during debugging
- Added scripts for building via docker.
- Added ability to change uart baudrate via fibre
- Changed ratiometric
motor.config.current_lim_tolerance
to absolutemotor.config.current_lim_margin
- Moved
controller.vel_ramp_enable
to INPUT_MODE_VEL_RAMP. - Anticogging map is temporarily forced to 0.1 deg precision, but saves with the config
- Some Encoder settings have been made read-only
- Cleaned up VSCode C/C++ Configuration settings on Windows with recursive includePath
- Now compiling with C++17
- Fixed a firmware hang that could occur from unlikely but possible user input
- Added JSON caching to Fibre. This drastically reduces the time odrivetool needs to connect to an ODrive (except for the first time or after firmware updates).
- Fix IPython
RuntimeWarning
that would occur every timeodrivetool
was started. - Reboot on
erase_configuration()
. This avoids unexpected behavior of a subsequentsave_configuration()
call, since the configuration is only erased from NVM, not from RAM. - Change
motor.get_inverter_temp()
to use a property which was already being sampled atmotor.inverter_temp
- Fixed a numerical issue in the trajectory planner that could cause sudden jumps of the position setpoint
- Fixed a numerical issue in the trajectory planner that could cause sudden jumps of the position setpoint
- Separate lockin configs for sensorless, index search, and general.
- Check current limit violation: added
ERROR_CURRENT_UNSTABLE
,motor.config.current_lim_tolerance
.
- Ascii command for reboot changed from
sb
tosr
.
- Index search would trigger in the wrong place.
- A release target for ODrive v3.6
- Communication watchdog feature.
encoder.set_linear_count(count)
function.- Configurable encoder offset calibration distance and speed:
calib_scan_distance
andcalib_scan_omega
- Encoder offset calibration debug variable
calib_scan_response
- Lock-in drive feature
- Script to enable using a hall signal as index edge.
- Moved
traptraj.A_per_css
tocontroller.inertia
- Refactored velocity ramp mode into the new general input filtering structure
- Encoder index search now based on the new lock-in drive feature
- Encoder index interrupts now disabled when not searching
dump_errors()
utility function in odrivetool to dump, decode and optionally clear errors.f
command to ascii protocol to get encoder position and velocity feedback.q
command to ascii protocol. It is like the oldp
command, but velocity and current mean limits, not feed-forward.ss
,se
,sr
commands to ascii protocol, for save config, erase config and reboot.move_incremental
function for relative trajectory moves.encoder.config.ignore_illegal_hall_state
option.encoder.config.enable_phase_interpolation
option. Setting to false may reduce jerky pulsations at low speed when using hall sensor feedback.- Analog input. Used the same way as the PWM input mappings.
- Voltage limit soft clamping instead of ERROR_MODULATION_MAGNITUDE in gimbal motor closed loop.
- Thermal current limit with linear derating.
- Unified lockin drive modes. Current for index searching and encoder offset calibration now moved to axis.lockin.current.
- Added required 1.5 cycle phase shift between ADC and PWM, lack thereof caused unstable current controller at high eRPM.
- Overspeed fault
- Current sense saturation fault.
- Suppress startup transients by sampling encoder estimate into position setpoint when entering closed loop control.
- Make step dir gpio pins configurable.
- Configuration variable
encoder.config.zero_count_on_find_idx
, true by default. Set to false to leave the initial encoder count to be where the axis was at boot. - Circular position setpoint mode: position setpoints wrapped [0, cpr). Useful for infinite incremental position control.
- Velocity setpoint ramping. Use velocity control mode, and set
controller.vel_ramp_enable
to true. This will rampcontroller.vel_setpoint
towardscontroller.vel_ramp_target
at a ramp rate ofcontroller.config.vel_ramp_rate
.
- Increased switching frequency from around 8kHz to 24kHz. Control loops still run at 8kHz.
- Renamed
axis.enable_step_dir
toaxis.step_dir_active
- New process for working with STM32CubeMX.
- Would get ERROR_CONTROL_DEADLINE_MISSED along with every ERROR_PHASE_RESISTANCE_OUT_OF_RANGE.
- ODrive tool can now run interactive nested scripts with "%run -i script.py"
- Broken printing of floats on ascii protocol
- Trapezoidal Trajectory Planner
- Hook to execute protocol property written callback
- -Wdouble-promotion warning to compilation
- Make python tools compatible with python 2.7 (so it can be used with ROS)
- Threading API constructor can't take the daemon parameter, so all thread creation had to be expanded out.
TimeoutError
isn't defined, but it makes for more readable code, so I defined it as an OSError subclass.ModuleNotFoundError
is replaced by the older ImportError.- Print function imported from future
- Using new hooks to calculate:
motor.config.current_control_bandwidth
- This deprecates
motor.set_current_control_bandwidth()
- This deprecates
encoder.config.bandwidth
- Default value for
motor.resistance_calib_max_voltage
changed to 2.0
- An issue where the axis state machine would jump in and out of idle when there is an error
- There is a bug in the arm fast math library, which gives spikes in the output of arm_cos_f32 for input values close to -pi/2. We fixed the bug locally, and hence are using "our_arm_cos_f32".
- Serious reliability issue with USB communication where packets on Native and the CDC interface would collide with each other.
min_endstop
andmax_endstop
objects can be configured on GPIO- Axes can be homed if
min_endstop
is enabled - Encoder position count "homed" to zero when index is found.
- We now enforce encoder offset calibration must happen after index is found (if using index)
- Renaming of the velocity estimate
pll_vel
->vel_estimate
. - Hardcoded maximum inductance now 2500 uH.
- Incorrect shifting of offset during index callback
- Once you got an axis error
ERROR_INVALID_STATE
you could never clear it - Char to int conversion to read motornum on arduino example
- GPIO above #5 would not be used correctly in some cases
- Hall sensor feedback
- Configurable RC PWM input
- Ability to read axis FET temperature
- Config settings for:
motor.config.requested_current_range
motor.config.current_control_bandwidth
andmotor.set_current_control_bandwidth
. Latter required to invoke gain recalculation.encoder.config.bandwidth
sensorless_estimator.config.pm_flux_linkage
- Encoder errors would show up as Axis error
ERROR_MOTOR_FAILED
instead ofERROR_ENCODER_FAILED
. - Various pip install dependencies
- Ability for python tools threads to quit properly
- dfuse error prints now python3 compatible
- Encoder can now go forever in velocity/torque mode due to using circular encoder space.
- Protocol supports function return values
- bake Git-derived firmware version into firmware binary. The firmware version is exposed through the
fw_version_[...]
properties. make write_otp
command to burn the board version onto the ODrive's one-time programmable memory. If you have an ODrive v3.4 or older, you should run this once for a better firmware update user experience in the future. Run the command without any options for more details. Once set, the board version is exposed through thehw_version_[...]
properties.- infrastructure to publish the python tools to PyPi. See
tools/setup.py
for details. - Automated test script
run_tests.py
- System stats (e.g. stack usage) are exposed under
<odrv>.system_stats
- DFU script updates
- Verify the flash after writing
- Automatically download firmware from GitHub releases if no file is provided
- Retain configuration during firmware updates
- Refactor python tools
- The scripts
explore_odrive.py
,liveplotter.py
,drv_status.py
andrate_test.py
have been merged into one singleodrivetool
script. Running this script without any arguments provides the shell thatexplore_odrive.py
used to provide. - The command line options of
odrivetool
have changed compared to the originalexplore_odrive.py
. Seeodrivetool --help
for more details. odrivetool
(previouslyexplore_odrive.py
) now supports controlling multiple ODrives concurrently (odrv0
,odrv1
, ...)- No need to restart the
odrivetool
shell when devices get disconnected and reconnected - ODrive accesses from within python tools are now thread-safe. That means you can read from the same remote property from multiple threads concurrently.
- The liveplotter (
odrivetool liveplotter
, formerlyliveplotter.py
) does no longer steal focus and closes as expected - Add commands
odrivetool backup-config
andodrivetool restore-config
- (experimental: start liveplotter from
odrivetool
shell by typingstart_liveplotter(lambda: odrv0.motor0.encoder.encoder_state)
)
- The scripts
- Set thread priority of USB pump thread above protocol thread
- GPIO3 not sensitive to edges by default
- The device now appears as a composite device on USB. One subdevice is still a CDC device (virtual COM port), the other subdevice is a vendor specific class. This should resolve several issues that were caused by conflicting kernel drivers or OS services.
- Add WinUSB descriptors. This will tell Windows >= 8 to automatically load winusb.sys for the ODrive (only for the vendor specific subdevice). This makes it possible to use the ODrive from userspace via WinUSB with zero configuration. The Python tool currently still uses libusb so Zadig is still required.
- Add a configuration to enable the ASCII protocol on USB at runtime. This will only enable the ASCII protocol on the USB CDC subdevice, not the vendor specific subdevice so the python tools will still be able to talk to the ODrive.
- Enums now transported with correct underlying type on native protocol
- USB issue where the device would stop responding when the host script would quit abruptly or reset the device during operation
- Storing of configuration parameters to Non Volatile Memory
- USB Bootloader
make erase_config
to erase the configuration with an STLink (the configuration can also be erased from within explore_odrive.py, usingodrv0.erase_configuration()
)- Travis-CI builds firmware for all board versions and deploys the binaries when a tag is pushed to master
- General purpose ADC API. See function get_adc_voltage() in low_level.cpp for more detais.
- Most of the code from
lowlevel.c
moved toaxis.cpp
,encoder.cpp
,controller.cpp
,sensorless_estimator.cpp
,motor.cpp
and the corresponding header files - Refactoring of the developer-facing communication protocol interface. See e.g.
axis.hpp
orcontroller.hpp
for examples on how to add your own fields and functions - Change of the user-facing field paths. E.g.
my_odrive.motor0.pos_setpoint
is now atmy_odrive.axis0.controller.pos_setpoint
. Names are mostly unchanged. - Rewrite of the top-level per-axis state-machine
- The build is now configured using the
tup.config
file instead of editing source files. Make sure you set your board version correctly. See here for details. - The toplevel directory for tup is now
Firmware
. If you used tup before, go toFirmware
and runrm -rd ../.tup; rm -rd build/*; make
. - Update CubeMX generated STM platform code to version 1.19.0
- Remove
UUID_0
,UUID_1
andUUID_2
from USB protocol. Useserial_number
instead. - Freertos memory pool (task stacks, etc) now uses Core Coupled Memory.
- malloc now fails if we run out of memory (before it would always succeed even if we are out of ram...)
- Reporting error if your encoder CPR is incorrect
- Ability to start anticogging calibration over USB protocol
- Reporting of DRV status/control registers and fault codes
- DRV status read script
- Microsecond delay function
- Travis-CI
- Firmware update over USB
- Build system is now tup instead of make. Please check the Readme for installation instructions.
- Broken way to check for python 2. Python 2 not supported yet.
- Liveplotter script
- Automatic recovery of USB halt/stall condition
- Modified python code to be Python 2 compatible
- USB CSC (USB serial) now reports a sensible baud rate
- Gimbal motor mode
- Encoder index pulse support
resistance_calib_max_voltage
parameter
- UUID Endpoint
- Reporting of correct ODrive version on USB descriptor
- Getting started instructions for VSCode
- USB Product ID to 0x0D32, as it is the only Pid we were allocated on pid.codes
- Recommended method to debug firmware from VSCode now uses Cortex-Debug extension instead of native-debug.
- Refactor IDE instructions into separate files
- Bug where the remote function calls from Python to the ODrive were not working properly.
- New binary communication protocol
- This is a much richer and more efficient binary protocol than the old human-readable protocol.
- The old protocol is still available (but will be depricated eventually). You must manually chose to fall back on this protocol if you wish to still use it.
- Support for C++
- Demo scripts for getting started with commanding ODrive from python
- Protection from user setting current_lim higher than is measurable
- Current sense shunt values for HW v3.4
- Check DRV chip fault line
- Shunt resistance values for v3.3 and earlier to include extra resistance of PCB
- Default HW revision to v3.4
- Refactoring of control code:
- Lifted top layer of low_level.c into Axis.cpp
- Incorrect TIM14 interrupt mapping on board v3.2 caused hard-fault
- GPIO communication mode now defaults to NONE
- USB communication deadlock
- EXTI handler redefiniton in V3.2
- Resistance/inductance measurement now saved dispite errors, to allow debugging
- UART communication
- Setting to select UART or Step/dir on GIPIO 1,2
- Basic Anti-cogging
- Step/Dir interface
- this Changelog
- motor control interrupt timing diagram
- uint16 exposed variable type
- null termination to USB string parsing
- Fixed Resistance measurement bug
- Simplified motor control adc triggers
- Increased AUX bridge deadtime