mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-22 16:14:37 +08:00
+16
-10
@@ -1,6 +1,6 @@
|
||||
# Parameters & Commands
|
||||
|
||||
We will use the `<odrv>` as a placeholder for any ODrive object. In `odrivetool` this is usually `odrv0`. Furthermore we use `<axis>` as a placeholder for any axis (for example `odrv0.axis0`).
|
||||
We will use the `<odrv>` as a placeholder for any ODrive object. Every ODrive controller is an ODrive object. In `odrivetool` this is usually `odrv0`. Furthermore we use `<axis>` as a placeholder for any axis, which is an attribute of an ODrive object (for example `odrv0.axis0`). An axis represents where the motors are connected. (axis0 for M0 or axis1 for M1)
|
||||
|
||||
## Per-Axis commands
|
||||
|
||||
@@ -11,26 +11,27 @@ For the most part, both axes on the ODrive can be controlled independently.
|
||||
The current state of an axis is indicated by `<axis>.current_state`. The user can request a new state by assigning a new value to `<axis>.requested_state`. The default state after startup is `AXIS_STATE_IDLE`.
|
||||
|
||||
1. `AXIS_STATE_IDLE` Disable motor PWM and do nothing.
|
||||
1. `AXIS_STATE_STARTUP_SEQUENCE` Run the [startup procedure](#startup-procedure).
|
||||
1. `AXIS_STATE_FULL_CALIBRATION_SEQUENCE` Run motor calibration and then encoder offset calibration (or encoder index search if `<axis>.encoder.use_index` is `True`).
|
||||
1. `AXIS_STATE_MOTOR_CALIBRATION` Measure phase resistance and phase inductance.
|
||||
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 `<axis>.encoder.use_index` is `True`).
|
||||
4. `AXIS_STATE_MOTOR_CALIBRATION` Measure phase resistance and phase inductance of the motor.
|
||||
* To store the results set `<axis>.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 `<axis>.motor.config.phase_resistance` and `<axis>.motor.config.phase_inductance`.
|
||||
1. `AXIS_STATE_SENSORLESS_CONTROL` Run sensorless control.
|
||||
5. `AXIS_STATE_SENSORLESS_CONTROL` Run sensorless control.
|
||||
* The motor must be calibrated (`<axis>.motor.is_calibrated`)
|
||||
* [`<axis>.controller.control_mode`](#control-mode) must be `True`.
|
||||
1. `AXIS_STATE_ENCODER_INDEX_SEARCH` Turn the motor in one direction until the encoder index is traversed. This state can only be entered if `<axis>.encoder.config.use_index` is `True`.
|
||||
1. `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.
|
||||
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 `<axis>.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 (`<axis>.motor.is_calibrated`).
|
||||
* A successful encoder calibration will make the `<axis>.encoder.is_ready` go to true.
|
||||
1. `AXIS_STATE_CLOSED_LOOP_CONTROL` Run closed loop control.
|
||||
8. `AXIS_STATE_CLOSED_LOOP_CONTROL` Run closed loop control.
|
||||
* The action depends on the [control mode](#control-mode).
|
||||
* Can only be entered if the motor is calibrated (`<axis>.motor.is_calibrated`) and the encoder is ready (`<axis>.encoder.is_ready`).
|
||||
|
||||
### Startup Procedure
|
||||
|
||||
By default the ODrive takes no action at startup and goes to idle immediately.
|
||||
This behavior can be changed by setting any of the following to `True`. The ODrive will sequence all enabled startup actions in the order shown below.
|
||||
In order to change what startup procedures are used, set the startup procedures you want to `True`.
|
||||
The ODrive will sequence all enabled startup actions selected in the order shown below.
|
||||
|
||||
* `<axis>.config.startup_motor_calibration`
|
||||
* `<axis>.config.startup_encoder_index_search`
|
||||
@@ -49,6 +50,12 @@ Possible values are:
|
||||
* `CTRL_MODE_CURRENT_CONTROL`
|
||||
* `CTRL_MODE_VOLTAGE_CONTROL` - this one is not normally used.
|
||||
|
||||
# Control Commands
|
||||
|
||||
* `<axis>.controller.pos_setpoint = <encoder_counts>`
|
||||
* `<axis>.controller.current_setpoint = <current_in_A>`
|
||||
* `<axis>.controller.vel_setpoint = <encoder_counts/s>`
|
||||
|
||||
### Tuning parameters
|
||||
The motion control gains are currently manually tuned:
|
||||
* `<axis>.controller.config.pos_gain = 20.0f` [(counts/s) / counts]
|
||||
@@ -78,4 +85,3 @@ All variables that are part of a `[...].config` object can be saved to non-volat
|
||||
* `<odrv>.serial_number`: A number that uniquely identifies your device. When printed in upper case hexadecimal (`hex(<odrv>.serial_number).upper()`), this is identical to the serial number indicated by the USB descriptor.
|
||||
* `<odrv>.fw_version_major`, `<odrv>.fw_version_minor`, `<odrv>.fw_version_revision`: The firmware version that is currently running.
|
||||
* `<odrv>.hw_version_major`, `<odrv>.hw_version_minor`, `<odrv>.hw_version_revision`: The hardware version of your ODrive.
|
||||
|
||||
|
||||
+20
-4
@@ -43,7 +43,7 @@ You will need:
|
||||
* A power supply (12V-24V for the 24V board variant, 12V-48V for the 48V board variant). A battery is also fine.
|
||||
<details><summary markdown="span">What voltage variant do I have?</summary><div markdown="block">
|
||||
On all ODrives shipped July 2018 or after have a silkscreen label clearly indicating the voltage variant.
|
||||
|
||||
|
||||
ODrives before this may or may not have this label. If you don't have a label, then you can look at the bus capacitors (8 gray cylinder components on the underside of the board). If they read 470uF, you have a 24V version; if they read 120uF you have a 48V version.
|
||||
</div></details>
|
||||
|
||||
@@ -77,7 +77,7 @@ Most instructions in this guide refer to a utility called `odrivetool`, so you s
|
||||
3. Install dependencies by typing `pip install pywin32==222` <kbd>Enter</kbd>
|
||||
3. Install the ODrive tools by typing `pip install odrive` <kbd>Enter</kbd>
|
||||
4. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC.
|
||||
5. Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive driver to libusb-win32.
|
||||
5. Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive driver to libusb-win32.
|
||||
* Check 'List All Devices' from the options menu, and select 'ODrive 3.x Native Interface (Interface 2)'. With that selected in the device list choose 'libusb-win32' from the target driver list and then press the large 'install driver' button.
|
||||
|
||||
|
||||
@@ -104,6 +104,20 @@ brew install libusb
|
||||
pip3 install odrive
|
||||
```
|
||||
|
||||
__Troubleshooting__
|
||||
1. Permission Errors: Just run the previous command in sudo
|
||||
```bash
|
||||
sudo pip3 install odrive
|
||||
```
|
||||
|
||||
2. Dependency Errors: If the installer doesn't complete and you get a dependency
|
||||
error (Ex. "No module..." or "module_name not found")
|
||||
```bash
|
||||
sudo pip3 install module_name
|
||||
```
|
||||
Try step 5 again
|
||||
|
||||
|
||||
### Linux
|
||||
|
||||
1. [Install Python 3](https://www.python.org/downloads/).
|
||||
@@ -117,7 +131,9 @@ pip3 install odrive
|
||||
|
||||
## Start `odrivetool`
|
||||
|
||||
<div class="note" markdown="span">__ODrive v3.4 and earlier:__ Your board does not come preflashed with any firmware. Follow the instructions [here](odrivetool#device-firmware-update) before you continue.</div>
|
||||
<div class="note" markdown="span">__ODrive v3.5 and later:__ Your board should come preflashed with firmware. If you run into problems, follow the instructions [here](odrivetool#device-firmware-update) on the DFU procedure before you continue.</div>
|
||||
|
||||
<div class="note" markdown="span">__ODrive v3.4 and earlier:__ Your board does __not__ come preflashed with any firmware. Follow the instructions [here](odrivetool#device-firmware-update) on the STP Link procedure before you continue.</div>
|
||||
|
||||
To launch the main interactive ODrive tool, type `odrivetool` <kbd>Enter</kbd>. Connect your ODrive and wait for the tool to find it. Now you can for instance type `odrv0.vbus_voltage` <kbd>Enter</kbd> to inpect the boards main supply voltage.
|
||||
It should look something like this:
|
||||
@@ -165,7 +181,7 @@ You can read more about the odrivetool [here](odrivetool.md).
|
||||
* `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`.
|
||||
* `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`).
|
||||
|
||||
|
||||
<details><summary markdown="span">Which `motor_type` to choose?</summary><div markdown="block">
|
||||
|
||||
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.
|
||||
|
||||
+4
-4
@@ -15,7 +15,7 @@ By default, `odrivetool` will connect to any ODrive it finds. If this is not wha
|
||||
To find the serial number of your ODrive, run `odrivetool`, connect exactly one ODrive and power it up. You should see this:
|
||||
```
|
||||
Connected to ODrive 306A396A3235 as odrv0
|
||||
In [1]:
|
||||
In [1]:
|
||||
```
|
||||
`306A396A3235` is the serial number of this particular ODrive. If you want ODrive Tool to ignore all other devices you would close it and then run `odrivetool --serial-number 306A396A3235`.
|
||||
|
||||
@@ -45,7 +45,7 @@ You can use ODrive Tool to back up and restore device configurations or transfer
|
||||
To update the ODrive to the newest firmware release, simply open up a terminal and run the following command:
|
||||
|
||||
```
|
||||
~ $ odrivetool dfu
|
||||
~ $ odrivetool dfu
|
||||
ODrive control utility v0.3.7.dev
|
||||
Waiting for ODrive...
|
||||
Found ODrive 308039673235 (v3.5-24V) with firmware v0.3.7-dev
|
||||
@@ -118,12 +118,12 @@ 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
|
||||
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
|
||||
target halted due to breakpoint, current mode: Thread
|
||||
xPSR: 0x61000000 pc: 0x20000046 msp: 0x20020000
|
||||
Warn : no flash bank found for address 10000000
|
||||
wrote 262144 bytes from file ODriveFirmware_v3.4-24V.elf in 10.194110s (25.113 KiB/s)
|
||||
|
||||
@@ -19,18 +19,18 @@ my_drive = odrive.find_any()
|
||||
print("Bus voltage is " + str(my_drive.vbus_voltage) + "V")
|
||||
|
||||
# Or to change a value, just assign to the property
|
||||
my_drive.motor0.pos_setpoint = 3.14
|
||||
print("Position setpoint is " + str(my_drive.motor0.pos_setpoint))
|
||||
my_drive.axis0.controller.pos_setpoint = 3.14
|
||||
print("Position setpoint is " + str(my_drive.axis0.controller.pos_setpoint))
|
||||
|
||||
# And this is how function calls are done:
|
||||
my_drive.motor0.set_pos_setpoint(0.0, 0.0, 0.0)
|
||||
my_drive.axis0.controller.set_pos_setpoint(0.0, 0.0, 0.0)
|
||||
|
||||
# A sine wave to test
|
||||
t0 = time.monotonic()
|
||||
while True:
|
||||
setpoint = 10000.0 * math.sin((time.monotonic() - t0)*2)
|
||||
print("goto " + str(int(setpoint)))
|
||||
my_drive.motor0.set_pos_setpoint(setpoint, 0.0, 0.0)
|
||||
my_drive.axis0.controller.set_pos_setpoint(setpoint, 0.0, 0.0)
|
||||
time.sleep(0.01)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user