Skip to content

Commit

Permalink
Merge branch 'devel' into control-loop-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelsadok committed Nov 3, 2020
2 parents e1c7ddb + 9594c47 commit 1f78154
Show file tree
Hide file tree
Showing 180 changed files with 31,514 additions and 3,974 deletions.
19 changes: 16 additions & 3 deletions .github/workflows/compile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,22 @@ jobs:
mv tup_build.sh tup_build.bat # in reality this is a .bat script on windows
.\tup_build.bat
#code-checks:
# runs-on: ubuntu-latest
# steps:
code-checks:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Check that we're not using std::isnan
run: |
cd ${{ github.workspace }}/Firmware
if grep 'std::isnan' -R .; then
echo "Don't use std::isnan because it's not compatible with '-ffast-math'. Use is_nan() instead."
return 1;
fi
# TODO:
# - check if enums.py is consistent with yaml
# - clang-format check
Expand Down
15 changes: 11 additions & 4 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build and publish HTML documentation website

on:
push:
branches: [ feature/doc_autogen ]
branches: [ master ]

jobs:
jekyll:
Expand Down Expand Up @@ -52,15 +52,22 @@ jobs:
cd /srv/jekyll/docs && \
bundle config path vendor/bundle && \
bundle install && \
JEKYLL_ENV=production bundle exec jekyll build
bundle exec jekyll build --baseurl \"\"
cd ..
mv docs/_site _site
rm -rdf docs
mv _site docs
touch docs/.nojekyll
"
touch .nojekyll
# Extra checks to reduce likelihood of defect build
test -f docs/CNAME
test -f docs/index.html
- name: Push to documentation branch
run: |
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git add -f docs/_site
git add -f docs
git commit -m "jekyll build from Action ${GITHUB_SHA}"
git push --force origin HEAD:${REMOTE_BRANCH}
env:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ Firmware/Tests/bin/
# GUI
GUI/dist_electron
GUI/node_modules
GUI/build
GUI/build
8 changes: 4 additions & 4 deletions Arduino/ODriveArduino/ODriveArduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ int32_t ODriveArduino::readInt() {
return readString().toInt();
}

