Skip to content

Commit

Permalink
Merge branch 'master' into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
madcowswe committed Aug 31, 2018
2 parents ca02413 + b3bcdd5 commit a4da373
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 9 deletions.
23 changes: 20 additions & 3 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ An upcoming feature will enable automatic tuning. Until then, here is a rough tu
* Back down `pos_gain` until you do not have overshoot anymore.
* The integrator is not easily tuned, nor is it strictly required. Tune at your own discretion.

## System monitoring commands

### Encoder position and velocity
* View encoder position with `<axis>.encoder.pos_estimate` [counts]
* View rotational velocity with `<axis>.encoder.pll_vel` [counts/s]

### Motor current and torque estimation
* View the commanded motor current with `<axis>.motor.current_control.Iq_setpoint` [A]
* View the measured motor current with `<axis>.motor.current_control.Iq_measured` [A]. If you find that this returns noisy data then use the command motor current instead. The two values should be close so long as you are not approching the maximim achieveable rotational velocity of your motor for a given supply votlage, in which case the commanded current may become larger than the measured current.

Using the motor current and the known KV of your motor you can estimate the motors torque using the following relationship: Torque [N.m] = 8.27 * Current [A] / KV.

## General system commands

### Saving the configuration
Expand All @@ -88,10 +100,15 @@ All variables that are part of a `[...].config` object can be saved to non-volat

## Setting up sensorless
The ODrive can run without encoder/hall feedback, but there is a minimum speed, usually around a few hunderd RPM.
However the
However the units of this mode is different from when using an encoder. Velocities are not measured in counts/s, instead it is electrical rad/s. This also applies to the gains. For example, `vel_gain` is in units of `A / (rad/s)` instead of `A / (count/s)`.

To give an example, suppose you have a motor with 7 pole pairs, and you want to spin it at 3000 RPM. Then you would set the `vel_setpoint` to `3000 * 2*pi/60 * 7 = 2199 rad/s electrical`.

Below are some suggested starting parameters that you can use. Note that you _must_ set the `pm_flux_linkage` correctly for sensorless mode to work.

```
odrv0.axis0.controller.config.vel_gain = 0.1
odrv0.axis0.controller.config.vel_integrator_gain = 0
odrv0.axis0.controller.config.vel_gain = 0.01
odrv0.axis0.controller.config.vel_integrator_gain = 0.05
odrv0.axis0.controller.config.control_mode = 2
odrv0.axis0.controller.vel_setpoint = 400
odrv0.axis0.sensorless_estimator.config.pm_flux_linkage = 5.51328895422 / (<pole pairs> * <motor kv>)
Expand Down
Binary file added docs/figure_1-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/figure_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 8 additions & 5 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,15 @@ In the previous step we started `odrivetool`. In there, you can assign variables
For instance, to set the current limit of M0 to 10A you would type: `odrv0.axis0.motor.config.current_lim = 10` <kbd>Enter</kbd>
</div></details>

* 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.
* 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.
<details><summary markdown="span">Ok so tell me how it actually works then...</summary><div markdown="block">
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.
</div></details>
* 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.
* 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.

### 2. Set other hardware parameters:

Expand All @@ -197,8 +197,11 @@ For instance, to set the current limit of M0 to 10A you would type: `odrv0.axis0


### 3. Save configuration.
You can save all `.config` parameters to persistent memory such that the ODrive remembers them between power cycles.
* `odrv0.save_configuration()` <kbd>Enter</kbd>
You can save all `.config` parameters to persistent memory such that the ODrive remembers them between power cycles.
* `odrv0.save_configuration()` <kbd>Enter</kbd>.

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

Expand Down Expand Up @@ -233,7 +236,7 @@ The ODrive also supports velocity control and current (torque) control.
You can now:

