Skip to content

Commit

Permalink
Merge pull request #601 from odriverobotics/fw-v0.5.3
Browse files Browse the repository at this point in the history
Firmware v0.5.3
  • Loading branch information
samuelsadok authored Sep 3, 2021
2 parents 5bd221e + ebacf50 commit c58aeee
Show file tree
Hide file tree
Showing 60 changed files with 1,391 additions and 376 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/compile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [master, devel]
tags: ['fw-v*']
push:
branches: [master, devel]
branches: [master, devel, 'fw-v*']
tags: ['fw-v*']

jobs:
Expand Down Expand Up @@ -112,6 +112,16 @@ jobs:
mv tup_build.sh tup_build.bat # in reality this is a .bat script on windows
.\tup_build.bat
- name: Upload binary
if: ${{ matrix.os == 'ubuntu-latest' && matrix.debug == false }}
uses: actions/upload-artifact@v2
with:
name: firmware-${{ matrix.board_version }}
path: |
Firmware/build/ODriveFirmware.elf
Firmware/build/ODriveFirmware.bin
Firmware/build/ODriveFirmware.hex
code-checks:
strategy:
fail-fast: false
Expand Down
4 changes: 0 additions & 4 deletions .gitmodules

This file was deleted.

9 changes: 7 additions & 2 deletions Arduino/ODriveArduino/ODriveArduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,24 @@ void ODriveArduino::SetCurrent(int motor_number, float current) {
serial_ << "c " << motor_number << " " << current << "\n";
}

