From cc0f083bf0b65c58f62ee3b75824c49bc94bc672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20H=C3=A4ggstr=C3=B6m?= Date: Thu, 13 Sep 2018 13:54:55 +0200 Subject: [PATCH 01/17] Poll analog inputs to drive a configured endpoint. --- Firmware/MotorControl/low_level.cpp | 31 +++++++++++++++++++++++- Firmware/MotorControl/low_level.h | 2 ++ Firmware/MotorControl/main.cpp | 2 ++ Firmware/MotorControl/odrive_main.h | 1 + Firmware/communication/communication.cpp | 7 ++++-- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Firmware/MotorControl/low_level.cpp b/Firmware/MotorControl/low_level.cpp index ffeeeadd..8d233188 100644 --- a/Firmware/MotorControl/low_level.cpp +++ b/Firmware/MotorControl/low_level.cpp @@ -724,4 +724,33 @@ void pwm_in_cb(int channel, uint32_t timestamp) { last_timestamp[gpio_num - 1] = timestamp; last_pin_state[gpio_num - 1] = current_pin_state; last_sample_valid[gpio_num - 1] = true; -} \ No newline at end of file +} + + +/* Analog speed control input */ + +static void update_analog_endpoint(const struct PWMMapping_t *map, int gpio) +{ + float fraction = get_adc_voltage(get_gpio_port_by_pin(gpio), get_gpio_pin_by_pin(gpio)) / 3.3f; + float value = map->min + (fraction * (map->max - map->min)); + get_endpoint(map->endpoint)->set_from_float(value); +} + +static void analog_polling_thread(void *) +{ + while (true) { + for (int i = 0; i < GPIO_COUNT; i++) { + struct PWMMapping_t *map = &board_config.analog_mappings[i]; + + if (is_endpoint_ref_valid(map->endpoint)) + update_analog_endpoint(map, i + 1); + } + osDelay(200); + } +} + +void start_analog_thread() +{ + osThreadDef(thread_def, analog_polling_thread, osPriorityLow, 0, 4*512); + osThreadCreate(osThread(thread_def), NULL); +} diff --git a/Firmware/MotorControl/low_level.h b/Firmware/MotorControl/low_level.h index 4af6e3e0..e098c75f 100644 --- a/Firmware/MotorControl/low_level.h +++ b/Firmware/MotorControl/low_level.h @@ -53,6 +53,8 @@ void pwm_in_init(); void update_brake_current(); +void start_analog_thread(); + #ifdef __cplusplus } #endif diff --git a/Firmware/MotorControl/main.cpp b/Firmware/MotorControl/main.cpp index 18b88433..4766cf54 100644 --- a/Firmware/MotorControl/main.cpp +++ b/Firmware/MotorControl/main.cpp @@ -208,6 +208,8 @@ int odrive_main(void) { axes[i]->start_thread(); } + start_analog_thread(); + system_stats_.fully_booted = true; return 0; } diff --git a/Firmware/MotorControl/odrive_main.h b/Firmware/MotorControl/odrive_main.h index 4e4db160..00be19f0 100644 --- a/Firmware/MotorControl/odrive_main.h +++ b/Firmware/MotorControl/odrive_main.h @@ -75,6 +75,7 @@ struct BoardConfig_t { //make_protocol_definitions()), make_protocol_object("axis1", axes[1]->make_protocol_definitions()), make_protocol_object("can", can1_ctx.make_protocol_definitions()), From a499d087e8537e08b03f4781b98973c72ef68fe2 Mon Sep 17 00:00:00 2001 From: je310 Date: Sat, 13 Oct 2018 11:32:20 +0100 Subject: [PATCH 02/17] Update usart.c Added a comment regarding baud rate. Probably should be tied into the build system at some point such that it does not need to be changed manually. --- Firmware/Board/v3/Src/usart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Board/v3/Src/usart.c b/Firmware/Board/v3/Src/usart.c index 52a869db..0c4bed6f 100644 --- a/Firmware/Board/v3/Src/usart.c +++ b/Firmware/Board/v3/Src/usart.c @@ -66,7 +66,7 @@ void MX_UART4_Init(void) { huart4.Instance = UART4; - huart4.Init.BaudRate = 115200; + huart4.Init.BaudRate = 115200; // Provisionally this can be changed to 921600 for faster transfers, the low power Arduinos will not keep up. huart4.Init.WordLength = UART_WORDLENGTH_8B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_NONE; From b41016eba3756f5f3d15802bf39bb9af8bcc7c59 Mon Sep 17 00:00:00 2001 From: tobbelobb Date: Thu, 18 Oct 2018 13:29:05 +0200 Subject: [PATCH 03/17] Update commands.md --- docs/commands.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index 7e7fe3da..05c28364 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -22,14 +22,14 @@ The current state of an axis is indicated by `.current_state`. The user ca 1. `AXIS_STATE_IDLE` Disable motor PWM and do nothing. 2. `AXIS_STATE_STARTUP_SEQUENCE` Run the [startup procedure](#startup-procedure). - 3. `AXIS_STATE_FULL_CALIBRATION_SEQUENCE` Run motor calibration and then encoder offset calibration (or encoder index search if `.encoder.use_index` is `True`). + 3. `AXIS_STATE_FULL_CALIBRATION_SEQUENCE` Run motor calibration and then encoder offset calibration (or encoder index search if `.encoder.config.use_index` is `True`). 4. `AXIS_STATE_MOTOR_CALIBRATION` Measure phase resistance and phase inductance of the motor. * To store the results set `.motor.config.pre_calibrated` to `True` and [save the configuration](#saving-the-configuration). After that you don't have to run the motor calibration on the next start up. * This modifies the variables `.motor.config.phase_resistance` and `.motor.config.phase_inductance`. 5. `AXIS_STATE_SENSORLESS_CONTROL` Run sensorless control. * The motor must be calibrated (`.motor.is_calibrated`) * [`.controller.control_mode`](#control-mode) must be `True`. - 6. `AXIS_STATE_ENCODER_INDEX_SEARCH` Turn the motor in one direction until the encoder index is traversed. This state can only be entered if `.encoder.config.use_index` is `True`. + 6. `AXIS_STATE_ENCODER_INDEX_SEARCH` Turn the motor in one direction until the encoder index is traversed. This state can only be entered if `.encoder.config.config.use_index` is `True`. 7. `AXIS_STATE_ENCODER_OFFSET_CALIBRATION` Turn the motor in one direction for a few seconds and then back to measure the offset between the encoder position and the electrical phase. * Can only be entered if the motor is calibrated (`.motor.is_calibrated`). * A successful encoder calibration will make the `.encoder.is_ready` go to true. From 30b950008389708e1a4e9a90ed75aaf8f4749c5e Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Thu, 18 Oct 2018 22:21:28 -0700 Subject: [PATCH 04/17] Update commands.md --- docs/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/commands.md b/docs/commands.md index 05c28364..32b7769d 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -29,7 +29,7 @@ The current state of an axis is indicated by `.current_state`. The user ca 5. `AXIS_STATE_SENSORLESS_CONTROL` Run sensorless control. * The motor must be calibrated (`.motor.is_calibrated`) * [`.controller.control_mode`](#control-mode) must be `True`. - 6. `AXIS_STATE_ENCODER_INDEX_SEARCH` Turn the motor in one direction until the encoder index is traversed. This state can only be entered if `.encoder.config.config.use_index` is `True`. + 6. `AXIS_STATE_ENCODER_INDEX_SEARCH` Turn the motor in one direction until the encoder index is traversed. This state can only be entered if `.encoder.config.use_index` is `True`. 7. `AXIS_STATE_ENCODER_OFFSET_CALIBRATION` Turn the motor in one direction for a few seconds and then back to measure the offset between the encoder position and the electrical phase. * Can only be entered if the motor is calibrated (`.motor.is_calibrated`). * A successful encoder calibration will make the `.encoder.is_ready` go to true. From 02740cc97b3cde3c96337914b4a8ca549d8019cb Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Sat, 20 Oct 2018 13:51:33 -0700 Subject: [PATCH 05/17] Update Gemfile.lock --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 20e81d61..1c6d972e 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -221,7 +221,7 @@ GEM ruby-enum (0.7.2) i18n ruby_dep (1.5.0) - rubyzip (1.2.1) + rubyzip (1.2.2) safe_yaml (1.0.4) sass (3.5.6) sass-listen (~> 4.0.0) From 86f97555d8036970701759c5c38b0b217f93f0be Mon Sep 17 00:00:00 2001 From: metanoic <5554798+metanoic@users.noreply.github.com> Date: Thu, 25 Oct 2018 14:45:50 -0500 Subject: [PATCH 06/17] Hoverboard docs J2->J4 Pretty sure this should be J4 rather than J2, no? --- docs/hoverboard.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/hoverboard.md b/docs/hoverboard.md index be35e74d..2e9f6cf4 100644 --- a/docs/hoverboard.md +++ b/docs/hoverboard.md @@ -8,9 +8,9 @@ Each step is acompanied by some explanation so hopefully you can carry over some ### Hoverboard motor wiring Hoverboard motors come with three motor phases (usually colored yellow, blue, green) which are thicker, and a set of 5 thinner wires for the hall sensor feedback (usually colored red, yellow, blue, green, black). -You may wire the motor phases in any order into a motor connector on the ODrive, as we will calibrate the phase alignment later anyway. Wire the hall feedback into the ODrive J2 conenctor (make sure that the motor channel number matches) as follows: +You may wire the motor phases in any order into a motor connector on the ODrive, as we will calibrate the phase alignment later anyway. Wire the hall feedback into the ODrive J4 conenctor (make sure that the motor channel number matches) as follows: -| Hall wire | J2 signal | +| Hall wire | J4 signal | |-----------|-----------| | Red | 5V | | Yellow | A | From f36fe0058e5af39bcbe2d53c4736968c8dfa9923 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 27 Nov 2018 22:51:13 -0500 Subject: [PATCH 07/17] Add controller_with_ff.png to docs --- docs/controller_with_ff.png | Bin 0 -> 100261 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/controller_with_ff.png diff --git a/docs/controller_with_ff.png b/docs/controller_with_ff.png new file mode 100644 index 0000000000000000000000000000000000000000..212b1f266d7309882c1fa0c05ea69732250456f2 GIT binary patch literal 100261 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