* See what other [commands and parameters](commands.md) are available, including setting tuning parameters for better performance.
* Control the ODrive from your own program or hook it up to an existing system through one of it's [interfaces](interfaces).
* Control the ODrive from your own program or hook it up to an existing system through one of it's [interfaces](interfaces.md).
* See how you can improve the behavior during the startup procedure, like [bypassing encoder calibration](encoders.md#encoder-with-index-signal).

If you have any issues or any questions please get in touch. The [ODrive Community](https://discourse.odriverobotics.com/) warmly welcomes you.
79 changes: 78 additions & 1 deletion docs/odrivetool.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,45 @@ To compile firmware from source, refer to the [developer guide](developer-guide)
* If the DFU script can't find the device, try forcing it into DFU mode.

<details><summary markdown="span">How to force DFU mode (ODrive v3.5)</summary><div markdown="block">
Flick the DIP switch that "DFU, RUN" to "DFU" and power cycle the board. If that alone doesn't work, also connect the After you're done, put the switch back into the "RUN" position and power cycle the board again.
Flick the DIP switch that "DFU, RUN" to "DFU" and power cycle the board. After you're done, put the switch back into the "RUN" position and power cycle the board again.
</div></details>

<details><summary markdown="span">How to force DFU mode (ODrive v3.1, v3.2)</summary><div markdown="block">
Connect the pin "BOOT0" to "3.3V" and power cycle the board. If that alone doesn't work, also connect the pin "GPIO1" to "GND". After you're done, remove the wires and power cycle the board again.
</div></details>

### Upgrading firmware with a different DFU tool
Some people have had issues using the python dfu tool, so below is a guide on how to manually use a different tool.

Before starting the below steps, you need to get firmware binary. You can download one of the officially released firmware files from [here](https://github.com/madcowswe/ODrive/releases). Make sure you select the file that matches your board version, and that you get the __.hex__ file (not the __.elf__ file).

To compile firmware from source, refer to the [developer guide](developer-guide).

#### Windows
You can use the DfuSe app from ST.

1. Download the tool [here](https://www.st.com/en/development-tools/stsw-stm32080.html). Unfortunately they make you create a login to download. Sorry about that.
1. After installing the tool, launch `DfuFileMgr.exe` which probably got added to the start menu as "Dfu file manager".
1. Select "I want to GENERATE a DFU file from S19, HEX or BIN files", press OK.
1. Click the button that says "S19 or Hex...", find the `ODriveFirmware.hex` file you built or downloaded.
1. Leave all the other settings as default and click the "Generate..." button.
1. Save the output file as `ODriveFirmware.dfu`. Note that the success message has a warning sign for some reason...
1. Launch `DfuSeDemo.exe` which probably got added to the start menu as "DfuSeDemo".
1. Force the ODrive into DFU mode, as per the instructions above "How to force DFU mode".
1. In the top left it should now be connected to "STM Device in DFU Mode".
1. If it doesn't appear, it may be because the driver is set to libusb by Zadig. We need to set it back to the original driver. Follow [these instructions](https://github.com/pbatard/libwdi/wiki/FAQ#Help_Zadig_replaced_the_driver_for_the_wrong_device_How_do_I_restore_it).
1. In the bottom right section called "Upgrade or Verify Action" click the button "Choose...".
1. Locate the `ODriveFirmware.dfu` we made before.
1. Click button "Upgrade".
1. If you get a warning that it's not possible to check that it's the correct device type: click yes to continue.
1. Congratulations your ODrive should now be flashed; you can now quit DfuSeDemo.
1. Turn off the power to the ODrive and set the DIP switch back to RUN mode.

#### MacOS or Linux
**This section needs more detail. Please consider adding detail if you got it to work.**
You may be able to use [dfu-util](http://dfu-util.sourceforge.net/) to upgrade the firmware. You will need to convert the .hex file to a .dfu file. You may be able to do it with the python script [dfu-convert](https://github.com/plietar/dfuse-tool/blob/master/dfu-convert) or the c program [hex2dfu](https://github.com/encedo/hex2dfu).

You probably need to force DFU mode, as per the instructions above.

## Flashing with an STLink

Expand Down Expand Up @@ -131,3 +163,48 @@ 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.

## Liveplotter

Liveplotter is used for the graphical plotting of odrive parameters (i.e. position) in real time. To start liveplotter, close any other instances of liveplotter and run `odrivetool liveplotter` from a new anaconda prompt window. By defult two parameters are plotted on startup; the encoder positon of axis 1 and axis 2. In the below example the motors are running in `closed_loop_control` while they are being forced off position by hand.

![Liveplotter position plot](figure_1.png)

To change what parameters are plotted open odrivetool (located in Anaconda3\Scripts or ODrive-master\tools) with a text editor and modify the liveplotter function:
```
# If you want to plot different values, change them here.
# You can plot any number of values concurrently.
cancellation_token = start_liveplotter(lambda: [
my_odrive.axis0.encoder.pos_estimate,
my_odrive.axis1.encoder.pos_estimate,
])
```
For example, to plot the approximate motor torque [N.cm] and the velocity [RPM] of axis1 with a 150KV motor and an 8192 count per rotation econder you would modify the function to read:
```
# If you want to plot different values, change them here.
# You can plot any number of values concurrently.
cancellation_token = start_liveplotter(lambda: [
(((my_odrive.axis0.encoder.pll_vel)/8192)*60), # 8192 CPR encoder
((8.27*my_odrive.axis0.motor.current_control.Iq_setpoint/150) * 100), # Torque [N.cm] = (8.27 * Current [A] / KV) * 100
])
```
In the example below the motor is forced off axis by hand and held there. In response the motor controller increases the torque (orange line) to counteract this disturbance up to a peak of 500 N.cm at which point the motor current limit is reached. When the motor is released it returns back to its commanded position very quickly as can be seen by the spike in the motor velocity (blue line).

![Liveplotter torque vel plot](figure_1-1.png)

To change the scale and sample rate of the plot modify the following parameters located at the beginning of utils.py (located in Anaconda3\Lib\site-packages\odrive):

```
data_rate = 100
plot_rate = 10
num_samples = 1000
```

For more examples on how to interact with the plotting functinality refer to the [Matplotlib examples.](https://matplotlib.org/examples)

### Liveplotter from interactive odrivetool instance
You can also run `start_liveplotter(...)` directly from the interactive odrivetool prompt. This is useful if you want to issue commands or otherwise keep interacting with the odrive while plotting.

For example you can type the following directly into the interactive prompt: `start_liveplotter(lambda: [odrv0.axis0.encoder.pos_estimate])`. Just like the examples above, you can list several parameters to plot separated by comma in the square brackets.
In general, you can plot any variable that you are able to read like normal in odrivetool.

0 comments on commit a4da373

Please sign in to comment.