Skip to content

Commit 6088b8d

Browse files
committed
Merge branch 'devel' into libfibre
2 parents 204b6c3 + efa8b30 commit 6088b8d

File tree

133 files changed

+24051
-801
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+24051
-801
lines changed

.github/workflows/documentation.yml

+11-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Build and publish HTML documentation website
22

33
on:
44
push:
5-
branches: [ feature/doc_autogen ]
5+
branches: [ master ]
66

77
jobs:
88
jekyll:
@@ -52,15 +52,22 @@ jobs:
5252
cd /srv/jekyll/docs && \
5353
bundle config path vendor/bundle && \
5454
bundle install && \
55-
JEKYLL_ENV=production bundle exec jekyll build
55+
bundle exec jekyll build --baseurl \"\"
56+
cd ..
57+
mv docs/_site _site
58+
rm -rdf docs
59+
mv _site docs
60+
touch docs/.nojekyll
5661
"
57-
touch .nojekyll
62+
# Extra checks to reduce likelihood of defect build
63+
test -f docs/CNAME
64+
test -f docs/index.html
5865
5966
- name: Push to documentation branch
6067
run: |
6168
git config user.name "${GITHUB_ACTOR}"
6269
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
63-
git add -f docs/_site
70+
git add -f docs
6471
git commit -m "jekyll build from Action ${GITHUB_SHA}"
6572
git push --force origin HEAD:${REMOTE_BRANCH}
6673
env:

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,8 @@ ODrive\.files
5858
ODrive\.includes
5959

6060
Firmware/Tests/bin/
61+
62+
# GUI
63+
GUI/dist_electron
64+
GUI/node_modules
65+
GUI/build

Arduino/ODriveArduino/ODriveArduino.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ int32_t ODriveArduino::readInt() {
5959
return readString().toInt();
6060
}
6161

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

7272
return timeout_ctr > 0;

Arduino/ODriveArduino/ODriveArduino.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ODriveArduino {
3535
int32_t readInt();
3636

3737
// State helper
38-
bool run_state(int axis, int requested_state, bool wait);
38+
bool run_state(int axis, int requested_state, bool wait_for_idle, float timeout = 10.0f);
3939
private:
4040
String readString();
4141

Arduino/ODriveArduino/examples/ODriveArduinoTest/ODriveArduinoTest.ino

+37-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,39 @@
1-
1+
// includes
2+
#include <HardwareSerial.h>
23
#include <SoftwareSerial.h>
34
#include <ODriveArduino.h>
4-
5-
// Printing with stream operator
5+
// Printing with stream operator helper functions
66
template<class T> inline Print& operator <<(Print &obj, T arg) { obj.print(arg); return obj; }
77
template<> inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; }
88

9-
// Serial to the ODrive
10-
SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
11-
// Note: you must also connect GND on ODrive to GND on Arduino!
9+
10+
////////////////////////////////
11+
// Set up serial pins to the ODrive
12+
////////////////////////////////
13+
14+
// Below are some sample configurations.
15+
// You can comment out the default Teensy one and uncomment the one you wish to use.
16+
// You can of course use something different if you like
17+
// Don't forget to also connect ODrive GND to Arduino GND.
18+
19+
// Teensy 3 and 4 (all versions) - Serial1
20+
// pin 0: RX - connect to ODrive TX
21+
// pin 1: TX - connect to ODrive RX
22+
// See https://www.pjrc.com/teensy/td_uart.html for other options on Teensy
23+
HardwareSerial& odrive_serial = Serial1;
24+
25+
// Arduino Mega or Due - Serial1
26+
// pin 19: RX - connect to ODrive TX
27+
// pin 18: TX - connect to ODrive RX
28+
// See https://www.arduino.cc/reference/en/language/functions/communication/serial/ for other options
29+
// HardwareSerial& odrive_serial = Serial1;
30+
31+
// Arduino without spare serial ports (such as Arduino UNO) have to use software serial.
32+
// Note that this is implemented poorly and can lead to wrong data sent or read.
33+
// pin 8: RX - connect to ODrive TX
34+
// pin 9: TX - connect to ODrive RX
35+
// SoftwareSerial odrive_serial(8, 9);
36+
1237

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

5378
requested_state = ODriveArduino::AXIS_STATE_MOTOR_CALIBRATION;
5479
Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
55-
odrive.run_state(motornum, requested_state, true);
80+
if(!odrive.run_state(motornum, requested_state, true)) return;
5681

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

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

