Skip to content

Commit

Permalink
Merge pull request #102 from madcowswe/devel
Browse files Browse the repository at this point in the history
Release v0.3.1
  • Loading branch information
madcowswe authored Jan 18, 2018
2 parents fc891c4 + 36e739b commit aac04f0
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 90 deletions.
25 changes: 11 additions & 14 deletions Firmware/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,16 @@
"version": "0.2.0",
"configurations": [
{
"type": "gdb",
"request": "attach",
"name": "Debug Firmware",
"target": "localhost:3333",
"gdbpath": "arm-none-eabi-gdb",
"remote": true,
"executable": "./build/ODriveFirmware.elf",
"cwd": "${workspaceRoot}",
"printCalls": false,
//"preLaunchTask": "openocd", // This isn't working quite right.
"autorun": [
"monitor reset halt"
]
}
// For the Cortex-Debug extension
"type": "openocd-gdb",
"request": "launch",
"name": "Debug ODrive",
"executable": "${workspaceRoot}/build/ODriveFirmware.elf",
"configFiles": [
"interface/stlink-v2.cfg",
"target/stm32f4x_stlink.cfg",
],
"cwd": "${workspaceRoot}"
},
]
}
15 changes: 15 additions & 0 deletions Firmware/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## [0.3.1] - 2018-01-18

### Added
* UUID Endpoint
* Reporting of correct ODrive version on USB descriptor
* Getting started instructions for VSCode