void ODriveArduino::TrapezoidalMove(int motor_number, float position){
void ODriveArduino::TrapezoidalMove(int motor_number, float position) {
serial_ << "t " << motor_number << " " << position << "\n";
}

float ODriveArduino::readFloat() {
return readString().toFloat();
}

float ODriveArduino::GetVelocity(int motor_number){
float ODriveArduino::GetVelocity(int motor_number) {
serial_<< "r axis" << motor_number << ".encoder.vel_estimate\n";
return ODriveArduino::readFloat();
}

float ODriveArduino::GetPosition(int motor_number) {
serial_ << "r axis" << motor_number << ".encoder.pos_estimate\n";
return ODriveArduino::readFloat();
}

int32_t ODriveArduino::readInt() {
return readString().toInt();
}
Expand Down
14 changes: 2 additions & 12 deletions Arduino/ODriveArduino/ODriveArduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,10 @@
#define ODriveArduino_h

#include "Arduino.h"
#include "ODriveEnums.h"

class ODriveArduino {
public:
enum AxisState_t {
AXIS_STATE_UNDEFINED = 0, //<! will fall through to idle
AXIS_STATE_IDLE = 1, //<! disable PWM and do nothing
AXIS_STATE_STARTUP_SEQUENCE = 2, //<! the actual sequence is defined by the config.startup_... flags
AXIS_STATE_FULL_CALIBRATION_SEQUENCE = 3, //<! run all calibration procedures, then idle
AXIS_STATE_MOTOR_CALIBRATION = 4, //<! run motor calibration
AXIS_STATE_SENSORLESS_CONTROL = 5, //<! run sensorless control
AXIS_STATE_ENCODER_INDEX_SEARCH = 6, //<! run encoder index search
AXIS_STATE_ENCODER_OFFSET_CALIBRATION = 7, //<! run encoder offset calibration
AXIS_STATE_CLOSED_LOOP_CONTROL = 8 //<! run closed loop control
};

ODriveArduino(Stream& serial);

// Commands
Expand All @@ -30,6 +19,7 @@ class ODriveArduino {
void TrapezoidalMove(int motor_number, float position);
// Getters
float GetVelocity(int motor_number);
float GetPosition(int motor_number);
// General params
float readFloat();
int32_t readInt();
Expand Down
199 changes: 199 additions & 0 deletions Arduino/ODriveArduino/ODriveEnums.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@

#ifndef ODriveEnums_h
#define ODriveEnums_h

/* TODO: This file is dangerous because the enums could potentially change between API versions. Should transmit as part of the JSON.
** To regenerate this file, nagivate to the top level of the ODrive repository and run:
** python Firmware/interface_generator_stub.py --definitions Firmware/odrive-interface.yaml --template tools/arduino_enums_template.j2 --output Arduino/ODriveArduino/ODriveEnums.h
*/

// ODrive.GpioMode
enum GpioMode {
GPIO_MODE_DIGITAL = 0,
GPIO_MODE_DIGITAL_PULL_UP = 1,
GPIO_MODE_DIGITAL_PULL_DOWN = 2,
GPIO_MODE_ANALOG_IN = 3,
GPIO_MODE_UART_A = 4,
GPIO_MODE_UART_B = 5,
GPIO_MODE_UART_C = 6,
GPIO_MODE_CAN_A = 7,
GPIO_MODE_I2C_A = 8,
GPIO_MODE_SPI_A = 9,
GPIO_MODE_PWM = 10,
GPIO_MODE_ENC0 = 11,
GPIO_MODE_ENC1 = 12,
GPIO_MODE_ENC2 = 13,
GPIO_MODE_MECH_BRAKE = 14,
GPIO_MODE_STATUS = 15,
};

// ODrive.StreamProtocolType
enum StreamProtocolType {
STREAM_PROTOCOL_TYPE_FIBRE = 0,
STREAM_PROTOCOL_TYPE_ASCII = 1,
STREAM_PROTOCOL_TYPE_STDOUT = 2,
STREAM_PROTOCOL_TYPE_ASCII_AND_STDOUT = 3,
};

// ODrive.Can.Protocol
enum Protocol {
PROTOCOL_SIMPLE = 0x00000001,
};

// ODrive.Axis.AxisState
enum AxisState {
AXIS_STATE_UNDEFINED = 0,
AXIS_STATE_IDLE = 1,
AXIS_STATE_STARTUP_SEQUENCE = 2,
AXIS_STATE_FULL_CALIBRATION_SEQUENCE = 3,
AXIS_STATE_MOTOR_CALIBRATION = 4,
AXIS_STATE_ENCODER_INDEX_SEARCH = 6,
AXIS_STATE_ENCODER_OFFSET_CALIBRATION = 7,
AXIS_STATE_CLOSED_LOOP_CONTROL = 8,
AXIS_STATE_LOCKIN_SPIN = 9,
AXIS_STATE_ENCODER_DIR_FIND = 10,
AXIS_STATE_HOMING = 11,
AXIS_STATE_ENCODER_HALL_POLARITY_CALIBRATION = 12,
AXIS_STATE_ENCODER_HALL_PHASE_CALIBRATION = 13,
};

// ODrive.Encoder.Mode
enum EncoderMode {
ENCODER_MODE_INCREMENTAL = 0,
ENCODER_MODE_HALL = 1,
ENCODER_MODE_SINCOS = 2,
ENCODER_MODE_SPI_ABS_CUI = 256,
ENCODER_MODE_SPI_ABS_AMS = 257,
ENCODER_MODE_SPI_ABS_AEAT = 258,
ENCODER_MODE_SPI_ABS_RLS = 259,
ENCODER_MODE_SPI_ABS_MA732 = 260,
};

// ODrive.Controller.ControlMode
enum ControlMode {
CONTROL_MODE_VOLTAGE_CONTROL = 0,
CONTROL_MODE_TORQUE_CONTROL = 1,
CONTROL_MODE_VELOCITY_CONTROL = 2,
CONTROL_MODE_POSITION_CONTROL = 3,
};

// ODrive.Controller.InputMode
enum InputMode {
INPUT_MODE_INACTIVE = 0,
INPUT_MODE_PASSTHROUGH = 1,
INPUT_MODE_VEL_RAMP = 2,
INPUT_MODE_POS_FILTER = 3,
INPUT_MODE_MIX_CHANNELS = 4,
INPUT_MODE_TRAP_TRAJ = 5,
INPUT_MODE_TORQUE_RAMP = 6,
INPUT_MODE_MIRROR = 7,
INPUT_MODE_TUNING = 8,
};

// ODrive.Motor.MotorType
enum MotorType {
MOTOR_TYPE_HIGH_CURRENT = 0,
MOTOR_TYPE_GIMBAL = 2,
MOTOR_TYPE_ACIM = 3,
};

// ODrive.Error
enum ODriveError {
ODRIVE_ERROR_NONE = 0x00000000,
ODRIVE_ERROR_CONTROL_ITERATION_MISSED = 0x00000001,
ODRIVE_ERROR_DC_BUS_UNDER_VOLTAGE = 0x00000002,
ODRIVE_ERROR_DC_BUS_OVER_VOLTAGE = 0x00000004,
ODRIVE_ERROR_DC_BUS_OVER_REGEN_CURRENT = 0x00000008,
ODRIVE_ERROR_DC_BUS_OVER_CURRENT = 0x00000010,
ODRIVE_ERROR_BRAKE_DEADTIME_VIOLATION = 0x00000020,
ODRIVE_ERROR_BRAKE_DUTY_CYCLE_NAN = 0x00000040,
ODRIVE_ERROR_INVALID_BRAKE_RESISTANCE = 0x00000080,
};

// ODrive.Can.Error
enum CanError {
CAN_ERROR_NONE = 0x00000000,
CAN_ERROR_DUPLICATE_CAN_IDS = 0x00000001,
};

// ODrive.Axis.Error
enum AxisError {
AXIS_ERROR_NONE = 0x00000000,
AXIS_ERROR_INVALID_STATE = 0x00000001,
AXIS_ERROR_WATCHDOG_TIMER_EXPIRED = 0x00000800,
AXIS_ERROR_MIN_ENDSTOP_PRESSED = 0x00001000,
AXIS_ERROR_MAX_ENDSTOP_PRESSED = 0x00002000,
AXIS_ERROR_ESTOP_REQUESTED = 0x00004000,
AXIS_ERROR_HOMING_WITHOUT_ENDSTOP = 0x00020000,
AXIS_ERROR_OVER_TEMP = 0x00040000,
AXIS_ERROR_UNKNOWN_POSITION = 0x00080000,
};

// ODrive.Motor.Error
enum MotorError {
MOTOR_ERROR_NONE = 0x00000000,
MOTOR_ERROR_PHASE_RESISTANCE_OUT_OF_RANGE = 0x00000001,
MOTOR_ERROR_PHASE_INDUCTANCE_OUT_OF_RANGE = 0x00000002,
MOTOR_ERROR_DRV_FAULT = 0x00000008,
MOTOR_ERROR_CONTROL_DEADLINE_MISSED = 0x00000010,
MOTOR_ERROR_MODULATION_MAGNITUDE = 0x00000080,
MOTOR_ERROR_CURRENT_SENSE_SATURATION = 0x00000400,
MOTOR_ERROR_CURRENT_LIMIT_VIOLATION = 0x00001000,
MOTOR_ERROR_MODULATION_IS_NAN = 0x00010000,
MOTOR_ERROR_MOTOR_THERMISTOR_OVER_TEMP = 0x00020000,
MOTOR_ERROR_FET_THERMISTOR_OVER_TEMP = 0x00040000,
MOTOR_ERROR_TIMER_UPDATE_MISSED = 0x00080000,
MOTOR_ERROR_CURRENT_MEASUREMENT_UNAVAILABLE = 0x00100000,
MOTOR_ERROR_CONTROLLER_FAILED = 0x00200000,
MOTOR_ERROR_I_BUS_OUT_OF_RANGE = 0x00400000,
MOTOR_ERROR_BRAKE_RESISTOR_DISARMED = 0x00800000,
MOTOR_ERROR_SYSTEM_LEVEL = 0x01000000,
MOTOR_ERROR_BAD_TIMING = 0x02000000,
MOTOR_ERROR_UNKNOWN_PHASE_ESTIMATE = 0x04000000,
MOTOR_ERROR_UNKNOWN_PHASE_VEL = 0x08000000,
MOTOR_ERROR_UNKNOWN_TORQUE = 0x10000000,
MOTOR_ERROR_UNKNOWN_CURRENT_COMMAND = 0x20000000,
MOTOR_ERROR_UNKNOWN_CURRENT_MEASUREMENT = 0x40000000,
MOTOR_ERROR_UNKNOWN_VBUS_VOLTAGE = 0x80000000,
MOTOR_ERROR_UNKNOWN_VOLTAGE_COMMAND = 0x100000000,
MOTOR_ERROR_UNKNOWN_GAINS = 0x200000000,
MOTOR_ERROR_CONTROLLER_INITIALIZING = 0x400000000,
MOTOR_ERROR_UNBALANCED_PHASES = 0x800000000,
};

// ODrive.Controller.Error
enum ControllerError {
CONTROLLER_ERROR_NONE = 0x00000000,
CONTROLLER_ERROR_OVERSPEED = 0x00000001,
CONTROLLER_ERROR_INVALID_INPUT_MODE = 0x00000002,
CONTROLLER_ERROR_UNSTABLE_GAIN = 0x00000004,
CONTROLLER_ERROR_INVALID_MIRROR_AXIS = 0x00000008,
CONTROLLER_ERROR_INVALID_LOAD_ENCODER = 0x00000010,
CONTROLLER_ERROR_INVALID_ESTIMATE = 0x00000020,
CONTROLLER_ERROR_INVALID_CIRCULAR_RANGE = 0x00000040,
CONTROLLER_ERROR_SPINOUT_DETECTED = 0x00000080,
};

// ODrive.Encoder.Error
enum EncoderError {
ENCODER_ERROR_NONE = 0x00000000,
ENCODER_ERROR_UNSTABLE_GAIN = 0x00000001,
ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH = 0x00000002,
ENCODER_ERROR_NO_RESPONSE = 0x00000004,
ENCODER_ERROR_UNSUPPORTED_ENCODER_MODE = 0x00000008,
ENCODER_ERROR_ILLEGAL_HALL_STATE = 0x00000010,
ENCODER_ERROR_INDEX_NOT_FOUND_YET = 0x00000020,
ENCODER_ERROR_ABS_SPI_TIMEOUT = 0x00000040,
ENCODER_ERROR_ABS_SPI_COM_FAIL = 0x00000080,
ENCODER_ERROR_ABS_SPI_NOT_READY = 0x00000100,
ENCODER_ERROR_HALL_NOT_CALIBRATED_YET = 0x00000200,
};

// ODrive.SensorlessEstimator.Error
enum SensorlessEstimatorError {
SENSORLESS_ESTIMATOR_ERROR_NONE = 0x00000000,
SENSORLESS_ESTIMATOR_ERROR_UNSTABLE_GAIN = 0x00000001,
SENSORLESS_ESTIMATOR_ERROR_UNKNOWN_CURRENT_MEASUREMENT = 0x00000002,
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ void loop() {
int motornum = c-'0';
int requested_state;

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

requested_state = ODriveArduino::AXIS_STATE_ENCODER_OFFSET_CALIBRATION;
requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION;
Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
if(!odrive.run_state(motornum, requested_state, true, 25.0f)) return;

requested_state = ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL;
requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL;
Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
if(!odrive.run_state(motornum, requested_state, false /*don't wait*/)) return;
}
Expand Down Expand Up @@ -112,8 +112,7 @@ void loop() {
unsigned long start = millis();
while(millis() - start < duration) {
for (int motor = 0; motor < 2; ++motor) {
odrive_serial << "r axis" << motor << ".encoder.pos_estimate\n";
Serial << odrive.readFloat() << '\t';
Serial << odrive.GetPosition(motor) << '\t';
}
Serial << '\n';
}
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# Unreleased Features
Please add a note of your changes below this heading if you make a Pull Request.

# Releases
## [0.5.3] - 2021-09-03

### Fixed
* ASCII protocol commands with multiline responses (`i`, `h`) now return the expected response (in v0.5.2 the response was corrupted)
* odrivetool no longer shows the message `<Task pending coro=... running at ...>` when closing
* Homing used to erroneously complete with `is_homed == True` even if it failed for some reason
* When entering closed loop control in trapezoidal trajectory mode the axis no longer snaps to the 0 position
* Fix python DFU firmware version prerelease status resolution to use correct attribute
* Fixed firmware compiled-in version number

### Added
* `brake_resistor_current` added to interface for reading the commanded brake resistor current

### Changed
* Removed `odrivetool generate-code`. This feature was broken in 0.5.2. Use [`interface_generator.py`](https://github.com/odriverobotics/ODrive/blob/master/tools/fibre-tools/interface_generator.py) instead (see Tupfile.lua for examples).
* Firmware boots on devices with unset OTP.
* Changed CAN heartbeat message to include "trajectory done" flag

# Releases
## [0.5.2] - 2021-05-21

Expand All @@ -27,6 +46,8 @@ Please add a note of your changes below this heading if you make a Pull Request.
* Added torque mirroring to INPUT_MODE_MIRROR
* `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`.
* Added autogenerated enums header file [ODriveEnums.h](../Arduino/ODriveArduino/ODriveEnums.h) for Arduino use. Created Jinja template and edited Makefile to autogenerate it. Reflected change in Dockerfile and added note in developer-guide markdown file for updating ODriveEnums.h alongside enums.py.
* Added GetPosition member function in ODriveArduino class to complement existing GetVelocity, SetVelocity, and SetPosition functions.

### Changed
* Step/dir performance improved! Dual axis step rates up to 250kHz have been tested
Expand Down Expand Up @@ -55,6 +76,9 @@ Please add a note of your changes below this heading if you make a Pull Request.
* Added `torque_mirror_ratio` and use it to feed-forward `controller_.torque_output` in `INPUT_MODE_MIRROR`
* Accumulate integer steps in step/dir to avoid float precision errors
* Circular setpoint mode must be enabled when the step/dir interface is used.
* Replaced inline enum in ODriveArduino class by including new autogenerated ODriveEnums.h header file.
* Changed the example ODriveArduinoTest.ino file to reflect the new GetPosition member function. Also removed the scope resolution operator to access the enums as it can now be accessed from the global namespace.
* `save_configuration()` reboots the board.

### API Migration Notes
* `axis.config.turns_per_step` changed to `axis.controller.config.steps_per_circular_range`
Expand Down
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ CMD \
--definitions odrive-interface.yaml \
--template ../tools/enums_template.j2 \
--output ../tools/odrive/enums.py && \
python interface_generator_stub.py \
--definitions odrive-interface.yaml \
--template ../tools/arduino_enums_template.j2 \
--output ../Arduino/ODriveArduino/ODriveEnums.h && \
# Hack around Tup's dependency on FUSE
tup init && \
tup generate build.sh && \
Expand Down
Loading

0 comments on commit c58aeee

Please sign in to comment.