6691
// Sinusoidal test move
6792
if (c == 's') {
6893
Serial.println("Executing test move");
6994
for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
70-
float pos_m0 = 20000.0f * cos(ph);
71-
float pos_m1 = 20000.0f * sin(ph);
95+
float pos_m0 = 2.0f * cos(ph);
96+
float pos_m1 = 2.0f * sin(ph);
7297
odrive.SetPosition(0, pos_m0);
7398
odrive.SetPosition(1, pos_m1);
7499
delay(5);

CHANGELOG.md

+18-5
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,51 @@
22
Please add a note of your changes below this heading if you make a Pull Request.
33
### Added
44
* [Mechanical brake support](docs/mechanical-brakes.md)
5+
* Added periodic sending of encoder position on CAN
56

67
### Changed
7-
8+
* Modified encoder offset calibration to work correctly when calib_scan_distance is not a multiple of 4pi
9+
* Moved thermistors from being a top level object to belonging to Motor objects. Also changed errors: thermistor errors rolled into motor errors
810
* Use DMA for DRV8301 setup
911
* Make NVM configuration code more dynamic so that the layout doesn't have to be known at compile time.
1012
* 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`.
1113
* Previously, if two components used the same interrupt pin (e.g. step input for axis0 and axis1) then the one that was configured later would override the other one. Now this is no longer the case (the old component remains the owner of the pin).
1214

13-
### API Miration Notes
15+
### API Migration Notes
1416

17+
* `odrive.axis.fet_thermistor`, `odrive.axis.motor_thermistor` moved to `odrive.axis.motor` object
1518
* `enable_uart` and `uart_baudrate` were renamed to `enable_uart0` and `uart0_baudrate`.
1619
* `enable_i2c_instead_of_can` was replaced by the separate settings `enable_i2c0` and `enable_can0`.
1720
* `<axis>.motor.gate_driver` was moved to `<axis>.gate_driver`.
1821
* `<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.
22+
* `<axis>.config.can_node_id` was moved to `<axis>.config.can.node_id`
23+
* `<axis>.config.can_node_id_extended` was moved to `<axis>.config.can.is_extended`
24+
* `<axis>.config.can_heartbeat_rate_ms` was moved to `<axis>.config.can.heartbeat_rate_ms`
1925

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

2936
### Changed
3037
* **`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]**
38+
* **`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).
3139
* `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.
3240
* `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.
3341
* `axis.config.counts_per_step` is now `axis.config.turns_per_step`
42+
* Outputs of `axis.sensorless_estimator` are now in turns/s instead of electrical rad/s
43+
* Fixed bug of high current during lockin-ramp caused by `motor::update()` expecting a torque command instead of current
44+
* 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
3445

46+
### Fixed
47+
* Fixed bug of high current during lockin-ramp caused by `motor::update()` expecting a torque command instead of current
48+
* 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
3549

36-
# Releases
3750
## [0.5.0] - 2020-08-03
3851
### Added
3952
* AC Induction Motor support.

Dockerfile

+13-7
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@ RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa
77
RUN add-apt-repository ppa:jonathonf/tup
88
RUN apt-get update
99
RUN apt-get -y upgrade
10-
RUN apt-get -y install gcc-arm-embedded openocd tup python3.7 build-essential git
10+
RUN apt-get -y install gcc-arm-embedded openocd tup python3.7 python3-yaml python3-jinja2 python3-jsonschema build-essential git
1111

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

15-
# Copy the firmware tree into the container
16-
RUN mkdir ODrive
17-
COPY . ODrive
15+
RUN mkdir -p ODrive
1816
WORKDIR ODrive/Firmware
1917

20-
# Hack around Tup's dependency on FUSE
21-
RUN tup generate build.sh
22-
RUN ./build.sh
18+
# Must attach the firmware tree into the container
19+
CMD \
20+
# Regenerate python interface
21+
python interface_generator_stub.py \
22+
--definitions odrive-interface.yaml \
23+
--template ../tools/enums_template.j2 \
24+
--output ../tools/odrive/enums.py && \
25+
# Hack around Tup's dependency on FUSE
26+
tup init && \
27+
tup generate build.sh && \
28+
./build.sh

Firmware/.vscode/c_cpp_properties.json