### Changed
* USB Product ID to 0x0D32, as it is the only Pid we were allocated on [pid.codes](http://pid.codes/1209/0D32/)
* Recommended method to debug firmware from VSCode now uses Cortex-Debug extension instead of native-debug.
* Refactor IDE instructions into separate files

### Fixed
* Bug where the remote function calls from Python to the ODrive were not working properly.

## [0.3] - 2017-12-18
### Added
* **New binary communication protocol**
Expand Down
11 changes: 8 additions & 3 deletions Firmware/MotorControl/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,18 @@ void motors_0_set_current_setpoint_func(void) {
motors[0].set_current_setpoint_args.current_setpoint);
}
void motors_1_set_pos_setpoint_func(void) {
set_pos_setpoint(&motors[0],
set_pos_setpoint(&motors[1],
motors[1].set_pos_setpoint_args.pos_setpoint,
motors[1].set_pos_setpoint_args.vel_feed_forward,
motors[1].set_pos_setpoint_args.current_feed_forward);
}
void motors_1_set_vel_setpoint_func(void) {
set_vel_setpoint(&motors[0],
set_vel_setpoint(&motors[1],
motors[1].set_vel_setpoint_args.vel_setpoint,
motors[1].set_vel_setpoint_args.current_feed_forward);
}
void motors_1_set_current_setpoint_func(void) {
set_current_setpoint(&motors[0],
set_current_setpoint(&motors[1],
motors[1].set_current_setpoint_args.current_setpoint);
}

Expand All @@ -94,6 +94,9 @@ void motors_1_set_current_setpoint_func(void) {
const Endpoint endpoints[] = {
Endpoint::make_property("vbus_voltage", const_cast<const float*>(&vbus_voltage)),
Endpoint::make_property("elec_rad_per_enc", const_cast<const float*>(&elec_rad_per_enc)),
Endpoint::make_property("UUID_0", (const uint32_t*)(ID_UNIQUE_ADDRESS + 0*4)),
Endpoint::make_property("UUID_1", (const uint32_t*)(ID_UNIQUE_ADDRESS + 1*4)),
Endpoint::make_property("UUID_2", (const uint32_t*)(ID_UNIQUE_ADDRESS + 2*4)),
Endpoint::make_object("motor0"),
Endpoint::make_property("control_mode", reinterpret_cast<int32_t*>(&motors[0].control_mode)),
Endpoint::make_property("error", reinterpret_cast<int32_t*>(&motors[0].error)),
Expand Down Expand Up @@ -123,6 +126,7 @@ const Endpoint endpoints[] = {
Endpoint::make_property("i_gain", &motors[0].current_control.i_gain),
Endpoint::make_property("v_current_control_integral_d", &motors[0].current_control.v_current_control_integral_d),
Endpoint::make_property("v_current_control_integral_q", &motors[0].current_control.v_current_control_integral_q),
Endpoint::make_property("Iq_command", &motors[0].current_control.Iq),
Endpoint::make_property("Ibus", const_cast<const float*>(&motors[0].current_control.Ibus)),
Endpoint::close_tree(),
Endpoint::make_object("encoder"),
Expand Down Expand Up @@ -176,6 +180,7 @@ const Endpoint endpoints[] = {
Endpoint::make_property("i_gain", &motors[1].current_control.i_gain),
Endpoint::make_property("v_current_control_integral_d", &motors[1].current_control.v_current_control_integral_d),
Endpoint::make_property("v_current_control_integral_q", &motors[1].current_control.v_current_control_integral_q),
Endpoint::make_property("Iq_command", &motors[1].current_control.Iq),
Endpoint::make_property("Ibus", const_cast<const float*>(&motors[1].current_control.Ibus)),
Endpoint::close_tree(),
Endpoint::make_object("encoder"),
Expand Down
4 changes: 4 additions & 0 deletions Firmware/MotorControl/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ inline const char* get_default_json_modifier<int32_t>() {
return "\"type\":\"int32\",\"access\":\"rw\"";
}
template<>
inline const char* get_default_json_modifier<const uint32_t>() {
return "\"type\":\"uint32\",\"access\":\"r\"";
}
template<>
inline const char* get_default_json_modifier<const uint16_t>() {
return "\"type\":\"uint16\",\"access\":\"r\"";
}
Expand Down
99 changes: 37 additions & 62 deletions Firmware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ The project is under active development, so make sure to check the [Changelog](C

- [Configuring parameters](#configuring-parameters)
- [Compiling and downloading firmware](#compiling-and-downloading-firmware)
- [Setting up an IDE](#setting-up-an-ide)
- [Continuing without an IDE](#no-ide-instructions)
- [Communicating over USB or UART](#communicating-over-usb-or-uart)
- [Generating startup code](#generating-startup-code)
- [Setting up Eclipse development environment](#setting-up-eclipse-development-environment)
- [Notes for Contributors](#notes-for-contributors)

<!-- /MarkdownTOC -->
Expand Down Expand Up @@ -94,8 +95,8 @@ An upcoming feature will enable automatic tuning. Until then, here is a rough tu
By default both motors are enabled, and the default control mode is position control.
If you want a different mode, you can change `.control_mode`. To disable a motor, set `.enable_control` and `.do_calibration` to false.

<br><br>
## Compiling and downloading firmware

### Getting a programmer
Get a programmer that supports SWD (Serial Wire Debugging) and is ST-link v2 compatible. You can get them really cheap on [eBay](http://www.ebay.co.uk/itm/ST-Link-V2-Emulator-Downloader-Programming-Mini-Unit-STM8-STM32-with-20CM-Line-/391173940927?hash=item5b13c8a6bf:g:3g8AAOSw~OdVf-Tu) or many other places.

Expand All @@ -122,6 +123,15 @@ Install the following:
* [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm). Make is used to script the compilation process. Download and run the complete package setup program. Add the path of the binaries to your PATH environment variable. For me this was at `C:\Program Files (x86)\GnuWin32\bin`. For details on how to set your path envirment in windows see [these instructions.](https://www.java.com/en/download/help/path.xml)
* OpenOCD. Follow the instructions at [GNU ARM Eclipse - How to install the OpenOCD binaries](http://gnuarmeclipse.github.io/openocd/install/), including the part about ST-LINK/V2 drivers. Add the path of the binaries to your PATH environment variable. For me this was at `C:\Program Files\GNU ARM Eclipse\OpenOCD\0.10.0-201704182147-dev\bin`.

<br><br>
## Setting up an IDE
ODrive is a Makefile project. It does not require an IDE, but the open-source IDE VSCode is recommended. It is also possible to use Eclipse. If you'd like to go that route, please see the respective configuration document:

* [Configuring VSCode](configuring-vscode.md)
* [Configuring Eclipse](configuring-eclipse.md)

<br><br>
## No IDE Instructions
After installing all of the above, open a Git Bash shell. Continue at section [Building the firmware](#building-the-firmware).

### Building the firmware
Expand All @@ -138,49 +148,49 @@ After installing all of the above, open a Git Bash shell. Continue at section [B
If the flashing worked, you can start sending commands. If you want to do that now, you can go to [Communicating over USB or UART](#communicating-over-usb-or-uart).

### Debugging the firmware
The following options are known to work and supported:
* Command line GDB. Run `make gdb`. This will reset and halt at program start. Now you can set breakpoints and run the program. If you know how to use gdb, you are good to go.
* Eclipse, see [Setting up Eclipse development environment](#setting-up-eclipse-development-environment).
* Visual Studio Code. The solution we have is not the most elegant, and if you know a better way, please do help us.
* Make sure you have the Firmware folder as your active folder
* Flash the board with the newest code (starting debug session doesn't do this)
* Tasks -> Run Task -> openocd
* Debug -> Start Debugging
* The processor will reset and halt.
* Set your breakpoints. Note: you can only set breakpoints when the processor is halted, if you set them during run mode, they won't get applied.
* Run
* When you are done, you must kill the openocd task before you are able to flash the board again: Tasks -> Terminate task -> openocd.
* Run `make gdb`. This will reset and halt at program start. Now you can set breakpoints and run the program. If you know how to use gdb, you are good to go.

<br><br>
## Communicating over USB or UART

Warning: If testing USB or UART communication for the first time it is recommend that your motors are free to spin continuously and are not connected to a drivetrain with limited travel.
### From Linux/Windows/macOS
There are two simple python scripts to help you get started with controlling the ODrive using python.
There are two example python scripts to help you get started with controlling the ODrive using python. One will drop you into an interactive shell to query settings, parameters, and variables, and let you send setpoints manually ([tools/explore_odrive.py](tools/explore_odrive.py)). The other is a demo application to show you how to control the ODrive programmatically ([tools/demo.py](tools/demo.py)). Below follows a step-by-step guide on how to run these.


1. [Install Python 3](https://www.python.org/downloads/), then install dependencies:
* __Windows__: It is recommended to use a Unix style command prompt, such as Git Bash that comes with [Git for windows](https://git-scm.com/download/win).

1. [Install Python 3](https://www.python.org/downloads/), then install dependencies pyusb and pyserial:
```
pip install pyusb pyserial
```
3. __Linux__: set up USB permissions
* Note: If you have python2 and python3 installed concurrently then you must specifiy that we wish to target python3. This is done as follows:
* __Linux__: Use `pip3` instead of `pip` in the above command.
* __Windows__: Use the full path of the Python3 pip, yeilding something like:
`C:\Users\YOUR_USERNAME\AppData\Local\Programs\Python\Python36-32\Scripts\pip install pyusb pyserial`
* If you have trouble with this step then refer to [this walkthrough.](https://www.youtube.com/watch?v=jnpC_Ib_lbc)

2. __Linux__: set up USB permissions
```
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="0d[0-9][0-9]", MODE="0666"' | sudo tee /etc/udev/rules.d/50-odrive.rules
sudo udevadm control --reload-rules
sudo udevadm trigger # until you reboot you may need to do this everytime you reset the ODrive
```
4. Power the ODrive board (as per the [Flashing the firmware](#flashing-the-firmware) step)
5. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC
6. __Windows__: Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb.
3. Power the ODrive board (as per the [Flashing the firmware](#flashing-the-firmware) step).
4. Plug in a USB cable into the microUSB connector on ODrive, and connect it to your PC.
5. __Windows__: Use the [Zadig](http://zadig.akeo.ie/) utility to set ODrive (not STLink!) driver to libusb-win32.
* If 'Odrive V3.x' is not in the list of devices upon opening Zadig, check 'List All Devices' from the options menu. With the Odrive selected in the device list choose 'libusb-win32' from the target driver list and select the large 'install driver' button.
7. Run `./tools/demo.py` or `./tools/explore_odrive.py`.
- `demo.py` is a very simple script which will make motor 0 turn back and forth. Use this as an example if you want to control the ODrive yourself programatically.
- `explore_odrive.py` drops you into an interactive python shell where you can explore and edit the parameters that are available on your device. For instance `my_odrive.motor0.pos_setpoint = 10000` makes motor0 move to position 10000. To connect over serial instead of USB run `./tools/explore_odrive.py --discover serial`.
6. Open the bash prompt in the `ODrive/tools/` folder.
7. Run `python3 demo.py` or `python3 explore_odrive.py`.
- `demo.py` is a very simple script which will make motor 0 turn back and forth. Use this as an example if you want to control the ODrive yourself programatically.
- `explore_odrive.py` drops you into an interactive python shell where you can explore and edit the parameters that are available on your device. For instance `my_odrive.motor0.pos_setpoint = 10000` makes motor0 move to position 10000. To connect over serial instead of USB run `./tools/explore_odrive.py --discover serial`.

### From Arduino
[See ODrive Arduino Library](https://github.com/madcowswe/ODriveArduino)

### Other platforms
See the [protocol specification](https://github.com/madcowswe/ODrive/blob/devel/Firmware/protocol.md) or the [legacy protocol specification](https://github.com/madcowswe/ODrive/blob/devel/Firmware/legacy-protocol.md).

See the [protocol specification](protocol.md) or the [legacy protocol specification](legacy-protocol.md).

<br><br>
## Generating startup code
**Note:** You do not need to run this step to program the board. This is only required if you wish to update the auto generated code.

Expand All @@ -196,42 +206,7 @@ You will likely want the pinout for this process. It is available [here](https:/
* Press `Project -> Generate code`
* You may need to let it download some drivers and such.

## Setting up Eclipse development environment

### Install
* Install [Eclipse IDE for C/C++ Developers](http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neon3)
* Install the [OpenOCD Eclipse plugin](http://gnuarmeclipse.github.io/plugins/install/)

### Import project
* File -> Import -> C/C++ -> Existing Code as Makefile Project
* Browse for existing code location, find the OdriveFirmware root.
* In the Toolchain options, select `Cross GCC`
* Hit Finish
* Build the project (press ctrl-B)

![Toolchain options](screenshots/CodeAsMakefile.png "Toolchain options")

### Load the launch configuration
* File -> Import -> Run/Debug -> Launch Configurations -> Next
* Highlight (don't tick) the OdriveFirmare folder in the left column
* Tick OdriveFirmware.launch in the right column
* Hit Finish

![Launch Configurations](screenshots/ImportLaunch.png "Launch Configurations")

### Launch!
* Make sure the programmer is connected to the board as per [Flashing the firmware](#flashing-the-firmware).
* Press the down-arrow of the debug symbol in the toolbar, and hit Debug Configurations
* You can also hit Run -> Debug Configurations
* Highlight the debug configuration you imported, called OdriveFirmware. If you do not see the imported launch configuration rename your project to `ODriveFirmware` or edit the launch configuration to match your project name by unfiltering unavailable projects:

![Launch Configuration Filters](screenshots/LaunchConfigFilter.png "Launch Configuration Filters")

* Hit Debug
* Eclipse should flash the board for you and the program should start halted on the first instruction in `Main`
* Set beakpoints, step, hit Resume, etc.
* Make some cool features! ;D

<br><br>
## Notes for Contributors
In general the project uses the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html), except that the default indendtation is 4 spaces, and that the 80 character limit is not very strictly enforced, merely encouraged.

Expand Down
24 changes: 13 additions & 11 deletions Firmware/Src/usbd_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,17 @@

/** @defgroup USBD_DESC_Private_Defines
* @{
*/
#define USBD_VID 0x1209
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "ODrive"
#define USBD_PID_FS 0x0D31
#define USBD_PRODUCT_STRING_FS "ODrive v3.1"
#define USBD_SERIALNUMBER_STRING_FS "000000000001"
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
#define USBD_INTERFACE_STRING_FS "CDC Interface"
*/
#define USBD_VID 0x1209
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "ODrive Robotics"
#define USBD_PID_FS 0x0D32
#define USBD_PRODUCT_XSTR(s) USBD_PRODUCT_STR(s)
#define USBD_PRODUCT_STR(s) #s
#define USBD_PRODUCT_STRING_FS ODrive version HW_VERSION_MAJOR.HW_VERSION_MINOR
#define USBD_SERIALNUMBER_STRING_FS "000000000001"
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
#define USBD_INTERFACE_STRING_FS "CDC Interface"

#define USB_SIZ_BOS_DESC 0x0C

Expand Down Expand Up @@ -253,11 +255,11 @@ uint8_t * USBD_FS_ProductStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *len
{
if(speed == 0)
{
USBD_GetString ((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
USBD_GetString ((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length);
}
else
{
USBD_GetString ((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
USBD_GetString ((uint8_t *)USBD_PRODUCT_XSTR(USBD_PRODUCT_STRING_FS), USBD_StrDesc, length);
}
return USBD_StrDesc;
}
Expand Down
35 changes: 35 additions & 0 deletions Firmware/configuring-eclipse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Setting up Eclipse development environment

## Install
* Install [Eclipse IDE for C/C++ Developers](http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neon3)
* Install the [OpenOCD Eclipse plugin](http://gnuarmeclipse.github.io/plugins/install/)

## Import project
* File -> Import -> C/C++ -> Existing Code as Makefile Project
* Browse for existing code location, find the OdriveFirmware root.
* In the Toolchain options, select `Cross GCC`
* Hit Finish
* Build the project (press ctrl-B)

![Toolchain options](screenshots/CodeAsMakefile.png "Toolchain options")

## Load the launch configuration
* File -> Import -> Run/Debug -> Launch Configurations -> Next
* Highlight (don't tick) the OdriveFirmare folder in the left column
* Tick OdriveFirmware.launch in the right column
* Hit Finish

![Launch Configurations](screenshots/ImportLaunch.png "Launch Configurations")

## Launch!
* Make sure the programmer is connected to the board as per [Flashing the firmware](#flashing-the-firmware).
* Press the down-arrow of the debug symbol in the toolbar, and hit Debug Configurations
* You can also hit Run -> Debug Configurations
* Highlight the debug configuration you imported, called OdriveFirmware. If you do not see the imported launch configuration rename your project to `ODriveFirmware` or edit the launch configuration to match your project name by unfiltering unavailable projects:

![Launch Configuration Filters](screenshots/LaunchConfigFilter.png "Launch Configuration Filters")

* Hit Debug
* Eclipse should flash the board for you and the program should start halted on the first instruction in `Main`
* Set beakpoints, step, hit Resume, etc.
* Make some cool features! ;D
Loading

0 comments on commit aac04f0

Please sign in to comment.