*VdH*qcDpbL1mZp2 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�-2(v=-i-1u*@h0N5 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 Xcu{=N774p`@bA)j<#TCr#(w_?1mc}^ literal 0 HcmV?d00001 From eea174f82b08d4db10e1d845a27e626ddadbe9b8 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 27 Nov 2018 22:54:54 -0500 Subject: [PATCH 08/17] Replace controller image in docs with new FF diagram --- docs/control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/control.md b/docs/control.md index f0b2da1d..fd04ac6d 100644 --- a/docs/control.md +++ b/docs/control.md @@ -2,7 +2,7 @@ The motor controller is a cascaded style position, velocity and current control loop, as per the diagram below. When the control mode is set to position control, the whole loop runs. When running in velocity control mode, the position control part is removed and the velocity command is fed directly in to the second stage input. In current control mode, only the current controller is used. -![Cascaded pos vel I loops](https://static1.squarespace.com/static/58aff26de4fcb53b5efd2f02/t/5b66284a0e2e72aae8818d64/1533421649405/CascadedController.png?format=2500w) +![Cascaded pos vel I loops](https://github.com/madcowswe/ODrive/blob/master/docs/controller_with_ff.png?raw=true) ### Position loop: The position controller is a P loop with a single proportional gain. From 167f00e622d2b95f0a89b8b5ad17a3eb01b11ef4 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 27 Nov 2018 22:29:02 -0800 Subject: [PATCH 09/17] add current sense saturation fault --- CHANGELOG.md | 1 + Firmware/MotorControl/motor.cpp | 11 ++++++++++- Firmware/MotorControl/motor.hpp | 16 ++++++++++------ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a257960d..e6069fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Please add a note of your changes below this heading if you make a Pull Request. ### Added * Overspeed fault +* Current sense saturation fault. * Supress 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. diff --git a/Firmware/MotorControl/motor.cpp b/Firmware/MotorControl/motor.cpp index 5585a862..7cee19b0 100644 --- a/Firmware/MotorControl/motor.cpp +++ b/Firmware/MotorControl/motor.cpp @@ -73,7 +73,8 @@ void Motor::DRV8301_setup() { // Solve for exact gain, then snap down to have equal or larger range as requested // or largest possible range otherwise static const float kMargin = 0.90f; - static const float max_output_swing = 1.6f; // [V] out of amplifier + static const float kTripMargin = 1.0f; // Trip level is at edge of linear range of amplifer + static const float max_output_swing = 1.35f; // [V] out of amplifier float max_unity_gain_current = kMargin * max_output_swing * hw_config_.shunt_conductance; // [A] float requested_gain = max_unity_gain_current / config_.requested_current_range; // [V/V] @@ -99,6 +100,8 @@ void Motor::DRV8301_setup() { phase_current_rev_gain_ = 1.0f / gain_snap_down->first; // Clip all current control to actual usable range current_control_.max_allowed_current = max_unity_gain_current * phase_current_rev_gain_; + // Set trip level + current_control_.overcurrent_trip_level = (kTripMargin / kMargin) * current_control_.max_allowed_current; // We now have the gain settings we want to use, lets set up DRV chip DRV_SPI_8301_Vars_t* local_regs = &gate_driver_regs_; @@ -296,6 +299,12 @@ bool Motor::FOC_current(float Id_des, float Iq_des, float phase) { // For Reporting ictrl.Iq_setpoint = Iq_des; + // Check for current sense saturation + if (fabsf(current_meas_.phB) > ictrl.overcurrent_trip_level + || fabsf(current_meas_.phC) > ictrl.overcurrent_trip_level) { + set_error(ERROR_CURRENT_SENSE_SATURATION); + } + // Clarke transform float Ialpha = -current_meas_.phB - current_meas_.phC; float Ibeta = one_by_sqrt3 * (current_meas_.phB - current_meas_.phC); diff --git a/Firmware/MotorControl/motor.hpp b/Firmware/MotorControl/motor.hpp index ebfd3a12..2fe384e5 100644 --- a/Firmware/MotorControl/motor.hpp +++ b/Firmware/MotorControl/motor.hpp @@ -20,7 +20,8 @@ public: ERROR_BRAKE_CURRENT_OUT_OF_RANGE = 0x0040, ERROR_MODULATION_MAGNITUDE = 0x0080, ERROR_BRAKE_DEADTIME_VIOLATION = 0x0100, - ERROR_UNEXPECTED_TIMER_CALLBACK = 0x0200 + ERROR_UNEXPECTED_TIMER_CALLBACK = 0x0200, + ERROR_CURRENT_SENSE_SATURATION = 0x0400 }; enum MotorType_t { @@ -43,9 +44,10 @@ public: // Voltage applied at end of cycle: float final_v_alpha; // [V] float final_v_beta; // [V] - float Iq_setpoint; - float Iq_measured; - float max_allowed_current; + float Iq_setpoint; // [A] + float Iq_measured; // [A] + float max_allowed_current; // [A] + float overcurrent_trip_level; // [A] }; // NOTE: for gimbal motors, all units of A are instead V. @@ -64,7 +66,7 @@ public: // float current_lim = 70.0f; //[A] float current_lim = 10.0f; //[A] // Value used to compute shunt amplifier gains - float requested_current_range = 70.0f; // [A] + float requested_current_range = 60.0f; // [A] float current_control_bandwidth = 1000.0f; // [rad/s] }; @@ -153,6 +155,7 @@ public: .Iq_setpoint = 0.0f, .Iq_measured = 0.0f, .max_allowed_current = 0.0f, + .overcurrent_trip_level = 0.0f, }; DRV8301_FaultType_e drv_fault_ = DRV8301_FaultType_NoFault; DRV_SPI_8301_Vars_t gate_driver_regs_; //Local view of DRV registers (initialized by DRV8301_setup) @@ -178,7 +181,8 @@ public: make_protocol_property("final_v_beta", ¤t_control_.final_v_beta), make_protocol_property("Iq_setpoint", ¤t_control_.Iq_setpoint), make_protocol_property("Iq_measured", ¤t_control_.Iq_measured), - make_protocol_property("max_allowed_current", ¤t_control_.max_allowed_current) + make_protocol_ro_property("max_allowed_current", ¤t_control_.max_allowed_current), + make_protocol_ro_property("overcurrent_trip_level", ¤t_control_.overcurrent_trip_level) ), make_protocol_object("gate_driver", make_protocol_ro_property("drv_fault", &drv_fault_) From bb680e175a5ce545c30a8abd2d38eadb9b6fa633 Mon Sep 17 00:00:00 2001 From: Mark Omo Date: Wed, 28 Nov 2018 16:33:53 -0700 Subject: [PATCH 10/17] Fix issues with spaces in install path on windows --- tools/odrivetool.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/odrivetool.bat b/tools/odrivetool.bat index 02b0a0bb..06dc5e56 100644 --- a/tools/odrivetool.bat +++ b/tools/odrivetool.bat @@ -1,2 +1,2 @@ @echo off -ipython %~dp0\odrivetool -- %* +ipython "%~dp0\odrivetool" -- %* From 8c393973b7120d3f517c843932b85d75df707e0e Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 28 Nov 2018 22:44:58 -0800 Subject: [PATCH 11/17] document different control modes --- docs/TrapTrajPosVel.PNG | Bin 0 -> 14096 bytes docs/getting-started.md | 76 +++++++++++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 docs/TrapTrajPosVel.PNG diff --git a/docs/TrapTrajPosVel.PNG b/docs/TrapTrajPosVel.PNG new file mode 100644 index 0000000000000000000000000000000000000000..59c5bbe90348caccd72bda40e14ac3d40b1cb31a GIT binary patch literal 14096 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 literal 0 HcmV?d00001 diff --git a/docs/getting-started.md b/docs/getting-started.md index 0127efad..022f0362 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -16,6 +16,7 @@ permalink: / - [Start `odrivetool`](#start-odrivetool) - [Configure M0](#configure-m0) - [Position control of M0](#position-control-of-m0) +- [Other control modes](#other-control-modes) - [What's next?](#whats-next) @@ -165,7 +166,7 @@ For instance, to set the current limit of M0 to 10A you would type: `odrv0.axis0 **Current limit**
`odrv0.axis0.motor.config.current_lim` [A]. -The default current limit, for safety reasons, is set to 10A. This is quite weak, but good for making sure the drive is stable. Once you have tuned the oDrive, you can increase this to 75A to increase performance. Note that above 75A, you must change the current amplifier gains. You do this by requesting a different current range. i.e. for 90A on M0: `odrv0.axis0.motor.config.requested_current_range = 90` [A], then save the configuration and reboot as the gains are written out to the DRV (MOSFET driver) only during startup. +The default current limit, for safety reasons, is set to 10A. This is quite weak, but good for making sure the drive is stable. Once you have tuned the oDrive, you can increase this to 60A to increase performance. Note that above 60A, you must change the current amplifier gains. You do this by requesting a different current range. i.e. for 90A on M0: `odrv0.axis0.motor.config.requested_current_range = 90` [A], then save the configuration and reboot as the gains are written out to the DRV (MOSFET driver) only during startup. *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.*

Ok, so tell me how it actually works then...
@@ -241,16 +242,73 @@ Let's get motor 0 up and running. The procedure for motor 1 is exactly the same, 2. Type `odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL` Enter. From now on the ODrive will try to hold the motor's position. If you try to turn it by hand, it will fight you gently. That is unless you bump up `odrv0.axis0.motor.config.current_lim`, in which case it will fight you more fiercely. 3. Send the motor a new position setpoint. `odrv0.axis0.controller.pos_setpoint = 10000` Enter. The units are in encoder counts. -### Other control modes -The ODrive also supports velocity control and current (torque) control. +## Other control modes +The default control mode is unfiltered position control in the absolute encoder reference frame. You may wish to use a controlled trajectory instead. Or you may wish to control position in a circular frame to allow continous rotation forever without growing the numeric value of the setpoint too large. +You may also wish to control velocity (directly or with a ramping filter). +You can also directly control the current of the motor, which is proportional to torque. -**Velocity control**
-Set `odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL`. -You can now control the velocity with `odrv0.axis0.controller.vel_setpoint = 5000` [count/s]. +- [Trajectory control](#trajectory-control) +- [Circular position control](#circular-position-control) +- [Velocity control](#velocity-control) +- [Ramped velocity control](#ramped-velocity-control) +- [Current control](#current-control) -**Current control**
-Set `odrv0.axis0.controller.config.control_mode = CTRL_MODE_CURRENT_CONTROL`. -You can now control the current with `odrv0.axis0.controller.current_setpoint = 3` [A]. + +### Trajectory control +This mode lets you smoothly accelerate, coast, and decelerate the axis from one position to another. With raw position control, the controller simply tries to go to the setpoint as quickly as possible. Using a trajectory lets you tune the feedback gains more aggressively to reject disturbance, while keeping smooth motion. + +![Taptraj](TrapTrajPosVel.PNG)
+In the above image blue is position and orange is velocity. + +#### Parameters +``` +..trap_traj.config.vel_limit = +..trap_traj.config.accel_limit = +..trap_traj.config.decel_limit = +..trap_traj.config.A_per_css = +``` + +`vel_limit` is the maximum planned trajectory speed. This sets your coasting speed.
+`accel_limit` is the maximum acceleration in counts / sec^2
+`decel_limit` is the maximum deceleration in counts / sec^2
+`A_per_css` is a value which correlates acceleration (in counts / sec^2) and motor current. It is 0 by default. It is optional, but can improve response of your system if correctly tuned. Keep in mind this will need to change with the load / mass of your system. + +All values should be strictly positive (>= 0). + +Keep in mind that you must still set your safety limits as before. I recommend you set these a little higher ( > 10%) than the planner values, to give the controller enough control authority. +``` +..motor.config.current_lim = +..controller.config.vel_limit = +``` + +#### Usage +Use the `move_to_pos` function to move to an absolute position: +``` +..controller.move_to_pos() +``` + +### Circular position control +This mode is useful for continuos incremental position movement. For example a robot rolling indefinitely, or an extruder motor or conveyor belt moving with controlled increments indefinitely. +In the regular position mode, the `pos_setpoint` would grow to a very large value and would lose precision due to floating point rounding. + +In this mode, the controller will try to track the position within only one turn of the motor. Specifically, `pos_setpoint` is expected in the range `[0, cpr-1]`, where `cpr` is the number of encoder counts in one revolution. If the `pos_setpoint` is incremented to outside this range (say via step/dir input), it is automatically wrapped around into the correct value. +Note that in this mode `encoder.pos_cpr` is used for feedback in stead of `encoder.pos_estimate`. + +If you try to increment the axis with a large step in one go that exceeds `cpr/2` steps, the motor will go to the same angle around the wrong way. This is also the case if there is a large disturbance. If you have an application where you would like to handle larger steps, you can use a virtual CPR that is an integer times larger than your encoder's actual CPR. Set `encoder.config.cpr = N * your_enc_cpr`, where N is some integer. Choose N to give you an appropriate circular space for your application. + +### Velocity control +Set `axis.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL`.
+You can now control the velocity with `axis.controller.vel_setpoint = 5000` [count/s]. + +### Ramped velocity control +Set `axis.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL`.
+Set the velocity ramp rate (acceleration): `axis.controller.config.vel_ramp_rate = 2000` [counts/s^2]
+Activate the ramped velocity mode: `axis.controller.vel_ramp_enable = True`.
+You can now control the velocity with `axis.controller.vel_ramp_target = 5000` [count/s]. + +### Current control +Set `axis.controller.config.control_mode = CTRL_MODE_CURRENT_CONTROL`.
+You can now control the current with `axis.controller.current_setpoint = 3` [A]. *Note: There is no velocity limiting in current control mode. Make sure that you don't overrev the motor, or exceed the max speed for your encoder.* From 16b1f7e60f30372319e1b29f9175e3835e79e2de Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 28 Nov 2018 22:46:01 -0800 Subject: [PATCH 12/17] add release info to changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6069fbc..10fc161e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Unreleased Features Please add a note of your changes below this heading if you make a Pull Request. +# Releases +## [0.4.7] - 2018-11-28 ### Added * Overspeed fault * Current sense saturation fault. @@ -19,7 +21,6 @@ Please add a note of your changes below this heading if you make a Pull Request. * 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" -# Releases ## [0.4.6] - 2018-10-07 ### Fixed * Broken printing of floats on ascii protocol From 763e50aa9535d66d5ced8d49258e96f4cbc72a5d Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 28 Nov 2018 22:50:06 -0800 Subject: [PATCH 13/17] format changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10fc161e..d77a003e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ Please add a note of your changes below this heading if you make a Pull Request. * Renamed `axis.enable_step_dir` to `axis.step_dir_active` * New process for working with STM32CubeMX. -## Fixed +### Fixed * 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" From 0c75e280a564f960a2d9a0facdbc32e50dacb6c4 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Wed, 28 Nov 2018 23:02:15 -0800 Subject: [PATCH 14/17] fix docs remenant --- docs/getting-started.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 022f0362..d9cc3dd6 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -130,10 +130,10 @@ Try step 5 again ## Firmware **ODrive v3.5 and later**
-Your board should come preflashed with firmware. If you run into problems, follow the instructions [here](odrivetool.md#device-firmware-update) on the DFU procedure before you continue.
+Your board should come preflashed with firmware. If you run into problems, follow the instructions [here](odrivetool.md#device-firmware-update) on the DFU procedure before you continue. **ODrive v3.4 and earlier**
-Your board does **not** come preflashed with any firmware. Follow the instructions [here](odrivetool.md#device-firmware-update) on the STP Link procedure before you continue. +Your board does **not** come preflashed with any firmware. Follow the instructions [here](odrivetool.md#device-firmware-update) on the STP Link procedure before you continue. ## Start `odrivetool` To launch the main interactive ODrive tool, type `odrivetool` Enter. Connect your ODrive and wait for the tool to find it. Now you can, for instance type `odrv0.vbus_voltage` Enter to inpect the boards main supply voltage. From 414f84a2ce16b2616141809368ef778329586551 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Thu, 6 Dec 2018 20:21:00 -0800 Subject: [PATCH 15/17] add dump errors util function --- CHANGELOG.md | 3 +++ docs/troubleshooting.md | 16 ++----------- tools/odrive/enums.py | 52 ++++++++++++++++++++++++++++++++--------- tools/odrive/shell.py | 5 ++-- tools/odrive/utils.py | 42 ++++++++++++++++++++++++++++++--- 5 files changed, 88 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d77a003e..6b001221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Unreleased Features Please add a note of your changes below this heading if you make a Pull Request. +### Added +* `dump_errors()` utility function in odrivetool to dump, decode and optionally clear errors. + # Releases ## [0.4.7] - 2018-11-28 ### Added diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index c05c7f92..c5556d02 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -14,21 +14,9 @@ Table of Contents: ## Error codes -If your ODrive is not working as expected, run `odrivetool` and type `hex(.error)` Enter where `` is the axis that isn't working. This will display a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) representation of the error code. Each bit represents one error flag. - -
Example
-Say you got this error output: -```python -In [1]: hex(odrv0.axis0.error) -Out[1]: '0x6' -``` - -Written in binary, the number `0x6` corresponds to `110`, that means bits 1 and 2 are set (counting starts at 0). -Looking at the reference below, this means that both `ERROR_DC_BUS_UNDER_VOLTAGE` and `ERROR_DC_BUS_OVER_VOLTAGE` occurred. -
- -The axis error may say that some other component has failed. Say it reports `ERROR_ENCODER_FAILED`, then you need to go check the encoder error: `hex(.encoder.error)`. +If your ODrive is not working as expected, run `odrivetool` and type `dump_errors(odrv0)` Enter. This will dump a list of all the errors that are present. To also clear all the errors, you can run `dump_errors(odrv0, True)`. +The following sections will give some guidance on the most common errors. You may also check the code for the full list of errors: * Axis error flags defined [here](../Firmware/MotorControl/axis.hpp). * Motor error flags defined [here](../Firmware/MotorControl/motor.hpp). * Encoder error flags defined [here](../Firmware/MotorControl/encoder.hpp). diff --git a/tools/odrive/enums.py b/tools/odrive/enums.py index 19572c90..26e0f816 100644 --- a/tools/odrive/enums.py +++ b/tools/odrive/enums.py @@ -11,17 +11,47 @@ AXIS_STATE_ENCODER_INDEX_SEARCH = 6 AXIS_STATE_ENCODER_OFFSET_CALIBRATION = 7 AXIS_STATE_CLOSED_LOOP_CONTROL = 8 -AXIS_ERROR_NONE = 0 -AXIS_ERROR_INVALID_STATE = 1 -#AXIS_ERROR_DC_BUS_UNDER_VOLTAGE = 2 -#AXIS_ERROR_DC_BUS_OVER_VOLTAGE = 3 -#AXIS_ERROR_CURRENT_MEASUREMENT_TIMEOUT = 4 -#AXIS_ERROR_CONTROL_LOOP_TIMEOUT = 5 -#AXIS_ERROR_MOTOR_FAILED = 6 -#AXIS_ERROR_SENSORLESS_ESTIMATOR_FAILED = 7 -#AXIS_ERROR_ENCODER_FAILED = 8 -#AXIS_ERROR_CONTROLLER_FAILED = 9 -#AXIS_ERROR_POS_CTRL_DURING_SENSORLESS = 10 +class errors: + class axis: + ERROR_NONE = 0x00 + ERROR_INVALID_STATE = 0x01 # Date: Mon, 17 Dec 2018 13:51:03 -0800 Subject: [PATCH 16/17] add ignore_illegal_hall_state --- Firmware/MotorControl/encoder.cpp | 6 ++++-- Firmware/MotorControl/encoder.hpp | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Firmware/MotorControl/encoder.cpp b/Firmware/MotorControl/encoder.cpp index 8c0691f8..9b964f21 100644 --- a/Firmware/MotorControl/encoder.cpp +++ b/Firmware/MotorControl/encoder.cpp @@ -271,8 +271,10 @@ bool Encoder::update() { if (delta_enc > 3) delta_enc -= 6; } else { - set_error(ERROR_ILLEGAL_HALL_STATE); - return false; + if (!config_.ignore_illegal_hall_state) { + set_error(ERROR_ILLEGAL_HALL_STATE); + return false; + } } } break; diff --git a/Firmware/MotorControl/encoder.hpp b/Firmware/MotorControl/encoder.hpp index 78f8f4f6..96e1a914 100644 --- a/Firmware/MotorControl/encoder.hpp +++ b/Firmware/MotorControl/encoder.hpp @@ -37,6 +37,7 @@ public: float offset_float = 0.0f; // Sub-count phase alignment offset float calib_range = 0.02f; float bandwidth = 1000.0f; + bool ignore_illegal_hall_state = false; }; Encoder(const EncoderHardwareConfig_t& hw_config, @@ -106,7 +107,8 @@ public: make_protocol_property("offset_float", &config_.offset_float), make_protocol_property("bandwidth", &config_.bandwidth, [](void* ctx) { static_cast(ctx)->update_pll_gains(); }, this), - make_protocol_property("calib_range", &config_.calib_range) + make_protocol_property("calib_range", &config_.calib_range), + make_protocol_property("ignore_illegal_hall_state", &config_.ignore_illegal_hall_state) ) ); } From 6e34beba9fa88e13610e46c586869ccf3084da97 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Mon, 17 Dec 2018 14:19:55 -0800 Subject: [PATCH 17/17] increase analog polling to 100Hz --- Firmware/MotorControl/low_level.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/MotorControl/low_level.cpp b/Firmware/MotorControl/low_level.cpp index 7748d6f4..e8fe62a4 100644 --- a/Firmware/MotorControl/low_level.cpp +++ b/Firmware/MotorControl/low_level.cpp @@ -734,7 +734,7 @@ static void analog_polling_thread(void *) if (is_endpoint_ref_valid(map->endpoint)) update_analog_endpoint(map, i + 1); } - osDelay(200); + osDelay(10); } }