mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-21 07:14:22 +08:00
Merge branch 'devel'
This commit is contained in:
@@ -85,3 +85,15 @@ 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.
|
||||
|
||||
## 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
|
||||
```
|
||||
odrv0.axis0.controller.config.vel_gain = 0.1
|
||||
odrv0.axis0.controller.config.vel_integrator_gain = 0
|
||||
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>)
|
||||
```
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ You can also modify the compile-time defaults for all `.config` parameters. You
|
||||
* 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 `Firmware` directory.
|
||||
__Note__: If you receive the error `can't find target interface/stlink-v2.cfg` or similar, create and set an environment variable named `OPENOCD_SCRIPTS` to the location of the openocd scripts directory.
|
||||
|
||||
If the flashing worked, you can connect to the board using the [odrivetool](getting-started#start-odrivetool).
|
||||
|
||||
|
||||
+48
-44
@@ -41,11 +41,11 @@ You will need:
|
||||
</div></details>
|
||||
|
||||
* 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.
|
||||
<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>
|
||||
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>
|
||||
|
||||
## Wiring up the ODrive
|
||||
|
||||
@@ -68,12 +68,12 @@ Most instructions in this guide refer to a utility called `odrivetool`, so you s
|
||||
### Windows
|
||||
|
||||
1. Install Python 3. We recommend the Anaconda distribution because it packs a lot of useful scientific tools, however you can also install the standalone python.
|
||||
* __Anaconda__: Download the installer from [here](https://www.anaconda.com/download/#windows). Execute the downloaded file and follow the instructions.
|
||||
* __Standalone Python__: Download the installer from [here](https://www.python.org/downloads/). Execute the downloaded file and follow the instructions.
|
||||
* If you have Python 2 installed alongside Python 3, replace `pip` by `C:\Users\YOUR_USERNAME\AppData\Local\Programs\Python\Python36-32\Scripts\pip`. If you have trouble with this step then refer to [this walkthrough](https://www.youtube.com/watch?v=jnpC_Ib_lbc).
|
||||
* __Anaconda__: Download the installer from [here](https://www.anaconda.com/download/#windows). Execute the downloaded file and follow the instructions.
|
||||
* __Standalone Python__: Download the installer from [here](https://www.python.org/downloads/). Execute the downloaded file and follow the instructions.
|
||||
* If you have Python 2 installed alongside Python 3, replace `pip` by `C:\Users\YOUR_USERNAME\AppData\Local\Programs\Python\Python36-32\Scripts\pip`. If you have trouble with this step then refer to [this walkthrough](https://www.youtube.com/watch?v=jnpC_Ib_lbc).
|
||||
2. Launch the command prompt.
|
||||
* __Anaconda__: In the start menu, type `Anaconda Prompt` <kbd>Enter</kbd>
|
||||
* __Standalone Python__: In the start menu, type `cmd` <kbd>Enter</kbd>
|
||||
* __Anaconda__: In the start menu, type `Anaconda Prompt` <kbd>Enter</kbd>
|
||||
* __Standalone Python__: In the start menu, type `cmd` <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.
|
||||
@@ -157,42 +157,46 @@ You can read more about the odrivetool [here](odrivetool.md).
|
||||
|
||||
1. Set the limits:
|
||||
|
||||
<details><summary markdown="span">Wait, how do I set these?</summary><div markdown="block">
|
||||
<details><summary markdown="span">Wait, how do I set these?</summary><div markdown="block">
|
||||
|
||||
In the previous step we started `odrivetool`. In there, you can assign variables directly by name.
|
||||
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` <kbd>Enter</kbd>
|
||||
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>
|
||||
</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.
|
||||
* 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 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.
|
||||
* 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.
|
||||
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.
|
||||
|
||||
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`.
|
||||
* `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`).
|
||||
* `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">
|
||||
<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.
|
||||
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 (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.
|
||||
|
||||
</div></details>
|
||||
</div></details>
|
||||
|
||||
* _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).
|
||||
|
||||
* `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.
|
||||
|
||||
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>
|
||||
@@ -203,19 +207,19 @@ Let's get motor 0 up and running. The procedure for motor 1 is exactly the same,
|
||||
|
||||
1. Type `odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE` <kbd>Enter</kbd>. 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.
|
||||
|
||||
<details><summary markdown="span">What's the point of this?</summary><div markdown="block">
|
||||
This procedure first measures your motor's electrical properties (namely phase resistance and phase inductance) and then the offset between the motor's electrical phase and the encoder position.
|
||||
</div></details>
|
||||
<details><summary markdown="span">What's the point of this?</summary><div markdown="block">
|
||||
This procedure first measures your motor's electrical properties (namely phase resistance and phase inductance) and then the offset between the motor's electrical phase and the encoder position.
|
||||
</div></details>
|
||||
|
||||
The startup procedure is demonstrated [here](https://www.youtube.com/watch?v=VCX1bA2xnuY).
|
||||
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 initalisation, but in the current software the default behaviour is not like that.
|
||||
|
||||
<details><summary markdown="span">Help, something isn't working!</summary><div markdown="block">
|
||||
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.
|
||||
<details><summary markdown="span">Help, something isn't working!</summary><div markdown="block">
|
||||
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` <kbd>Enter</kbd>) and retry. You may also need to clear the error state of other subcomponents (e.g. `odrv0.axis0.motor.error`).
|
||||
</div></details>
|
||||
Once you have understood the error and fixed its cause, you may clear the error state (`odrv0.axis0.error = 0` <kbd>Enter</kbd>) and retry. You may also need to clear the error state of other subcomponents (e.g. `odrv0.axis0.motor.error`).
|
||||
</div></details>
|
||||
|
||||
2. Type `odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL` <kbd>Enter</kbd>. 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` <kbd>Enter</kbd>. The units are in encoder counts.
|
||||
@@ -229,8 +233,8 @@ 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).
|
||||
* See how you can improve the behavior during the startup procedure, like [bypassing encoder calibration](encoders.md#encoder-with-index-signal).
|
||||
* 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).
|
||||
* 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.
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
|
||||
# Hoverboard motor and remote control setup guide
|
||||
By popular request here follows a step-by-step guide on how to setup the ODrive to drive hoverboard motors using RC PWM input.
|
||||
Each step is acompanied by some explanation so hopefully you can carry over some of the steps to other setups and configurations.
|
||||
|
||||
[](https://www.youtube.com/watch?v=ponx_U4xhoM) <br> Click above to play video.
|
||||
|
||||
### Hoverboard motor configuration
|
||||
Standard 6.5 inch hoverboard hub motors have 30 permanent magnet poles, and thus 15 pole pairs. If you have a different motor you need to count the magnets or have a reliable datasheet for this information.
|
||||
```txt
|
||||
odrv0.axis0.motor.config.pole_pairs = 15
|
||||
```
|
||||
|
||||
Hoverboard hub motors are quite high resistance compared to the hobby aircraft motors, so we want to use a bit higher voltage for the motor calibration, and set up the current sense gain to be more sensitive.
|
||||
The motors are also fairly high inductance, so we need to reduce the bandwidth of the current controller from the default to keep it stable.
|
||||
```txt
|
||||
odrv0.axis0.motor.config.resistance_calib_max_voltage = 4
|
||||
odrv0.axis0.motor.config.requested_current_range = 25 #Requires config save and reboot
|
||||
odrv0.axis0.motor.set_current_control_bandwidth(100)
|
||||
```
|
||||
|
||||
Set the encoder to hall mode (instead of incremental). See the [pinout](interfaces.md#hall-feedback-pinout) for instructions on how to plug in the hall feedback.
|
||||
The hall feedback has 6 states for every pole pair in the motor. Since we have 15 pole pairs, we set the cpr to 15*6 = 90.
|
||||
```txt
|
||||
odrv0.axis0.encoder.config.mode = ENCODER_MODE_HALL
|
||||
odrv0.axis0.encoder.config.cpr = 90
|
||||
```
|
||||
|
||||
Since the hall feedback only has 90 counts per revolution, we want to reduce the velocity tracking bandwidth to get smoother velocity estimates.
|
||||
We can also set these fairly modest gains that will be a bit sloppy but shouldn't shake your rig apart if it's built poorly. Make sure to tune the gains up when you have everything else working to a stiffness that is applicable to your application.
|
||||
Lets also start in velocity control mode since that is probably what you want for a wheeled robot. Note that in velocity mode `pos_gain` isn't used but I have given you a recommended value anyway in case you wanted to run position control mode.
|
||||
```txt
|
||||
odrv0.axis0.encoder.config.bandwidth = 100
|
||||
odrv0.axis0.controller.config.pos_gain = 1
|
||||
odrv0.axis0.controller.config.vel_gain = 0.02
|
||||
odrv0.axis0.controller.config.vel_limit = 1000
|
||||
odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL
|
||||
```
|
||||
|
||||
In the next step we are going to start powering the motor and so we want to make sure that some of the above settings that requrie a reboot are applied first.
|
||||
```txt
|
||||
odrv0.save_configuration()
|
||||
odrv0.reboot()
|
||||
```
|
||||
|
||||
Make sure the motor is free to move, then activate the motor calibration.
|
||||
```txt
|
||||
odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
|
||||
```
|
||||
|
||||
You can read out all the data pertaining to the motor:
|
||||
```txt
|
||||
odrv0.axis0.motor
|
||||
```
|
||||
|
||||
Check to see that there is no error and that the phase resistance and inductance are reasonable. Here are the results I got:
|
||||
```txt
|
||||
error = 0x0000 (int)
|
||||
phase_inductance = 0.00033594953129068017 (float)
|
||||
phase_resistance = 0.1793474406003952 (float)
|
||||
```
|
||||
|
||||
If all looks good then you can tell the ODrive that saving this calibration to presistent memory is OK:
|
||||
```txt
|
||||
odrv0.axis0.motor.config.pre_calibrated = True
|
||||
```
|
||||
|
||||
Next step is to check the alignment between the motor and the hall sensor.
|
||||
Because of this step you are allowed to plug the motor phases in random order and also the hall signals can be random. Just don't change it after calibration.
|
||||
Make sure the motor is free to move and run:
|
||||
```txt
|
||||
odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
|
||||
```
|
||||
|
||||
Check the status of the encoder object:
|
||||
```txt
|
||||
odrv0.axis0.encoder
|
||||
```
|
||||
|
||||
Check that there are no errors. If your hall sensors has a standard timing angle then `offset_float` should be close to 0.5.
|
||||
```txt
|
||||
error = 0x0000 (int)
|
||||
offset_float = 0.5126956701278687 (float)
|
||||
```
|
||||
|
||||
If all looks good then you can tell the ODrive that saving this calibration to presistent memory is OK:
|
||||
```txt
|
||||
odrv0.axis0.encoder.config.pre_calibrated = True
|
||||
```
|
||||
|
||||
OK, we are now done with the motor configuration! Time to save, reboot, and then test it.
|
||||
The ODrive starts in idle (we will look at changing this later) so we can enable closed loop control.
|
||||
```txt
|
||||
odrv0.save_configuration()
|
||||
odrv0.reboot()
|
||||
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
|
||||
odrv0.axis0.controller.vel_setpoint = 120
|
||||
# Your motor should spin here
|
||||
odrv0.axis0.controller.vel_setpoint = 0
|
||||
odrv0.axis0.requested_state = AXIS_STATE_IDLE
|
||||
```
|
||||
|
||||
Hopefully you got your motor to spin! Feel free to repeat all of the above for the other axis if appropriate.
|
||||
|
||||
### PWM input
|
||||
If you want to drive your hoverboard wheels around with an RC remote contro you can use the [RC PWM input](interfaces.md#rc-pwm-input). There is more information in that link.
|
||||
Lets use GPIO 3/4 for the velocity inputs so that we don't have to disable UART.
|
||||
Then let's map the full stick range of these inputs to some suitable velocity setpoint range.
|
||||
We also have to reboot to activate the PWM input.
|
||||
```txt
|
||||
odrv0.config.gpio3_pwm_mapping.min = -200
|
||||
odrv0.config.gpio3_pwm_mapping.max = 200
|
||||
odrv0.config.gpio3_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint']
|
||||
|
||||
odrv0.config.gpio4_pwm_mapping.min = -200
|
||||
odrv0.config.gpio4_pwm_mapping.max = 200
|
||||
odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis1.controller._remote_attributes['vel_setpoint']
|
||||
|
||||
odrv0.save_configuration()
|
||||
odrv0.reboot()
|
||||
```
|
||||
|
||||
Now we can check that the sticks are writing to the velocity setpoint. Move the stick, print `vel_setpoint`, move to a different position, check again.
|
||||
```txt
|
||||
In [1]: odrv0.axis1.controller.vel_setpoint
|
||||
Out[1]: 0.1904754638671875
|
||||
|
||||
In [2]: odrv0.axis1.controller.vel_setpoint
|
||||
Out[2]: 0.1904754638671875
|
||||
|
||||
In [3]: odrv0.axis1.controller.vel_setpoint
|
||||
Out[3]: 28.152389526367188
|
||||
|
||||
In [4]: odrv0.axis1.controller.vel_setpoint
|
||||
Out[4]: 61.21905517578125
|
||||
|
||||
In [5]: odrv0.axis1.controller.vel_setpoint
|
||||
Out[5]: -52.990474700927734
|
||||
```
|
||||
|
||||
Ok, now we should be able to turn on the drive and control the wheels!
|
||||
```txt
|
||||
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
|
||||
odrv0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
|
||||
```
|
||||
|
||||
### Automatic startup
|
||||
Try to reboot and then activate AXIS_STATE_CLOSED_LOOP_CONTROL on both axis. Check that everything is operational and works as expected.
|
||||
If so, you can now make the ODrive turn on the motor power automatically after booting. This is useful if you are going to be running the ODrive without a PC or other logic board.
|
||||
```txt
|
||||
odrv0.axis0.config.startup_closed_loop_control = True
|
||||
odrv0.axis1.config.startup_closed_loop_control = True
|
||||
odrv0.save_configuration()
|
||||
odrv0.reboot()
|
||||
```
|
||||
+25
-14
@@ -37,6 +37,26 @@ The ODrive can be controlled over various ports and protocols. If you're comfort
|
||||
|
||||
ODrive v3.3 and onward have 5V tolerant GPIO pins.
|
||||
|
||||
### Pin function priorities
|
||||
1. PWM in, if enabled. Disabled by default.
|
||||
1. UART, **Enabled by default**.
|
||||
1. Step/Dir, if enabled. Disabled by default.
|
||||
1. Analog, default behaviour if not overriden (only on supported pins).
|
||||
1. Digital in, default behaviour on pins not capable of analog input.
|
||||
|
||||
For predictable results, try to have only one feature enabled for any one pin. When changing pin assignments you must:
|
||||
* `odrv0.save_configuration()`
|
||||
* `odrv0.reboot()`
|
||||
|
||||
### Hall feedback pinout
|
||||
When the encoder mode is set to hall feedback, the pinout on the encoder port is as follows:
|
||||
|
||||
| Label on ODrive | Hall feedback |
|
||||
|-----------------|---------------|
|
||||
| A | Hall A |
|
||||
| B | Hall B |
|
||||
| Z | Hall C |
|
||||
|
||||
## Native Protocol
|
||||
|
||||
This protocol is what the ODrive Tool uses to talk to the ODrive. If you have a choice, this is the recommended protocol for all applications. The native protocol runs on USB and can also be configured to run on UART.
|
||||
@@ -76,45 +96,36 @@ Pinout:
|
||||
* GND: you must connect the grounds of the devices together. Use any GND pin on J3 of the ODrive.
|
||||
|
||||
To enable step/dir mode for the GPIO, set `<axis>.config.enable_step_dir` to true for each axis that you wish to use this on.
|
||||
Axis 0 step/dir pins conflicts with UART, and the UART takes priority. So to be able to use step/dir on Axis 0, you must also set `odrv0.config.enable_uart = False`.
|
||||
To apply these settings you must reboot, and to keep them on reboot you must save configuration:
|
||||
* `odrv0.save_configuration()`
|
||||
* `odrv0.reboot()`
|
||||
Axis 0 step/dir pins conflicts with UART, and the UART takes priority. So to be able to use step/dir on Axis 0, you must also set `odrv0.config.enable_uart = False`. See the [pin function priorities](#pin-function-priorities) for more detail. Don't forget to save configuration and reboot.
|
||||
|
||||
There is also a config variable called `<axis>.config.counts_per_step`, which specifies how many encoder counts a "step" corresponds to. It can be any floating point value.
|
||||
The maximum step rate is pending tests, but it should handle at least 50kHz. If you want to test it, please be aware that the failure mode on too high step rates is expected to be that the motors shuts down and coasts.
|
||||
|
||||
Please be aware that there is no enable line right now, and the step/direction interface is enabled by default, and remains active as long as the ODrive is in position control mode. To get the ODrive to go into position control mode at bootup, see how to configure the [startup procedure](commands.md#startup-procedure).
|
||||
|
||||
<!--
|
||||
## RC PWM input
|
||||
|
||||
You can control the ODrive directly from an hobby RC receiver.
|
||||
|
||||
Up to 4 channels (GPIOs 1, 2, 3 and 4) can be used simultaneously if the respective pins are not assigned to other functions. Any of the numerical parameters that are writable from the ODrive Tool can be hooked up to a PWM input.
|
||||
Some GPIO pins can be used for PWM input, if they are not allocated to other functions. For example, you must disable the UART to use GPIO 1,2. See the [pin function priorities](#pin-function-priorities) for more detail.
|
||||
|
||||
Any of the numerical parameters that are writable from the ODrive Tool can be hooked up to a PWM input.
|
||||
As an example, we'll configure GPIO4 to control the angle of axis 0. We want the axis to move within a range of -1500 to 1500 encoder counts.
|
||||
|
||||
1. Make sure you're able control the axis 0 angle by writing to `odrv0.axis0.controller.pos_setpoint`. If you need help with this follow the [getting started guide](getting-started.md).
|
||||
2. It is recommended that you configure the ODrive such that axis 0 automatically goes operational after a reboot. You may have to set `odrv0.axis0.config.startup_encoder_offset_calibration` and `odrv0.axis0.config.startup_closed_loop_control` to `True`. The exact procedure may vary depending on what type of encoder you're using.
|
||||
2. If you want to control your ODrive with the PWM input without using anything else to activate the ODrive, you can configure the ODrive such that axis 0 automatically goes operational at startup. See [here](commands.md#startup-procedure) for more information.
|
||||
3. In ODrive Tool, configure the PWM input mapping
|
||||
```
|
||||
In [1]: odrv0.config.gpio4_pwm_mapping.min = -1500
|
||||
|
||||
In [2]: odrv0.config.gpio4_pwm_mapping.max = 1500
|
||||
|
||||
In [3]: odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['pos_setpoint']
|
||||
```
|
||||
Note: you can disable the input by setting `odrv0.config.gpio4_pwm_mapping.endpoint = None`
|
||||
4. Save the configuration and reboot
|
||||
```
|
||||
In [4]: odrv0.save_configuration()
|
||||
|
||||
In [5]: odrv0.reboot()
|
||||
```
|
||||
5. Connect the RC receiver ground to the ODrive's GND and one of the RC receiver signals to GPIO4. You may try to power the receiver from the ODrive's 5V supply if it doesn't draw too much power. Power up the the RC transmitter. You should now be able to control axis 0 from one of the RC sticks.
|
||||
|
||||
-->
|
||||
5. With the ODrive powered off, connect the RC receiver ground to the ODrive's GND and one of the RC receiver signals to GPIO4. You may try to power the receiver from the ODrive's 5V supply if it doesn't draw too much power. Power up the the RC transmitter. You should now be able to control axis 0 from one of the RC sticks.
|
||||
|
||||
## Ports
|
||||
Note: when you use an existing library you don't have to deal with the specifics described in this section.
|
||||
|
||||
+4
-4
@@ -3,13 +3,13 @@
|
||||
|
||||
Communicating with an ODrive consists of a series of endpoint operations.
|
||||
An endpoint can theoretically be any kind data serialized in any way.
|
||||
There is a default seralization implementation for POD types; for custom types
|
||||
you must (de)seralize yourself. In the future we may provide a default seralizer
|
||||
for stucts.
|
||||
There is a default serialization implementation for POD types; for custom types
|
||||
you must (de)serialize yourself. In the future we may provide a default serializer
|
||||
for structs.
|
||||
The available endpoints can be enumerated by reading the JSON from endpoint 0
|
||||
and can theoretically be different for each communication interface (they are not in practice).
|
||||
|
||||
Each endpoint operation can send bytes to one endpoint (referenced by it's ID)
|
||||
Each endpoint operation can send bytes to one endpoint (referenced by its ID)
|
||||
and at the same time receive bytes from the same endpoint. The semantics of
|
||||
these payloads are specific to each endpoint's type, the name of which is
|
||||
indicated in the JSON.
|
||||
|
||||
Reference in New Issue
Block a user