bool ODriveArduino::run_state(int axis, int requested_state, bool wait) {
int timeout_ctr = 100;
bool ODriveArduino::run_state(int axis, int requested_state, bool wait_for_idle, float timeout) {
int timeout_ctr = (int)(timeout * 10.0f);
serial_ << "w axis" << axis << ".requested_state " << requested_state << '\n';
if (wait) {
if (wait_for_idle) {
do {
delay(100);
serial_ << "r axis" << axis << ".current_state\n";
} while (readInt() != requested_state && --timeout_ctr > 0);
} while (readInt() != AXIS_STATE_IDLE && --timeout_ctr > 0);
}

return timeout_ctr > 0;
Expand Down
2 changes: 1 addition & 1 deletion Arduino/ODriveArduino/ODriveArduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ODriveArduino {
int32_t readInt();

// State helper
bool run_state(int axis, int requested_state, bool wait);
bool run_state(int axis, int requested_state, bool wait_for_idle, float timeout = 10.0f);
private:
String readString();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@

// includes
#include <HardwareSerial.h>
#include <SoftwareSerial.h>
#include <ODriveArduino.h>

// Printing with stream operator
// Printing with stream operator helper functions
template<class T> inline Print& operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
template<> inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; }

// Serial to the ODrive
SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
// Note: you must also connect GND on ODrive to GND on Arduino!

////////////////////////////////
// Set up serial pins to the ODrive
////////////////////////////////

// Below are some sample configurations.
// You can comment out the default Teensy one and uncomment the one you wish to use.
// You can of course use something different if you like
// Don't forget to also connect ODrive GND to Arduino GND.

// Teensy 3 and 4 (all versions) - Serial1
// pin 0: RX - connect to ODrive TX
// pin 1: TX - connect to ODrive RX
// See https://www.pjrc.com/teensy/td_uart.html for other options on Teensy
HardwareSerial& odrive_serial = Serial1;

// Arduino Mega or Due - Serial1
// pin 19: RX - connect to ODrive TX
// pin 18: TX - connect to ODrive RX
// See https://www.arduino.cc/reference/en/language/functions/communication/serial/ for other options
// HardwareSerial& odrive_serial = Serial1;

// Arduino without spare serial ports (such as Arduino UNO) have to use software serial.
// Note that this is implemented poorly and can lead to wrong data sent or read.
// pin 8: RX - connect to ODrive TX
// pin 9: TX - connect to ODrive RX
// SoftwareSerial odrive_serial(8, 9);


// ODrive object
ODriveArduino odrive(odrive_serial);
Expand All @@ -28,7 +53,7 @@ void setup() {
// You can of course set them different if you want.
// See the documentation or play around in odrivetool to see the available parameters
for (int axis = 0; axis < 2; ++axis) {
odrive_serial << "w axis" << axis << ".controller.config.vel_limit " << 22000.0f << '\n';
odrive_serial << "w axis" << axis << ".controller.config.vel_limit " << 10.0f << '\n';
odrive_serial << "w axis" << axis << ".motor.config.current_lim " << 11.0f << '\n';
// This ends up writing something like "w axis0.motor.config.current_lim 10.0\n"
}
Expand All @@ -52,23 +77,23 @@ void loop() {

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

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

requested_state = ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL;
Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
odrive.run_state(motornum, requested_state, false); // don't wait
if(!odrive.run_state(motornum, requested_state, false /*don't wait*/)) return;
}

// Sinusoidal test move
if (c == 's') {
Serial.println("Executing test move");
for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
float pos_m0 = 20000.0f * cos(ph);
float pos_m1 = 20000.0f * sin(ph);
float pos_m0 = 2.0f * cos(ph);
float pos_m1 = 2.0f * sin(ph);
odrive.SetPosition(0, pos_m0);
odrive.SetPosition(1, pos_m1);
delay(5);
Expand Down
24 changes: 17 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
Please add a note of your changes below this heading if you make a Pull Request.
### Added
* [Mechanical brake support](docs/mechanical-brakes.md)
* Added periodic sending of encoder position on CAN

### Changed

* Modified encoder offset calibration to work correctly when calib_scan_distance is not a multiple of 4pi
* Moved thermistors from being a top level object to belonging to Motor objects. Also changed errors: thermistor errors rolled into motor errors
* Use DMA for DRV8301 setup
* Make NVM configuration code more dynamic so that the layout doesn't have to be known at compile time.
* GPIO initialization logic was changed. GPIOs now need to be explicitly set to the mode corresponding to the feature that they are used by. See `<odrv>.config.gpioX_mode`.
Expand All @@ -24,12 +26,16 @@ Please add a note of your changes below this heading if you make a Pull Request.
* More informative profiling instrumentation was added.
* A system-level error property was introduced.

### API Miration Notes
### API Migration Notes

* `odrive.axis.fet_thermistor`, `odrive.axis.motor_thermistor` moved to `odrive.axis.motor` object
* `enable_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()`.
* Several error flags from `<odrv>.<axis>.error` were removed. Some were moved to `<odrv>.error` and some are no longer relevant because implementation details changed.
* Several error flags from `<odrv>.<axis>.motor.error` were removed. Some were moved to `<odrv>.error` and some are no longer relevant because implementation details changed.
Expand All @@ -48,30 +54,34 @@ Please add a note of your changes below this heading if you make a Pull Request.
* `<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>.async_estimator.config.slip_velocity`.
* `<axis>.encoder.config.idx_search_unidirectional` was removed. Offset calibration direction is fully defined by the sign of `<axis>.encoder.config.calib_scan_omega` and how the motor is wired up.
* The unit of `<axis>.sensorless_estimator.vel_estimate` was changed from `rad/s` to `turns/s`.
* Several properties were changed to readonly.
* `<axis>.encoder.config.offset` was renamed to ``<axis>.encoder.config.phase_offset`
* `<axis>.encoder.config.offset_float` was renamed to ``<axis>.encoder.config.phase_offset_float`

# Release Candidate
## [0.5.1] - Date TBD
# Releases
## [0.5.1] - 2020-09-27
### Added
* Added motor `torque_constant`: units of torque are now [Nm] instead of just motor current.
* Added `motor.config.torque_lim`: limit for motor torque in [Nm].
* [Motor thermistors support](docs/thermistors.md)
* Enable/disable of thermistor thermal limits according `setting axis.<thermistor>.enabled`.
* Introduced `odrive-interface.yaml` as a root source for the ODrive's API. `odrivetool` connects much faster as a side effect.
* Added torque_constant and torque_lim to motor config

### Changed
* **`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]**
* **`pos_gain`, `vel_gain`, `vel_integrator_gain`, are now in units of [(turns/s) / turns], [Nm/(turns/s)], [Nm/(turns/s * s)] instead of [(counts/s) / counts], [A/(counts/s)], [A/((counts/s) * s)].** `pos_gain` is not affected. Old values of `vel_gain` and `vel_integrator_gain` should be multiplied by `torque_constant * encoder cpr` to convert from the old units to the new units. `torque_constant` is approximately equal to 8.27 / (motor KV).
* `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`
* Outputs of `axis.sensorless_estimator` are now in turns/s instead of electrical rad/s
* Fixed bug of high current during lockin-ramp caused by `motor::update()` expecting a torque command instead of current
* Fixed bug where commanded velocity was extremely high just after sensorless ramp when using `input_mode` INPUT_MODE_VEL_RAMP caused by `vel_setpoint` and `axis.config.sensorless_ramp.vel` being in different units

### Fixed
* Fixed bug of high current during lockin-ramp caused by `motor::update()` expecting a torque command instead of current
* Fixed bug where commanded velocity was extremely high just after sensorless ramp when using `input_mode` INPUT_MODE_VEL_RAMP caused by `vel_setpoint` and `axis.config.sensorless_ramp.vel` being in different units

# Releases
## [0.5.0] - 2020-08-03
### Added
* AC Induction Motor support.
Expand Down
20 changes: 13 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa
RUN add-apt-repository ppa:jonathonf/tup
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install gcc-arm-embedded openocd tup python3.7 build-essential git
RUN apt-get -y install gcc-arm-embedded openocd tup python3.7 python3-yaml python3-jinja2 python3-jsonschema build-essential git

# Build step below does not know about debian's python naming schemme
RUN ln -s /usr/bin/python3.7 /usr/bin/python

# Copy the firmware tree into the container
RUN mkdir ODrive
COPY . ODrive
RUN mkdir -p ODrive
WORKDIR ODrive/Firmware

# Hack around Tup's dependency on FUSE
RUN tup generate build.sh
RUN ./build.sh
# Must attach the firmware tree into the container
CMD \
# Regenerate python interface
python interface_generator_stub.py \
--definitions odrive-interface.yaml \
--template ../tools/enums_template.j2 \
--output ../tools/odrive/enums.py && \
# Hack around Tup's dependency on FUSE
tup init && \
tup generate build.sh && \
./build.sh
27 changes: 21 additions & 6 deletions Firmware/.vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@
"${workspaceFolder}/**"
],
"defines": [
"__arm__",
"STM32F405xx",
"FPU_FPV4",
"USE_HAL_DRIVER",
"HW_VERSION_MAJOR=3",
"HW_VERSION_MINOR=6",
"HW_VERSION_VOLTAGE=56",
"USB_PROTOCOL_NATIVE",
"__weak=\"__attribute__((weak))\"",
"__packed=\"__attribute__((__packed__))\"",
"__GNUC__"
],
"intelliSenseMode": "gcc-x64",
"compilerPath": "\"${ARM_GCC_ROOT}/bin/arm-none-eabi-g++.exe\" -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float",
"intelliSenseMode": "gcc-arm",
"compilerPath": "arm-none-eabi-g++.exe",
"compilerArgs": [
"-mthumb",
"-mcpu=cortex-m4",
"-mfpu=fpv4-sp-d16",
"-mfloat-abi=hard",
"-specs=nosys.specs",
"-specs=nano.specs",
"-u _printf_float",
"-u _scanf_float"
],
"cStandard": "c11",
"cppStandard": "c++17"
},
Expand All @@ -27,7 +38,9 @@
"${workspaceFolder}/**"
],
"defines": [
"__arm__",
"STM32F405xx",
"FPU_FPV4",
"USE_HAL_DRIVER",
"HW_VERSION_MAJOR=3",
"HW_VERSION_MINOR=6",
Expand All @@ -36,7 +49,7 @@
"__packed=\"__attribute__((__packed__))\"",
"__GNUC__"
],
"intelliSenseMode": "gcc-x64",
"intelliSenseMode": "gcc-arm",
"compilerPath": "arm-none-eabi-g++ -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float",
"cStandard": "c11",
"cppStandard": "c++17"
Expand All @@ -47,16 +60,18 @@
"${workspaceFolder}/**"
],
"defines": [
"__arm__",
"STM32F405xx",
"FPU_FPV4",
"USE_HAL_DRIVER",
"HW_VERSION_MAJOR=3",
"HW_VERSION_MINOR=4",
"HW_VERSION_VOLTAGE=24",
"HW_VERSION_VOLTAGE=56",
"__weak=\"__attribute__((weak))\"",
"__packed=\"__attribute__((__packed__))\"",
"__GNUC__"
],
"intelliSenseMode": "gcc-x64",
"intelliSenseMode": "gcc-arm",
"cStandard": "c11",
"cppStandard": "c++17"
}
Expand Down
Loading

0 comments on commit 1f78154

Please sign in to comment.