From 965fad3174e45548b6953c36cc370578b25f8867 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Thu, 20 Sep 2018 19:20:07 -0700 Subject: [PATCH 1/3] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index baaf20c1..b9a9a5aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Please add a note of your changes below this heading if you make a Pull Request. * Hardcoded maximum inductance now 2500 uH. ### Fixed +* Incorrect shifting of offset during index callback * Once you got an axis error `ERROR_INVALID_STATE` you could never clear it * Char to int conversion to read motornum on arduino example From f8a31ed662e9c7ddb59bdaba4f26dfbc0f9c4833 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Fri, 21 Sep 2018 21:16:33 -0700 Subject: [PATCH 2/3] Update odrivetool.md --- docs/odrivetool.md | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/docs/odrivetool.md b/docs/odrivetool.md index 6041928d..01670257 100644 --- a/docs/odrivetool.md +++ b/docs/odrivetool.md @@ -143,36 +143,14 @@ This procedure is only necessary for ODrive v3.4 or earlier. You will need an ST Power up the ODrive. 4. Open up a terminal and navigate to the directory where the firmware is. 5. Run the following command (replace `ODriveFirmware_v3.4-24V.elf` with the name of your firmware file): - ``` -~/Downloads $ openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c reset\ halt -c flash\ write_image\ erase\ ODriveFirmware_v3.4-24V.elf -c reset\ run -c exit -Open On-Chip Debugger 0.10.0 -Licensed under GNU GPL v2 -For bug reports, read - http://openocd.org/doc/doxygen/bugs.html -Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '. -Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD -adapter speed: 2000 kHz -adapter_nsrst_delay: 100 -none separate -Info : Unable to match requested speed 2000 kHz, using 1800 kHz -Info : Unable to match requested speed 2000 kHz, using 1800 kHz -Info : clock speed 1800 kHz -Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748 -Info : using stlink api v2 -Info : Target voltage: 3.236027 -Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints -adapter speed: 2000 kHz -target halted due to debug-request, current mode: Thread -xPSR: 0x01000000 pc: 0x08009224 msp: 0x20020000 -auto erase enabled -Info : device id = 0x10076413 -Info : flash size = 1024kbytes -target halted due to breakpoint, current mode: Thread -xPSR: 0x61000000 pc: 0x20000046 msp: 0x20020000 -Warn : no flash bank found for address 10000000 +``` +openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase ODriveFirmware_v3.4-24V.elf" -c "reset run" -c exit +``` + +If everything worked correctly, you should see something similar to this towards the end of the printout: +``` wrote 262144 bytes from file ODriveFirmware_v3.4-24V.elf in 10.194110s (25.113 KiB/s) -adapter speed: 2000 kHz - ``` +``` If something doesn't work, make sure `openocd` is in your `PATH` variable, check that the wires are connected properly and try with elevated privileges. From 3e6a1af48f7779176e61db6706621a8b1a164206 Mon Sep 17 00:00:00 2001 From: Oskar Weigl Date: Tue, 25 Sep 2018 23:26:04 -0700 Subject: [PATCH 3/3] Carry over big update to getting-started to master --- docs/getting-started.md | 117 ++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 994009f1..f4035948 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -12,6 +12,7 @@ permalink: / - [Hardware Requirements](#hardware-requirements) - [Wiring up the ODrive](#wiring-up-the-odrive) - [Downloading and Installing Tools](#downloading-and-installing-tools) +- [Firmware](#firmware) - [Start `odrivetool`](#start-odrivetool) - [Configure M0](#configure-m0) - [Position control of M0](#position-control-of-m0) @@ -21,8 +22,7 @@ permalink: / ## Hardware Requirements -You will need: - +### You will need: * One or two [brushless motors](https://docs.google.com/spreadsheets/d/12vzz7XVEK6YNIOqH0jAz51F5VUpc-lJEs3mmkWP1H4Y). It is fine, even recommended, to start testing with just a single motor and encoder. * One or two [quadrature incremental encoder(s)](encoders) * A power resistor. A good starting point would be the 50W resistor included with your ODrive. @@ -49,14 +49,18 @@ You will need: ## Wiring up the ODrive
-Make sure you have a good mechanical connection between the encoder and the motor, slip can cause disasterous oscillations or runaway. +Make sure you have a good mechanical connection between the encoder and the motor, slip can cause disastrous oscillations or runaway.
All non-power I/O is 3.3V output and 5V tolerant on input, on ODrive v3.3 and newer. -1. Wire up the motor phases into the 3-phase screw terminals, and the power resistor to the AUX terminal. Wire up the power source to the DC terminal, make sure to pay attention to the polarity. Do not apply power just yet. +### Wiring up the motors +* Connect the motor phases into the 3-phase screw terminals. It is not recommended to use a clip-on connector such as an alligator clip, as this can cause issues with the phase resistance/inductance measurements. +* Connect the power source to the DC terminals. Make sure to pay attention to the polarity. +* Do not apply power just yet. -2. Wire up the encoder(s) to J4. The A,B phases are required, and the Z (index pulse) is optional. The A,B and Z lines have 3.3k pull up resistors, for use with open-drain encoder outputs. For single ended push-pull signals with weak drive current (\<4mA), you may want to desolder the pull-ups. +### Wiring up the encoders +Connect the encoder(s) to J4. The A,B phases are required, and the Z (index pulse) is optional. The A,B and Z lines have 3.3k pull up resistors, for use with open-drain encoder outputs. For single ended push-pull signals with weak drive current (\<4mA), you may want to desolder the pull-ups. ![Image of ODrive all hooked up](https://docs.google.com/drawings/d/e/2PACX-1vTCD0P40Cd-wvD7Fl8UYEaxp3_UL81oI4qUVqrrCJPi6tkJeSs2rsffIXQRpdu6rNZs6-2mRKKYtILG/pub?w=1716&h=1281) @@ -120,20 +124,22 @@ Try step 5 again 1. [Install Python 3](https://www.python.org/downloads/). 2. Install the ODrive tools by opening a terminal and typing `pip install odrive` Enter -3. __Linux__: set up USB permissions +3. Set up USB permissions ```bash echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="0d[0-9][0-9]", MODE="0666"' | sudo tee /etc/udev/rules.d/91-odrive.rules sudo udevadm control --reload-rules sudo udevadm trigger ``` +## 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. + +#### 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. + ## Start `odrivetool` - -
__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.
- -
__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.
- -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. +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. It should look something like this: ```text @@ -148,63 +154,77 @@ Out[1]: 11.97055721282959 The tool you're looking at is a fully capable Python command prompt, so you can type any valid python code. -You can read more about the odrivetool [here](odrivetool.md). +You can read more about `odrivetool` [here](odrivetool.md). ## Configure M0 -
Read this section carefully, else you risk breaking something.
There is a [separate guide](hoverboard.md) specifically for hoverboard motors.
### 1. Set the limits:
Wait, how do I set these?
+ In the previous step we started `odrivetool`. In there, you can assign variables directly by name. For instance, to set the current limit of M0 to 10A you would type: `odrv0.axis0.motor.config.current_lim = 10` Enter
-* The current limit: `odrv0.axis0.motor.config.current_lim` [A]. 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. 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 configeration 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...
- The current in the motor is only connected to the current in the power supply _sometimes_ and other times it just cycles out of one phase and back in the other. This is what the modulation magnitude is (sometimes people call this duty cycle, but that's a bit confusing because we use SVM not straight PWM). When the modulation magnitude is 0, the average voltage seen across the motor phases is 0, and the motor current is never connected to the power supply. When the magnitude is 100%, it is always connected, and at 50% it's connected half the time, and cycled in just the motor half the time. +#### 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 largest effect on modulation magnitude is speed. There are other smaller factors, but in general: if the motor is still it's not unreasonable to have 50A in the motor from 5A on the power supply. When the motor is spinning close to top speed, the power supply current and the motor current will be somewhat close to each other. +*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...
+The current in the motor is only connected to the current in the power supply _sometimes_ and other times it just cycles out of one phase and back in the other. This is what the modulation magnitude is (sometimes people call this duty cycle, but that's a bit confusing because we use SVM not straight PWM). When the modulation magnitude is 0, the average voltage seen across the motor phases is 0, and the motor current is never connected to the power supply. When the magnitude is 100%, it is always connected, and at 50% it's connected half the time, and cycled in just the motor half the time. + +The largest effect on modulation magnitude is speed. There are other smaller factors, but in general: if the motor is still it's not unreasonable to have 50A in the motor from 5A on the power supply. When the motor is spinning close to top speed, the power supply current and the motor current will be somewhat close to each other.
-* The velocity limit: `odrv0.axis0.controller.config.vel_limit` [counts/s]. The motor will be limited to this speed; again the default value is quite slow. -* You can change `odrv0.axis0.motor.config.calibration_current` [A] to the largest value you feel comfortable leaving running through the motor continously when the motor is stationary. If you are using a small motor (i.e. 15A current rated) you may need to reduce `calibration_current` to a value smaller than the default. +#### Velocity limit +`odrv0.axis0.controller.config.vel_limit` [counts/s]. +The motor will be limited to this speed. Again the default value is quite slow. +#### Calibration current +You can change `odrv0.axis0.motor.config.calibration_current` [A] to the largest value you feel comfortable leaving running through the motor continuously when the motor is stationary. If you are using a small motor (i.e. 15A current rated) you may need to reduce `calibration_current` to a value smaller than the default. -### 2. Set other hardware parameters: +### 2. Set other hardware parameters +`odrv0.config.brake_resistance` [Ohm] +This is the resistance of the brake resistor. If you are not using it, you may set it to `0`. Note that there may be some extra resistance in your wiring and in the screw terminals, so if you are getting issues while braking you may want to increase this parameter by around 0.05 ohm. + +`odrv0.axis0.motor.config.pole_pairs` +This is the number of **magnet poles** in the rotor, **divided by two**. To find this, you can simply count the number of permanent magnets in the rotor, if you can see them. _Note: this is not the same as the number of coils in the stator._ +If you can't see them, try sliding a magnet around the rotor, and counting how many times it stops. This will be the number of **pole pairs**. If you use a magnetic piece of metal instead of a magnet, you will get the number of **magnet poles**. +`odrv0.axis0.motor.config.motor_type` +This is the type of motor being used. Currently two types of motors are supported: High-current motors (`MOTOR_TYPE_HIGH_CURRENT`) and gimbal motors (`MOTOR_TYPE_GIMBAL`). - * `odrv0.config.brake_resistance` [Ohm]: This is the resistance of the brake resistor. If you are not using it, you may set it to `0`. Note that there may be some extra resistance in your wiring and in the screw terminals, so if you are getting issues while braking you may want to increase this parameter by around 0.05 ohm. - * `odrv0.axis0.motor.config.pole_pairs`: This is the number of **magnet poles** in the rotor, **divided by two**. You can simply count the number of permanent magnets in the rotor, if you can see them. _Note: this is not the same as the number of coils in the stator._ - * `odrv0.axis0.motor.config.motor_type`: This is the type of motor being used. Currently two types of motors are supported: High-current motors (`MOTOR_TYPE_HIGH_CURRENT`) and Gimbal motors (`MOTOR_TYPE_GIMBAL`). +
Which motor_type to choose?
-
Which `motor_type` to choose?
- If you're using a regular hobby brushless motor like [this](https://hobbyking.com/en_us/turnigy-aerodrive-sk3-5065-236kv-brushless-outrunner-motor.html) one, you should set `motor_mode` to `MOTOR_TYPE_HIGH_CURRENT`. For low-current gimbal motors like [this](https://hobbyking.com/en_us/turnigy-hd-5208-brushless-gimbal-motor-bldc.html) one, you should choose `MOTOR_TYPE_GIMBAL`. Do not use `MOTOR_TYPE_GIMBAL` on a motor that is not a gimbal motor, as it may overheat the motor or the ODrive. +If you're using a regular hobby brushless motor like [this](https://hobbyking.com/en_us/turnigy-aerodrive-sk3-5065-236kv-brushless-outrunner-motor.html) one, you should set `motor_mode` to `MOTOR_TYPE_HIGH_CURRENT`. For low-current gimbal motors like [this](https://hobbyking.com/en_us/turnigy-hd-5208-brushless-gimbal-motor-bldc.html) one, you should choose `MOTOR_TYPE_GIMBAL`. Do not use `MOTOR_TYPE_GIMBAL` on a motor that is not a gimbal motor, as it may overheat the motor or the ODrive. - **Further detail:** - If 100's of mA of current noise is "small" for you, you can choose `MOTOR_TYPE_HIGH_CURRENT`. - If 100's of mA of current noise is "large" for you, and you do not intend to spin the motor very fast (omega * L << R), and the motor is fairly large resistance (1 ohm or larger), you can chose `MOTOR_TYPE_GIMBAL`. - If 100's of mA current noise is "large" for you, _and_ you intend to spin the motor fast, then you need to replace the shunt resistors on the ODrive. -
+**Further detail:** +If 100's of mA of current noise is "small" for you, you can choose `MOTOR_TYPE_HIGH_CURRENT`. +If 100's of mA of current noise is "large" for you, and you do not intend to spin the motor very fast (Ω * L << R), and the motor is fairly large resistance (1 ohm or larger), you can chose `MOTOR_TYPE_GIMBAL`. +If 100's of mA current noise is "large" for you, _and_ you intend to spin the motor fast, then you need to replace the shunt resistors on the ODrive. - Note: When using gimbal motors, `current_lim` and `calibration_current` actually mean "voltage limit" and "calibration voltage", since we don't use current feedback. This means that if you set it to 10, it means 10V, despite the name of the parameter. +

- * _if using encoder_: `odrv0.axis0.encoder.config.cpr`: Encoder Count Per Revolution (CPR). This is 4x the Pulse Per Revolution (PPR) value. Usually this is indicated in the datasheet of your encoder. - * _if not using encoder_: - * If you wish to run in sensorless mode, please see [Setting up Sensorless](commands.md#setting-up-sensorless). - * If you are using hall sensor feedback, please see the [hoverboard motor example](hoverboard.md). +*Note: When using gimbal motors,* `current_lim` *and* `calibration_current` *actually mean "voltage limit" and "calibration voltage", since we don't use current feedback. This means that if you set it to 10, it means 10V, despite the name of the parameter.* + +#### If using encoder +`odrv0.axis0.encoder.config.cpr`: Encoder Count Per Revolution [CPR] +This is 4x the Pulse Per Revolution (PPR) value. Usually this is indicated in the datasheet of your encoder. +#### If not using encoder +* If you wish to run in sensorless mode, please see [Setting up sensorless](commands.md#setting-up-sensorless). +* If you are using hall sensor feedback, please see the [hoverboard motor example](hoverboard.md). -### 3. Save configuration. -You can save all `.config` parameters to persistent memory such that the ODrive remembers them between power cycles. +### 3. Save configuration +You can save all `.config` parameters to persistent memory so the ODrive remembers them between power cycles. * `odrv0.save_configuration()` Enter. Due to a [known issue](https://github.com/madcowswe/ODrive/issues/183) it is strongly recommended that you reboot following every save of your configuration using `odrv0.reboot()`. ## Position control of M0 - -Let's get motor 0 up and running. The procedure for motor 1 is exactly the same, so feel free to replace read "axis1" wherever it says "axis0". +Let's get motor 0 up and running. The procedure for motor 1 is exactly the same, so feel free to substitute `axis0` wherever it says `axis0`. 1. Type `odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE` Enter. After about 2 seconds should hear a beep. Then the motor will turn slowly in one direction for a few seconds, then back in the other direction. @@ -214,12 +234,13 @@ Let's get motor 0 up and running. The procedure for motor 1 is exactly the same, The startup procedure is demonstrated [here](https://www.youtube.com/watch?v=VCX1bA2xnuY). - **Note**: the rotor must be allowed to rotate without any biased load during startup. That means mass and weak friction loads are fine, but gravity or spring loads are not okay. Also note that in the video, the motors spin after initalisation, but in the current software the default behaviour is not like that. + *Note: the rotor must be allowed to rotate without any biased load during startup. That means mass and weak friction loads are fine, but gravity or spring loads are not okay. Also note that in the video, the motors spin after initialization, but in the current software the default behaviour is not like that.*
Help, something isn't working!
+ Check the encoder wiring and that the encoder is firmly connected to the motor. Check the value of `hex(odrv0.axis0.error)` and then refer to the [error code documentation](troubleshooting.md#error-codes) for details. - Once you have understood the error and fixed its cause, you may clear the error state (`odrv0.axis0.error = 0` Enter) and retry. You may also need to clear the error state of other subcomponents (e.g. `odrv0.axis0.motor.error`). + Once you understand the error and have fixed its cause, you may clear the error state with (`odrv0.axis0.error = 0` Enter) and retry. You may also need to clear the error state of other subcomponents (e.g. `odrv0.axis0.motor.error = 0`).
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. @@ -227,8 +248,14 @@ Let's get motor 0 up and running. The procedure for motor 1 is exactly the same, ### Other control modes The ODrive also supports velocity control and current (torque) control. -* **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`. Units are counts/s. -* **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`. Units are 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. +#### 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]. +#### 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]. + +*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.* ## What's next?