From a7b11f8c6db30af55302b8b0343bd9b601579208 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Mon, 20 Nov 2017 20:10:38 -0800 Subject: [PATCH 01/15] Update README.md --- Firmware/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/README.md b/Firmware/README.md index ec5d96f6..eebd5de8 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -105,7 +105,7 @@ After installing all of the above, open a Git Bash shell. Continue at section [B ### Flashing the firmware * **Make sure you have [configured the parameters first](#configuring-parameters)** -* Connect `SWD`, `SWC`, and `GND` on connector J2 to the programmer. +* Connect `GND`, `SWD`, and `SWC` on connector J2 to the programmer. Note: Always plug in `GND` first! * You need to power the board by only **ONE** of the following: VCC(3.3v), 5V, or the main power connection (the DC bus). The USB port (J1) does not power the board. * Run `make flash` in the root of this repository. From 671c90afceb40faaf98037becfc8325ccb33df7e Mon Sep 17 00:00:00 2001 From: Capo01 <503426+Capo01@users.noreply.github.com> Date: Mon, 27 Nov 2017 22:10:29 +1100 Subject: [PATCH 02/15] Update README.md --- Firmware/README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Firmware/README.md b/Firmware/README.md index af5fac44..443b820c 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -145,14 +145,26 @@ The following options are known to work and supported: * When you are done, you must kill the openocd task before you are able to flash the board again: Tasks -> Terminate task -> openocd. ## Communicating over USB or UART - +Warning: If testing USB or UART communication for the first time it is recommend that your motors are free to spin continuously and are not connected to a drivetrain with limited travel. ### From Linux/Windows/macOS There are two simple python scripts to help you get started with controlling the ODrive using python. -1. [Install Python 3](https://www.python.org/downloads/), then install dependencies: +1. [Install Python 3](https://www.python.org/downloads/), then install dependencies pyusb and pyserial: + * __Linux__ ``` pip install pyusb pyserial ``` + * __Windows__ +From the start menu type 'cmd' and open the command prompt. If you only have python3 installed then enter: +``` +pip install pyusb pyserial +``` +If you have python2 and python3 installed concurrently then you must specifiy the location of pip for python3. For me this was at 'C:\Users\ 'username' \AppData\Local\Programs\Python\Python36-32\Scripts\' and so I instead enter: +``` +C:\Users\'username'\AppData\Local\Programs\Python\Python36-32\Scripts\pip install pyusb pyserial +``` +If you have trouble with this step then refer to [this walkthrough.](https://www.youtube.com/watch?v=jnpC_Ib_lbc) + 3. __Linux__: set up USB permissions ``` echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="0d[0-9][0-9]", MODE="0666"' | sudo tee /etc/udev/rules.d/50-odrive.rules @@ -163,9 +175,11 @@ pip install pyusb pyserial 5. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC 6. __Windows__: Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb. * If 'Odrive V3.x' is not in the list of devices upon opening Zadig, check 'List All Devices' from the options menu. With the Odrive selected in the device list choose 'libusb-win32' from the target driver list and select the large 'install driver' button. -7. Run `./tools/demo.py` or `./tools/explore_odrive.py`. +7. Run `./tools/demo.py` or `./tools/explore_odrive.py`. - `demo.py` is a very simple script which will make motor 0 turn back and forth. Use this as an example if you want to control the ODrive yourself programatically. - `explore_odrive.py` drops you into an interactive python shell where you can explore and edit the parameters that are available on your device. For instance `my_odrive.motor0.pos_setpoint = 10000` makes motor0 move to position 10000. To connect over serial instead of USB run `./tools/explore_odrive.py --discover serial`. + * __Windows Users:__ +If you run either of the python scripts and only see a prompt window appear for a split second before it closes then it is likely that you have not installed pyusb and pyserial for python3 correctly. ### From Arduino [See ODrive Arduino Library](https://github.com/madcowswe/ODriveArduino) From 772bbeef12d754b90c101619630f94044ba250d4 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Thu, 7 Dec 2017 10:40:24 -0800 Subject: [PATCH 03/15] Update README.md --- Firmware/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/README.md b/Firmware/README.md index eebd5de8..138049b2 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -48,6 +48,7 @@ You must set: #### Tuning parameters The most important parameters are the limits: * The current limit: `.current_lim = 75.0f, //[A] // Note: consistent with 40v/v gain`. The default current limit, for safety reasons, is set to 10A. This is quite weak, and good for making sure the drive is stable. Once you have tuned the drive, you can increase this to 75A to get some performance. Note that above 75A, you must change the current amplifier gains. + * Note: The motor current and the current drawn from the power supply is not the same in general. You should not look at the power supply current to see what is going on with the motor current. * The velocity limit: `.vel_limit = 20000.0f, // [counts/s]`. Does what it says on the tin. The motion control gains are currently manually tuned: From f301d3cac404dd1f31adf6ebe7c96ae2b48a4f00 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Sun, 10 Dec 2017 16:16:35 -0800 Subject: [PATCH 04/15] change HW version to v3.4 --- Firmware/Inc/main.h | 2 +- Firmware/MotorControl/commands.cpp | 8 ++++---- Firmware/MotorControl/low_level.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Firmware/Inc/main.h b/Firmware/Inc/main.h index 911d81fe..ef2b2734 100644 --- a/Firmware/Inc/main.h +++ b/Firmware/Inc/main.h @@ -53,7 +53,7 @@ /* USER CODE BEGIN Includes */ #define HW_VERSION_MAJOR 3 -#define HW_VERSION_MINOR 3 +#define HW_VERSION_MINOR 4 #if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR == 1 \ || HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR == 2 diff --git a/Firmware/MotorControl/commands.cpp b/Firmware/MotorControl/commands.cpp index 77febe2c..54031438 100644 --- a/Firmware/MotorControl/commands.cpp +++ b/Firmware/MotorControl/commands.cpp @@ -108,8 +108,8 @@ const Endpoint endpoints[] = { Endpoint::make_property("calibration_current", &motors[0].calibration_current), Endpoint::make_property("phase_inductance", const_cast(&motors[0].phase_inductance)), Endpoint::make_property("phase_resistance", const_cast(&motors[0].phase_resistance)), - Endpoint::make_property("current_meas.phB", const_cast(&motors[0].current_meas.phB)), - Endpoint::make_property("current_meas.phC", const_cast(&motors[0].current_meas.phC)), + Endpoint::make_property("current_meas_phB", const_cast(&motors[0].current_meas.phB)), + Endpoint::make_property("current_meas_phC", const_cast(&motors[0].current_meas.phC)), Endpoint::make_property("DC_calib.phB", &motors[0].DC_calib.phB), Endpoint::make_property("DC_calib.phC", &motors[0].DC_calib.phC), Endpoint::make_property("shunt_conductance", &motors[0].shunt_conductance), @@ -161,8 +161,8 @@ const Endpoint endpoints[] = { Endpoint::make_property("calibration_current", &motors[1].calibration_current), Endpoint::make_property("phase_inductance", const_cast(&motors[1].phase_inductance)), Endpoint::make_property("phase_resistance", const_cast(&motors[1].phase_resistance)), - Endpoint::make_property("current_meas.phB", const_cast(&motors[1].current_meas.phB)), - Endpoint::make_property("current_meas.phC", const_cast(&motors[1].current_meas.phC)), + Endpoint::make_property("current_meas_phB", const_cast(&motors[1].current_meas.phB)), + Endpoint::make_property("current_meas_phC", const_cast(&motors[1].current_meas.phC)), Endpoint::make_property("DC_calib.phB", &motors[1].DC_calib.phB), Endpoint::make_property("DC_calib.phC", &motors[1].DC_calib.phC), Endpoint::make_property("shunt_conductance", &motors[1].shunt_conductance), diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 06e3e1ad..3f906834 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -636,8 +636,8 @@ void pwm_trig_adc_cb(ADC_HandleTypeDef* hadc, bool injected) { // TODO check Ibeta balance to verify good motor connection bool measure_phase_resistance(Motor_t* motor, float test_current, float max_voltage) { - static const float kI = 10.0f; //[(V/s)/A] - static const int num_test_cycles = 3.0f / CURRENT_MEAS_PERIOD; // Test runs for 3s + static const float kI = 10.0f; // [(V/s)/A] + static const int num_test_cycles = 3.0f / CURRENT_MEAS_PERIOD; // Test runs for 3s float test_voltage = 0.0f; for (int i = 0; i < num_test_cycles; ++i) { osEvent evt = osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, PH_CURRENT_MEAS_TIMEOUT); From 5aec8667884912cdd035e68c732b139325dbcfc1 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Fri, 15 Dec 2017 19:51:51 -0800 Subject: [PATCH 05/15] check DRV fault --- Firmware/MotorControl/low_level.c | 43 +++++++++++++++++++------------ Firmware/MotorControl/low_level.h | 4 ++- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 3f906834..8383b0be 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -320,7 +320,7 @@ void global_fault(int error) { *(motors[i].axis_legacy.enable_control) = false; } // disable brake resistor - update_brake_current(0.0f); + set_brake_current(0.0f); } float phase_current_from_adcval(Motor_t* motor, uint32_t ADCValue) { @@ -1112,7 +1112,16 @@ bool spin_up_sensorless(Motor_t* motor) { // TODO: check pll vel (abs ratio, 0.8) } -void update_brake_current(float brake_current) { +void update_brake_current() { + float Ibus_sum = 0.0f; + for (int i = 0; i < num_motors; ++i) { + Ibus_sum += motors[i].current_control.Ibus; + } + // Note: set_brake_current will clip negative values to 0.0f + set_brake_current(-Ibus_sum); +} + +void set_brake_current(float brake_current) { if (brake_current < 0.0f) brake_current = 0.0f; float brake_duty = brake_current * brake_resistance / vbus_voltage; @@ -1191,19 +1200,6 @@ bool FOC_current(Motor_t* motor, float Id_des, float Iq_des) { // Compute estimated bus current ictrl->Ibus = mod_d * Id + mod_q * Iq; - // If this is last motor, update brake resistor duty - // if (motor == &motors[num_motors-1]) { - // Above check doesn't work if last motor is executing voltage control - // TODO trigger this update in control_motor_loop instead, - // and make voltage control a control mode in it. - float Ibus_sum = 0.0f; - for (int i = 0; i < num_motors; ++i) { - Ibus_sum += motors[i].current_control.Ibus; - } - // Note: function will clip negative values to 0.0f - update_brake_current(-Ibus_sum); - // } - // Inverse park transform float mod_alpha = c * mod_d - s * mod_q; float mod_beta = c * mod_q + s * mod_d; @@ -1224,12 +1220,23 @@ bool FOC_current(Motor_t* motor, float Id_des, float Iq_des) { return true; } +//Returns true if the fault line is asserted +bool check_DRV_fault(Motor_t* motor) { + //TODO: make this pin configurable per motor ch + GPIO_PinState nFAULT_state = HAL_GPIO_ReadPin(nFAULT_GPIO_Port, nFAULT_Pin); + return (nFAULT_state == GPIO_PIN_RESET) ? true : false; +} + void control_motor_loop(Motor_t* motor) { while (*(motor->axis_legacy.enable_control)) { if (osSignalWait(M_SIGNAL_PH_CURRENT_MEAS, PH_CURRENT_MEAS_TIMEOUT).status != osEventSignal) { motor->error = ERROR_FOC_MEASUREMENT_TIMEOUT; break; } + if (check_DRV_fault(motor)) { + motor->error = ERROR_DRV_FAULT; + break; + } update_rotor(motor); anti_cogging_calibration(motor); // Only runs if anticogging.calib_anticogging is true; non-blocking @@ -1304,9 +1311,11 @@ void control_motor_loop(Motor_t* motor) { if (!FOC_current(motor, 0.0f, Iq)) { break; // in case of error exit loop, motor->error has been set by FOC_current } + + update_brake_current(); } //We are exiting control, reset Ibus, and update brake current - //TODO update brake current from all motors in 1 func - //TODO reset this motor Ibus, then call from here + motor->current_control.Ibus = 0.0f; + update_brake_current(); } diff --git a/Firmware/MotorControl/low_level.h b/Firmware/MotorControl/low_level.h index 342c19ec..22a09877 100644 --- a/Firmware/MotorControl/low_level.h +++ b/Firmware/MotorControl/low_level.h @@ -48,6 +48,7 @@ typedef enum { ERROR_UNEXPECTED_STEP_SRC, ERROR_POS_CTRL_DURING_SENSORLESS, ERROR_SPIN_UP_TIMEOUT, + ERROR_DRV_FAULT, } Error_t; // Note: these should be sorted from lowest level of control to @@ -232,7 +233,8 @@ bool using_sensorless(Motor_t* motor); float get_rotor_phase(Motor_t* motor); float get_pll_vel(Motor_t* motor); bool spin_up_sensorless(Motor_t* motor); -void update_brake_current(float brake_current); +void update_brake_current(); +void set_brake_current(float brake_current); void queue_modulation_timings(Motor_t* motor, float mod_alpha, float mod_beta); void queue_voltage_timings(Motor_t* motor, float v_alpha, float v_beta); bool FOC_current(Motor_t* motor, float Id_des, float Iq_des); From 07525383b29aa74e7b16816e6084182876a88d6f Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Fri, 15 Dec 2017 20:18:43 -0800 Subject: [PATCH 06/15] boost switching freq, add vbus_s HV define --- Firmware/Inc/main.h | 10 +++++++++- Firmware/MotorControl/low_level.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Firmware/Inc/main.h b/Firmware/Inc/main.h index ef2b2734..2a26800c 100644 --- a/Firmware/Inc/main.h +++ b/Firmware/Inc/main.h @@ -54,6 +54,7 @@ #define HW_VERSION_MAJOR 3 #define HW_VERSION_MINOR 4 +// #define HW_VERSION_HIGH_VOLTAGE true #if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR == 1 \ || HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR == 2 @@ -63,7 +64,8 @@ /* Private define ------------------------------------------------------------*/ #define TIM_1_8_CLOCK_HZ 168000000 -#define TIM_1_8_PERIOD_CLOCKS 10192 +// #define TIM_1_8_PERIOD_CLOCKS 8192 +#define TIM_1_8_PERIOD_CLOCKS 6000 #define TIM_1_8_DEADTIME_CLOCKS 20 #define TIM_APB1_CLOCK_HZ 84000000 #define TIM_APB1_PERIOD_CLOCKS 4096 @@ -157,6 +159,12 @@ #define CURRENT_MEAS_PERIOD ((float)(2*TIM_1_8_PERIOD_CLOCKS)/(float)TIM_1_8_CLOCK_HZ) #define CURRENT_MEAS_HZ (TIM_1_8_CLOCK_HZ/(2*TIM_1_8_PERIOD_CLOCKS)) +#if HW_VERSION_HIGH_VOLTAGE == true +#define VBUS_S_DIVIDER_RATIO 19.0f +#else +#define VBUS_S_DIVIDER_RATIO 11.0f +#endif + /* USER CODE END Private defines */ void _Error_Handler(char *, int); diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 8383b0be..3de25b22 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -528,7 +528,7 @@ void step_cb(uint16_t GPIO_Pin) { } void vbus_sense_adc_cb(ADC_HandleTypeDef* hadc, bool injected) { - static const float voltage_scale = 3.3f * 11.0f / (float)(1 << 12); + static const float voltage_scale = 3.3f * VBUS_S_DIVIDER_RATIO / (float)(1 << 12); // Only one conversion in sequence, so only rank1 uint32_t ADCValue = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1); vbus_voltage = ADCValue * voltage_scale; From 9287f5a00b1c4a425c3dfd268db9875b870405eb Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Mon, 18 Dec 2017 15:20:31 -0800 Subject: [PATCH 07/15] add hw v3.4, check DRV fault --- Firmware/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Firmware/CHANGELOG.md b/Firmware/CHANGELOG.md index da7b613f..eeb1d1a4 100644 --- a/Firmware/CHANGELOG.md +++ b/Firmware/CHANGELOG.md @@ -7,9 +7,12 @@ * 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 ### Changed * 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 From 138ad2037aae8baa1f4b2bb6f873aca254ff750e Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Mon, 18 Dec 2017 15:22:29 -0800 Subject: [PATCH 08/15] release v0.3 date in changelog --- Firmware/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/CHANGELOG.md b/Firmware/CHANGELOG.md index eeb1d1a4..7ddb3bba 100644 --- a/Firmware/CHANGELOG.md +++ b/Firmware/CHANGELOG.md @@ -1,5 +1,4 @@ -## [0.3] - +## [0.3] - 2017-12-18 ### Added * **New binary communication protocol** * This is a much richer and more efficient binary protocol than the old human-readable protocol. From c14bc7b87152df481dc4ee162ff456157df3682c Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 19 Dec 2017 20:56:36 -0800 Subject: [PATCH 09/15] add Iq control effort report --- Firmware/MotorControl/commands.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/MotorControl/commands.cpp b/Firmware/MotorControl/commands.cpp index 54031438..bc426507 100644 --- a/Firmware/MotorControl/commands.cpp +++ b/Firmware/MotorControl/commands.cpp @@ -123,6 +123,7 @@ const Endpoint endpoints[] = { Endpoint::make_property("i_gain", &motors[0].current_control.i_gain), Endpoint::make_property("v_current_control_integral_d", &motors[0].current_control.v_current_control_integral_d), Endpoint::make_property("v_current_control_integral_q", &motors[0].current_control.v_current_control_integral_q), + Endpoint::make_property("Iq_command", &motors[0].current_control.Iq), Endpoint::make_property("Ibus", const_cast(&motors[0].current_control.Ibus)), Endpoint::close_tree(), Endpoint::make_object("encoder"), @@ -176,6 +177,7 @@ const Endpoint endpoints[] = { Endpoint::make_property("i_gain", &motors[1].current_control.i_gain), Endpoint::make_property("v_current_control_integral_d", &motors[1].current_control.v_current_control_integral_d), Endpoint::make_property("v_current_control_integral_q", &motors[1].current_control.v_current_control_integral_q), + Endpoint::make_property("Iq_command", &motors[1].current_control.Iq), Endpoint::make_property("Ibus", const_cast(&motors[1].current_control.Ibus)), Endpoint::close_tree(), Endpoint::make_object("encoder"), From 66431f2176cdd986e22b9427f0eea0d75619af6d Mon Sep 17 00:00:00 2001 From: Quincy Jones Date: Sat, 23 Dec 2017 01:39:21 -0600 Subject: [PATCH 10/15] Changed #ifdef logic for VBUS divider ratio selection. --- Firmware/Inc/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Inc/main.h b/Firmware/Inc/main.h index 2a26800c..7bbe9ae7 100644 --- a/Firmware/Inc/main.h +++ b/Firmware/Inc/main.h @@ -159,7 +159,7 @@ #define CURRENT_MEAS_PERIOD ((float)(2*TIM_1_8_PERIOD_CLOCKS)/(float)TIM_1_8_CLOCK_HZ) #define CURRENT_MEAS_HZ (TIM_1_8_CLOCK_HZ/(2*TIM_1_8_PERIOD_CLOCKS)) -#if HW_VERSION_HIGH_VOLTAGE == true +#ifdef HW_VERSION_HIGH_VOLTAGE #define VBUS_S_DIVIDER_RATIO 19.0f #else #define VBUS_S_DIVIDER_RATIO 11.0f From ec050387e2e5d905fad97703903270409a732b89 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Sat, 30 Dec 2017 01:00:34 -0800 Subject: [PATCH 11/15] Update main.h --- Firmware/Inc/main.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/Inc/main.h b/Firmware/Inc/main.h index 7bbe9ae7..a9650093 100644 --- a/Firmware/Inc/main.h +++ b/Firmware/Inc/main.h @@ -64,8 +64,7 @@ /* Private define ------------------------------------------------------------*/ #define TIM_1_8_CLOCK_HZ 168000000 -// #define TIM_1_8_PERIOD_CLOCKS 8192 -#define TIM_1_8_PERIOD_CLOCKS 6000 +#define TIM_1_8_PERIOD_CLOCKS 8192 #define TIM_1_8_DEADTIME_CLOCKS 20 #define TIM_APB1_CLOCK_HZ 84000000 #define TIM_APB1_PERIOD_CLOCKS 4096 From e2a8dce3553595fc39858fcb72e5ace7324c54c0 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 2 Jan 2018 20:52:40 -0800 Subject: [PATCH 12/15] Update low_level.c --- Firmware/MotorControl/low_level.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index 3de25b22..ecf23231 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -418,7 +418,7 @@ void start_adc_pwm() { start_pwm(&htim1); start_pwm(&htim8); // TODO: explain why this offset - sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 1 * 128); + sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 0 * 128); // Motor output starts in the disabled state __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(&htim1); From 6cefbf6e62db74eadc34712c62279dd376977b51 Mon Sep 17 00:00:00 2001 From: Cristian Fluture Date: Sun, 14 Jan 2018 23:38:21 -0800 Subject: [PATCH 13/15] Added 3 endpoints (UUID_0, UUID_1, UUID2) to expose the device UUID --- Firmware/MotorControl/commands.cpp | 3 +++ Firmware/MotorControl/protocol.hpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/Firmware/MotorControl/commands.cpp b/Firmware/MotorControl/commands.cpp index bc426507..25871230 100644 --- a/Firmware/MotorControl/commands.cpp +++ b/Firmware/MotorControl/commands.cpp @@ -94,6 +94,9 @@ void motors_1_set_current_setpoint_func(void) { const Endpoint endpoints[] = { Endpoint::make_property("vbus_voltage", const_cast(&vbus_voltage)), Endpoint::make_property("elec_rad_per_enc", const_cast(&elec_rad_per_enc)), + Endpoint::make_property("UUID_0", (const uint32_t*)(ID_UNIQUE_ADDRESS + 0*4)), + Endpoint::make_property("UUID_1", (const uint32_t*)(ID_UNIQUE_ADDRESS + 1*4)), + Endpoint::make_property("UUID_2", (const uint32_t*)(ID_UNIQUE_ADDRESS + 2*4)), Endpoint::make_object("motor0"), Endpoint::make_property("control_mode", reinterpret_cast(&motors[0].control_mode)), Endpoint::make_property("error", reinterpret_cast(&motors[0].error)), diff --git a/Firmware/MotorControl/protocol.hpp b/Firmware/MotorControl/protocol.hpp index 92664d55..bc3b3b9a 100644 --- a/Firmware/MotorControl/protocol.hpp +++ b/Firmware/MotorControl/protocol.hpp @@ -335,6 +335,10 @@ inline const char* get_default_json_modifier() { return "\"type\":\"int32\",\"access\":\"rw\""; } template<> +inline const char* get_default_json_modifier() { + return "\"type\":\"uint32\",\"access\":\"r\""; +} +template<> inline const char* get_default_json_modifier() { return "\"type\":\"uint16\",\"access\":\"r\""; } From e7398e23c5504d8c8ab1e8521fcf535d7b399501 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 16 Jan 2018 19:36:05 -0800 Subject: [PATCH 14/15] Update low_level.c --- Firmware/MotorControl/low_level.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c index ecf23231..3de25b22 100644 --- a/Firmware/MotorControl/low_level.c +++ b/Firmware/MotorControl/low_level.c @@ -418,7 +418,7 @@ void start_adc_pwm() { start_pwm(&htim1); start_pwm(&htim8); // TODO: explain why this offset - sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 0 * 128); + sync_timers(&htim1, &htim8, TIM_CLOCKSOURCE_ITR0, TIM_1_8_PERIOD_CLOCKS / 2 - 1 * 128); // Motor output starts in the disabled state __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(&htim1); From d898caede7933b7c67429196698b730be95a7caf Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 16 Jan 2018 23:01:14 -0800 Subject: [PATCH 15/15] improve python on windows instructions --- Firmware/README.md | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/Firmware/README.md b/Firmware/README.md index 679656bb..f2dd9873 100644 --- a/Firmware/README.md +++ b/Firmware/README.md @@ -148,39 +148,35 @@ The following options are known to work and supported: ## Communicating over USB or UART Warning: If testing USB or UART communication for the first time it is recommend that your motors are free to spin continuously and are not connected to a drivetrain with limited travel. ### From Linux/Windows/macOS -There are two simple python scripts to help you get started with controlling the ODrive using python. +There are two example python scripts to help you get started with controlling the ODrive using python. One will drop you into an interactive shell to query settings, parameters, and variables, and let you send setpoints manually ([tools/explore_odrive.py](tools/explore_odrive.py)). The other is a demo application to show you how to control the ODrive programmatically ([tools/demo.py](tools/demo.py)). Below follows a step-by-step guide on how to run these. + + +* __Windows__: It is recommended to use a Unix style command prompt, such as Git Bash that comes with [Git for windows](https://git-scm.com/download/win). 1. [Install Python 3](https://www.python.org/downloads/), then install dependencies pyusb and pyserial: - * __Linux__ ``` pip install pyusb pyserial ``` - * __Windows__ -From the start menu type 'cmd' and open the command prompt. If you only have python3 installed then enter: -``` -pip install pyusb pyserial -``` -If you have python2 and python3 installed concurrently then you must specifiy the location of pip for python3. For me this was at 'C:\Users\ 'username' \AppData\Local\Programs\Python\Python36-32\Scripts\' and so I instead enter: -``` -C:\Users\'username'\AppData\Local\Programs\Python\Python36-32\Scripts\pip install pyusb pyserial -``` -If you have trouble with this step then refer to [this walkthrough.](https://www.youtube.com/watch?v=jnpC_Ib_lbc) +* Note: If you have python2 and python3 installed concurrently then you must specifiy that we wish to target python3. This is done as follows: + * __Linux__: Use `pip3` instead of `pip` in the above command. + * __Windows__: Use the full path of the Python3 pip, yeilding something like: + `C:\Users\YOUR_USERNAME\AppData\Local\Programs\Python\Python36-32\Scripts\pip install pyusb pyserial` +* If you have trouble with this step then refer to [this walkthrough.](https://www.youtube.com/watch?v=jnpC_Ib_lbc) -3. __Linux__: set up USB permissions +2. __Linux__: set up USB permissions ``` echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="0d[0-9][0-9]", MODE="0666"' | sudo tee /etc/udev/rules.d/50-odrive.rules sudo udevadm control --reload-rules sudo udevadm trigger # until you reboot you may need to do this everytime you reset the ODrive ``` -4. Power the ODrive board (as per the [Flashing the firmware](#flashing-the-firmware) step) -5. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC -6. __Windows__: Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb. +3. Power the ODrive board (as per the [Flashing the firmware](#flashing-the-firmware) step). +4. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC. +5. __Windows__: Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb-win32. * If 'Odrive V3.x' is not in the list of devices upon opening Zadig, check 'List All Devices' from the options menu. With the Odrive selected in the device list choose 'libusb-win32' from the target driver list and select the large 'install driver' button. -7. Run `./tools/demo.py` or `./tools/explore_odrive.py`. - - `demo.py` is a very simple script which will make motor 0 turn back and forth. Use this as an example if you want to control the ODrive yourself programatically. - - `explore_odrive.py` drops you into an interactive python shell where you can explore and edit the parameters that are available on your device. For instance `my_odrive.motor0.pos_setpoint = 10000` makes motor0 move to position 10000. To connect over serial instead of USB run `./tools/explore_odrive.py --discover serial`. - * __Windows Users:__ -If you run either of the python scripts and only see a prompt window appear for a split second before it closes then it is likely that you have not installed pyusb and pyserial for python3 correctly. +6. Open the bash prompt in the `ODrive/tools/` folder. +7. Run `python3 demo.py` or `python3 explore_odrive.py`. +- `demo.py` is a very simple script which will make motor 0 turn back and forth. Use this as an example if you want to control the ODrive yourself programatically. +- `explore_odrive.py` drops you into an interactive python shell where you can explore and edit the parameters that are available on your device. For instance `my_odrive.motor0.pos_setpoint = 10000` makes motor0 move to position 10000. To connect over serial instead of USB run `./tools/explore_odrive.py --discover serial`. ### From Arduino [See ODrive Arduino Library](https://github.com/madcowswe/ODriveArduino)