+14-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,18 @@
1717
"__packed=\"__attribute__((__packed__))\"",
1818
"__GNUC__"
1919
],
20-
"intelliSenseMode": "gcc-x64",
21-
"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",
20+
"intelliSenseMode": "gcc-arm",
21+
"compilerPath": "arm-none-eabi-g++.exe",
22+
"compilerArgs": [
23+
"-mthumb",
24+
"-mcpu=cortex-m4",
25+
"-mfpu=fpv4-sp-d16",
26+
"-mfloat-abi=hard",
27+
"-specs=nosys.specs",
28+
"-specs=nano.specs",
29+
"-u _printf_float",
30+
"-u _scanf_float"
31+
],
2232
"cStandard": "c11",
2333
"cppStandard": "c++17"
2434
},
@@ -39,7 +49,7 @@
3949
"__packed=\"__attribute__((__packed__))\"",
4050
"__GNUC__"
4151
],
42-
"intelliSenseMode": "gcc-x64",
52+
"intelliSenseMode": "gcc-arm",
4353
"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",
4454
"cStandard": "c11",
4555
"cppStandard": "c++17"
@@ -61,7 +71,7 @@
6171
"__packed=\"__attribute__((__packed__))\"",
6272
"__GNUC__"
6373
],
64-
"intelliSenseMode": "gcc-x64",
74+
"intelliSenseMode": "gcc-arm",
6575
"cStandard": "c11",
6676
"cppStandard": "c++17"
6777
}

Firmware/Board/v3/Src/stm32f4xx_it.c

+8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "stm32f4xx.h"
3636
#include "stm32f4xx_it.h"
3737
#include "cmsis_os.h"
38+
#include <stdbool.h>
3839

3940
/* USER CODE BEGIN 0 */
4041
#include <Drivers/STM32/stm32_system.h>
@@ -85,6 +86,13 @@ void get_regs(void** stack_ptr) {
8586
void* volatile pc __attribute__((unused)) = stack_ptr[6]; // Program counter
8687
void* volatile psr __attribute__((unused)) = stack_ptr[7]; // Program status register
8788

89+
void* volatile cfsr __attribute__((unused)) = (void*)SCB->CFSR; // Configurable fault status register
90+
void* volatile cpacr __attribute__((unused)) = (void*)SCB->CPACR;
91+
void* volatile fpccr __attribute__((unused)) = (void*)FPU->FPCCR;
92+
93+
volatile bool preciserr __attribute__((unused)) = (uint32_t)cfsr & 0x200;
94+
volatile bool ibuserr __attribute__((unused)) = (uint32_t)cfsr & 0x100;
95+
8896
volatile int stay_looping = 1;
8997
while(stay_looping);
9098
}

Firmware/Board/v3/board.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,26 @@ OnboardThermistorCurrentLimiter fet_thermistors[AXIS_COUNT] = {
5858
}
5959
};
6060

61+
OffboardThermistorCurrentLimiter motor_thermistors[AXIS_COUNT];
62+
6163
Motor motors[AXIS_COUNT] = {
6264
{
6365
&htim1, // timer
6466
TIM_1_8_PERIOD_CLOCKS, // control_deadline
6567
1.0f / SHUNT_RESISTANCE, // shunt_conductance [S]
6668
m0_gate_driver, // gate_driver
67-
m0_gate_driver // opamp
69+
m0_gate_driver, // opamp
70+
fet_thermistors[0],
71+
motor_thermistors[0]
6872
},
6973
{
7074
&htim8, // timer
7175
(3 * TIM_1_8_PERIOD_CLOCKS) / 2, // control_deadline
7276
1.0f / SHUNT_RESISTANCE, // shunt_conductance [S]
7377
m1_gate_driver, // gate_driver
74-
m1_gate_driver // opamp
78+
m1_gate_driver, // opamp
79+
fet_thermistors[1],
80+
motor_thermistors[1]
7581
}
7682
};
7783

@@ -101,7 +107,6 @@ MechanicalBrake mechanical_brakes[AXIS_COUNT];
101107
SensorlessEstimator sensorless_estimators[AXIS_COUNT];
102108
Controller controllers[AXIS_COUNT];
103109
TrapezoidalTrajectory trap[AXIS_COUNT];
104-
OffboardThermistorCurrentLimiter motor_thermistors[AXIS_COUNT];
105110

106111
std::array<Axis, AXIS_COUNT> axes{{
107112
{
@@ -112,8 +117,6 @@ std::array<Axis, AXIS_COUNT> axes{{
112117
encoders[0], // encoder
113118
sensorless_estimators[0], // sensorless_estimator
114119
controllers[0], // controller
115-
fet_thermistors[0], // fet_thermistor
116-
motor_thermistors[0], // motor_thermistor
117120
motors[0], // motor
118121
trap[0], // trap
119122
endstops[0], endstops[1], // min_endstop, max_endstop
@@ -132,8 +135,6 @@ std::array<Axis, AXIS_COUNT> axes{{
132135
encoders[1], // encoder
133136
sensorless_estimators[1], // sensorless_estimator
134137
controllers[1], // controller
135-
fet_thermistors[1], // fet_thermistor
136-
motor_thermistors[1], // motor_thermistor
137138
motors[1], // motor
138139
trap[1], // trap
139140
endstops[2], endstops[3], // min_endstop, max_endstop

0 commit comments

Comments
 (0)