|
|
(8 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| RoboVero™ is a robotics expansion board for the Overo COM series. | | RoboVero™ is a robotics expansion board for the Overo COM series. |
| | | |
− | [[Image:view_top_robovero.jpg|thumb|450px|RoboVero™ Expansion Board]]
| + | Getting started information about RoboVero is available at [http://robovero.org/ RoboVero.org] |
− | | + | |
− | = Quickstart =
| + | |
− | | + | |
− | == Connect ==
| + | |
− | | + | |
− | All RoboVero boards ship with a peripheral driver library and command line interface preflashed. When you apply power, a red LED should illuminate immediately. This indicates that code is executing on the board. The LED stays on until a USB connection is established when it begins blinking at a heartbeat rhythm. The device should appear as /dev/ttyACM0. You can connect with kermit.
| + | |
− | | + | |
− | $ ls /dev | grep ttyACM
| + | |
− | ttyACM0
| + | |
− | $ kermit -l /dev/ttyACM0
| + | |
− |
| + | |
− | C-Kermit 8.0.211, 10 Apr 2004, for Linux
| + | |
− | Copyright (C) 1985, 2004,
| + | |
− | Trustees of Columbia University in the City of New York.
| + | |
− | Type ? or HELP for help.
| + | |
− | C-Kermit> set carrier-watch off
| + | |
− | C-Kermit> connect
| + | |
− | | + | |
− | <snip welcome message>
| + | |
− | press enter to begin...
| + | |
− | | + | |
− | This gives you a simple command line interface to most of the NXP driver functions.
| + | |
− | | + | |
− | | + | |
− | = Hardware =
| + | |
− | | + | |
− | [[Image:HubCommander.png|thumb|300px|HubCommander™]]
| + | |
− | | + | |
− | All you need to get started with RoboVero is a power source - a 5-15V battery or 5V power supply will do - and USB-A to Mini-B cable. Note that the RoboVero power supply is different from that of other expansion boards.
| + | |
− | | + | |
− | RoboVero is based on the NXP LPC1769 ARM Cortex-M3 microcontroller. Schematic and layout are available [http://pubs.gumstix.com/boards/ROBOVERO/ here]
| + | |
− | | + | |
− | == HubCommander ==
| + | |
− | | + | |
− | When an external machine is connected to the RoboVero USB Mini-B, it automatically takes control of the RoboVero USB subsystem.
| + | |
− | | + | |
− | = Toolchain =
| + | |
− | | + | |
− | == Prerequisites ==
| + | |
− | | + | |
− | You'll need to install git to retrieve some of the software for the toolchain.
| + | |
− | | + | |
− | $ sudo apt-get install gawk bison flex automake libtool libncurses5-dev zlib1g-dev libusb-dev unzip
| + | |
− | | + | |
− | Create a new folder in your home directory.
| + | |
− | | + | |
− | $ mkdir ${HOME}/cortex-m3
| + | |
− | | + | |
− | == crosstool-NG ==
| + | |
− | | + | |
− | A cross compiler builds executable code for a platform other than the one on which the compiler runs. In our case, the toolchain (compiler, linker, debugger, etc.) will typically run on i386 or i686 and generate binaries for ARMv7-M. crosstool-NG is an application for building cross toolchains.
| + | |
− | | + | |
− | === ARM Angstrom ===
| + | |
− | | + | |
− | Building the RoboVero toolchain for Overo takes hours and requires installing a number of non-standard packages. The easiest way to get started is to download the archive containing a pre-built toolchain and extract it to your home folder.
| + | |
− | | + | |
− | NOTE: This hasn't been tested with a clean build and may require additional packages.
| + | |
− | | + | |
− | # cd
| + | |
− | # wget http://cumulus.gumstix.org/sources/robovero/x-tools.tar.gz
| + | |
− | # tar -xzf x-tools.tar.gz
| + | |
− | | + | |
− | Your toolchain should appear in ${HOME}/x-tools. Process the the Exporting PATH section.
| + | |
− | | + | |
− | | + | |
− | === Build From Source ===
| + | |
− | | + | |
− | Go to http://ymorin.is-a-geek.org/dokuwiki/projects/crosstool to determine the current version of crosstool-NG
| + | |
− | | + | |
− | $ cd ${HOME}/cortex-m3
| + | |
− | $ wget http://ymorin.is-a-geek.org/download/crosstool-ng/crosstool-ng-X.X.X.tar.bz2
| + | |
− | | + | |
− | Extract the archive
| + | |
− | | + | |
− | $ tar xjf crosstool-ng-X.X.X.tar.bz2
| + | |
− | $ cd ${HOME}/cortex-m3/crosstool-ng-X.X.X
| + | |
− | | + | |
− | Install crosstool-ng
| + | |
− | | + | |
− | $ ./configure
| + | |
− | $ make
| + | |
− | $ make install
| + | |
− | | + | |
− | Make a new directory for the baremetal configuration file.
| + | |
− | | + | |
− | $ mkdir ${HOME}/cortex-m3/arm-eabi
| + | |
− | $ cd ${HOME}/cortex-m3/arm-eabi
| + | |
− | $ cp ${HOME}/cortex-m3/crosstool-ng-1.9.1/samples/arm-bare_newlib_cortex_m3_nommu-eabi/crosstool.config .config
| + | |
− | | + | |
− | Add gdb to the configuration and build the toolchain. The build will take around 30 minutes depending on your machine.
| + | |
− | | + | |
− | $ ct-ng menuconfig
| + | |
− | Debug facilities ---
| + | |
− | [*] gdb ---
| + | |
− | [*] Cross-gdb
| + | |
− | | + | |
− | $ ct-ng build
| + | |
− | | + | |
− | | + | |
− | === Exporting PATH ===
| + | |
− | | + | |
− | If the build succeeds your new toolchain will appear in ~/x-tools. Add to the PATH environment variable (where the system looks for binaries) by appending an export command to .bashrc. Open a new terminal and echo path to verify that the change has taken effect.
| + | |
− | | + | |
− | $ nano ${HOME}/.bashrc
| + | |
− | export PATH="${HOME}/x-tools/arm-bare_newlib_cortex_m3_nommu-eabi/bin:$PATH"
| + | |
− | | + | |
− | [new terminal]
| + | |
− | $ echo $PATH
| + | |
− | | + | |
− | == LPC1700CMSIS ==
| + | |
− | | + | |
− | LPC1700CMSIS is a collection of source code and libraries to simplify writing firmware for the M3.
| + | |
− | | + | |
− | $ cd ${HOME}/cortex-m3
| + | |
− | $ mkdir LPC1700CMSIS
| + | |
− | $ cd LPC1700CMSIS
| + | |
− | $ wget
| + | |
− | http://ics.nxp.com/support/documents/microcontrollers/zip/lpc17xx.cmsis.driver.library.zip
| + | |
− | $ unzip lpc17xx.cmsis.driver.library.zip
| + | |
− | | + | |
− | === Test ===
| + | |
− | | + | |
− | Time to find out whether we can compile a project. Let's try to build the LPC1700CMSIS Driver Library.
| + | |
− | | + | |
− | $ cd ${HOME}/cortex-m3/LPC1700CMSIS/makesection
| + | |
− | $ nano makeconfig
| + | |
− | | + | |
− | PROJ_ROOT =${HOME}/cortex-m3/LPC1700CMSIS
| + | |
− | CMCORE_TYPE =CM3
| + | |
− | DEVICE =LPC17xx
| + | |
− | MANUFACTURE =NXP
| + | |
− | TOOL =gnu
| + | |
− | DEBUG_MODE =1
| + | |
− | GNU_INSTALL_ROOT =${HOME}/x-tools/arm-bare_newlib_cortex_m3_nommu-eabi
| + | |
− | GNU_VERSION =4.4.1
| + | |
− | | + | |
− | $ cd makerule/common
| + | |
− | $ nano make.rules.environment
| + | |
− | | + | |
− | [remove path and .exe extension from tools - you might also need to change some backslashes]
| + | |
− | | + | |
− | $ cd ../LPC17xx
| + | |
− | $ nano makefile.LPC17xx.gnu
| + | |
− | | + | |
− | TOOLCHAIN =arm-bare_newlib_cortex_m3_nommu-eabi
| + | |
− | | + | |
− | $ ${HOME}/cortex-m3/LPC1700CMSIS
| + | |
− | $ make VERBOSE=yes
| + | |
− | | + | |
− | Take a look at the compiler messages to verify that arm-bare_newlib_cortex_m3_nommu-eabi-gcc and arm-bare_newlib_cortex_m3_nommu-eabi-ld are being invoked. If so, and you get no build errors, the toolchain is working. You can also try building one of the images in the Examples folder.
| + | |
− | | + | |
− | | + | |
− | == FT2232 ==
| + | |
− | | + | |
− | FT2232 is a serial protocol converter that provides JTAG connectivity to the Robovero and console port access to the Overo COM. We need to install the driver for JTAG to work.
| + | |
− | | + | |
− | === Ubuntu ===
| + | |
− | | + | |
− | $ sudo apt-get install libftdi-dev
| + | |
− | | + | |
− | | + | |
− | === ARM Angstrom ===
| + | |
− | | + | |
− | # opkg install libftdi
| + | |
− | | + | |
− | | + | |
− | === Build From Source ===
| + | |
− | | + | |
− | Go to http://www.intra2net.com/en/developer/libftdi/download.php to find the current libftdi release
| + | |
− | | + | |
− | $ cd ${HOME}/cortex-m3
| + | |
− | $ wget http://www.intra2net.com/en/developer/libftdi/download/libftdi-X.X.tar.gz
| + | |
− | $ tar xf libftdi-X.X.tar.gz
| + | |
− | $ cd libftdi-X.XX/
| + | |
− | $ ./configure
| + | |
− | $ make
| + | |
− | $ sudo make install
| + | |
− | $ sudo ldconfig
| + | |
− | | + | |
− | == OpenOCD ==
| + | |
− | | + | |
− | Open On-Circuit Debugger (OpenOCD) provides debugging, in-system programming and boundary-scan testing for the Robovero. It connects the debug host (your development machine) to the target (cortex) through an adapter (FT2232). OpenOCD allows you to debug code running on the target with GDB.
| + | |
− | | + | |
− | === ARM Angstrom ===
| + | |
− | | + | |
− | # wget http://cumulus.gumstix.org/sources/robovero/openocd_0.4-r0.6_armv7a.ipk
| + | |
− | # opkg install openocd_0.4-r0.6_armv7a.ipk
| + | |
− | # wget http://cumulus.gumstix.org/sources/lpc1769.cfg
| + | |
− | # cp lpc1769.cfg /usr/share/openocd/scripts/target
| + | |
− | | + | |
− | | + | |
− | === Build From Source ===
| + | |
− | | + | |
− | $ cd ${HOME}/cortex-m3
| + | |
− | $ wget http://download.berlios.de/openocd/openocd-X.X.X.tar.bz2
| + | |
− | $ tar xjf openocd-X.X.X.tar.bz2
| + | |
− | $ cd openocd-X.X.X/
| + | |
− | $ ./configure --enable-ft2232_libftdi
| + | |
− | $ make
| + | |
− | $ sudo make install
| + | |
− | $ wget http://cumulus.gumstix.org/sources/lpc1769.cfg
| + | |
− | $ sudo cp lpc1769.cfg /usr/local/share/openocd/scripts/target
| + | |
− | | + | |
− | === Test ===
| + | |
− | | + | |
− | Plug in your device. And run OpenOCD to connect.
| + | |
− | | + | |
− | $ sudo openocd -f interface/openocd-usb.cfg -f target/lpc1769.cfg
| + | |
− | Open On-Chip Debugger 0.4.0 (2011-01-06-19:17)
| + | |
− | Licensed under GNU GPL v2
| + | |
− | For bug reports, read
| + | |
− | http://openocd.berlios.de/doc/doxygen/bugs.html
| + | |
− | 500 kHz
| + | |
− | Info : clock speed 500 kHz
| + | |
− | Info : JTAG tap: lpc1768.cpu tap/device found: 0x4ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x4)
| + | |
− | Info : lpc1768.cpu: hardware has 6 breakpoints, 4 watchpoints
| + | |
− | | + | |
− | | + | |
− | == Eclipse ==
| + | |
− | | + | |
− | First, install Eclipse and C/C++ Development Tooling. In Ubuntu,
| + | |
− | | + | |
− | sudo apt-get install eclipse eclipse-cdt
| + | |
− | | + | |
− | If you are using a different OS, go to [http://www.eclipse.org/downloads/ Eclipse downloads] for the correct version. The following instructions are for Eclipse Galileo.
| + | |
− | | + | |
− | | + | |
− | | + | |
− | INSTRUCTIONS
| + | |
− | | + | |
− | = Firmware =
| + | |
− | | + | |
− | == Source ==
| + | |
− | | + | |
− | The source for the firmware that ships with RoboVero is available via github. Follow these steps if you would like to contribute to the project or just use it as a reference.
| + | |
− | | + | |
− | $ cd
| + | |
− | $ mkdir robovero
| + | |
− | $ cd robovero
| + | |
− | $ git clone git://github.com/robovero/firmware.git
| + | |
− | | + | |
− | The source will now appear in ${HOME}/robovero/firmware. Next, build and flash the firmware to your device. If your toolchain isn't at ${HOME}/x-tools you will have to modify the Makefile and PATH environment variable.
| + | |
− | | + | |
− | $ cd firmware
| + | |
− | $ make
| + | |
− | | + | |
− | Start OpenOCD according to the above instructions if you haven't already. Open another terminal. We will flash using GDB.
| + | |
− | | + | |
− | $ wget http://cumulus.gumstix.org/sources/robovero/gdbconfig
| + | |
− | $ x-tools/arm-bare_newlib_cortex_m3_nommu-eabi/bin/arm-bare_newlib_cortex_m3_nommu-eabi-gdb -x gdbconfig robovero/firmware/firmware
| + | |
− | | + | |
− | (gdb) load
| + | |
− | (gdb) continue
| + | |
− | | + | |
− | If your LED starts to flash then your debug tools are working. You can press the RoboVero reset and the firmware will run without GDB.
| + | |
− | | + | |
− | | + | |
− | == Functions ==
| + | |
− | | + | |
− | === list ===
| + | |
− | | + | |
− | You can call '''list''' to see all available functions.
| + | |
− | | + | |
− | [:)] list
| + | |
− | <snip all functions>
| + | |
− | | + | |
− | Or for a more manageable subset, provide a start and the number of functions to display. Note that all arguments and return values are hexadecimal.
| + | |
− | | + | |
− | [:)] list 1 7
| + | |
− | 001 return
| + | |
− | 002 search
| + | |
− | 003 list
| + | |
− | 004 promptOn
| + | |
− | 005 promptOff
| + | |
− | 006 heartbeatOn
| + | |
− | 007 heartbeatOff
| + | |
− | 008 malloc
| + | |
− | 009 free
| + | |
− | 00a deref
| + | |
− | 00b roboveroConfig
| + | |
− | 00c resetConfig
| + | |
− | | + | |
− | The number beside the function name is its index in the function list. You can speed up function calls by using the index rather than the function name.
| + | |
− | | + | |
− | [:)] 3 1 c
| + | |
− | 001 return
| + | |
− | 002 search
| + | |
− | 003 list
| + | |
− | 004 promptOn
| + | |
− | 005 promptOff
| + | |
− | 006 heartbeatOn
| + | |
− | 007 heartbeatOff
| + | |
− | 008 malloc
| + | |
− | 009 free
| + | |
− | 00a deref
| + | |
− | 00b roboveroConfig
| + | |
− | 00c resetConfig
| + | |
− | | + | |
− | | + | |
− | === return ===
| + | |
− | | + | |
− | Your prompt indicates whether the previous operation succeeded.
| + | |
− | | + | |
− | [:)] somenonfunction
| + | |
− | [:(]
| + | |
− | | + | |
− | Naturely, it is best to avoid upsetting RoboVero whenever possible. '''return''' is another mechanism for obtaining the return status.
| + | |
− | | + | |
− | [:)] return
| + | |
− | 0
| + | |
− | [:)] somenonfunction
| + | |
− | [:(] return
| + | |
− | 1
| + | |
− | [:)]
| + | |
− | | + | |
− | There are a couple of subtle points to understand here. First, return indicates the status of the command line, not of the function you are calling. For example, the function I2C_MasterTransferData might fail to transfer data on the I2C bus, and '''return''' will output 0 since the command line operation succeeded - the function was called. The second point is that '''return''' modifies the status variable. If you call a function that fails, and then accidentally call '''retrun''' the status of the previous operation is lost.
| + | |
− | | + | |
− | | + | |
− | === search ===
| + | |
− | | + | |
− | If you want to find the index of a function you can use '''search''' to find it.
| + | |
− | | + | |
− | [:)] search GPIO_SetValue
| + | |
− | 261 GPIO_SetValue
| + | |
− | | + | |
− | If you don't know the full name of the function you can '''search''' part of it.
| + | |
− | | + | |
− | [:)] search GPIO
| + | |
− | 24c GPIO_ClearInt
| + | |
− | 24d GPIO_GetIntStatus
| + | |
− | 24f GPIO_IntCmd
| + | |
− | 252 GPIO_ReadValue
| + | |
− | 25a GPIO_ClearValue
| + | |
− | 261 GPIO_SetValue
| + | |
− | 263 GPIO_SetDir
| + | |
− | 264 GPIO_Byte_TypeDef_malloc
| + | |
− | 265 GPIO_HalfWord_TypeDef_malloc
| + | |
− | 266 GPIO_HalfWord_TypeDef_FIODIRL
| + | |
− | 267 GPIO_HalfWord_TypeDef_FIODIRU
| + | |
− | 268 GPIO_HalfWord_TypeDef_FIOMASKL
| + | |
− | 269 GPIO_HalfWord_TypeDef_FIOMASKU
| + | |
− | 26a GPIO_HalfWord_TypeDef_FIOPINL
| + | |
− | 26b GPIO_HalfWord_TypeDef_FIOPINU
| + | |
− | 26c GPIO_HalfWord_TypeDef_FIOSETL
| + | |
− | 26d GPIO_HalfWord_TypeDef_FIOSETU
| + | |
− | 26e GPIO_HalfWord_TypeDef_FIOCLRL
| + | |
− | 26f GPIO_HalfWord_TypeDef_FIOCLRU
| + | |
− | | + | |
− | If you attempt to call a function that isn't found, '''search''' is called automatically.
| + | |
− | | + | |
− | [:)] GPIO_ClearIn
| + | |
− | 24c GPIO_ClearInt
| + | |
− | | + | |
− | | + | |
− | === promptOn/promptOff ===
| + | |
− | | + | |
− | These functions are used to enable/disable local echo and the command prompt. These are used by the Python Client Library. You will probably not use them unless you are writing your own interface for RoboVero (in C, bash, etc.).
| + | |
− | | + | |
− | [:)] promptOff
| + | |
− | <types promptOn>
| + | |
− | [:)]
| + | |
− | | + | |
− | | + | |
− | === heartbeatOn/heartbeatOff ===
| + | |
− | | + | |
− | If you want to disable the default heartbeat rhythm of the LED call '''heartbeatOff'''.
| + | |
− | | + | |
− | | + | |
− | === malloc ===
| + | |
− | | + | |
− | '''malloc''' allows you to allocate space in RoboVero RAM for data. The following command requests 16 bytes of memory and a pointer to heap space where the memory is allocated is returned.
| + | |
− | | + | |
− | [:)] malloc 10
| + | |
− | 10003900
| + | |
− | | + | |
− | | + | |
− | === free ===
| + | |
− | | + | |
− | Release a block of previously allocated memory back to the heap.
| + | |
− | | + | |
− | [:)] free 10003900
| + | |
− | | + | |
− | | + | |
− | === deref ===
| + | |
− | | + | |
− | Read or write the value stored at a given address. The first argument is the memory address, the second is the width (number of bytes) the value uses. If a third argument is provided the value is written, otherwise it is read.
| + | |
− | | + | |
− | [:)] malloc 4
| + | |
− | 10003900
| + | |
− | [:)] deref 10003900 1
| + | |
− | 72
| + | |
− | [:)] deref 10003900 2
| + | |
− | 4472
| + | |
− | [:)] deref 10003900 4
| + | |
− | a2094472
| + | |
− | [:)] deref 10003900 4 0
| + | |
− | [:)] deref 10003900 4
| + | |
− | 0
| + | |
− | [:)] free 10003900
| + | |
− | | + | |
− | '''deref''' does not validate the memory address provided so you must exercise caution when using this function. A mistyped address could easily lead to a system fault requiring a reset.
| + | |
− | | + | |
− | | + | |
− | === roboveroConfig ===
| + | |
− | | + | |
− | '''roboveroConfig''' exists for users that want to quickly get using the RoboVero in its standard configuration. It automatically configures the pins according to their PCB labels and initializes peripherals. The intent is to reduce the overhead associated with using RoboVero. '''roboveroConfig''' is used in a number of the Python Client Library examples.
| + | |
− | | + | |
− | | + | |
− | === resetConfig ===
| + | |
− | | + | |
− | This is a convenience/safety function that simulates the effect of a reset on pin select registers without disconnecting USB. '''resetConfig''' is called automatically when a Python Client Library program terminates.
| + | |
− | | + | |
− | | + | |
− | === Library functions ===
| + | |
− | | + | |
− | A second group of functions wrap the LPC17xx CMSIS-Compliant Standard Peripheral Firmware Driver Library functions. Pass arguments to these functions as hexadecimal values and expect the same returned. For example, '''GPIO_SetValue''' and '''GPIO_ClearValue''' can be used to manually control the LED. First we need to disable the heartbeat.
| + | |
− | | + | |
− | [:)] heartbeatOff
| + | |
− | | + | |
− | Now we can turn the LED on. Since P3.25 controls the LED's cathode, we need to drive the pin low.
| + | |
− | | + | |
− | [:)] GPIO_ClearValue 3 2000000
| + | |
− | | + | |
− | This is equivalent to the following function call in C, which is used in the heartbeat function.
| + | |
− | | + | |
− | GPIO_ClearValue(3, (1<<25));
| + | |
− | | + | |
− | The command line interface does not resolve mathematical operations such as (1<<25) so anything beyond simple testing quickly becomes cumbersome using the command line. However, it is relatively simple to write a script that makes a series of function calls. This is precisely what the Python Client Library does, and a similar interface can be written in any language that supports serial communication.
| + | |
− | | + | |
− | If you followed the installation above, you can find documentation for library functions in ${HOME}/cortex-m3/LPC1700CMSIS.
| + | |
− | | + | |
− | | + | |
− | === Data functions ===
| + | |
− | | + | |
− | A final category of function is used for safely manipulating data structures used by the peripheral driver library. Here is the definition of PINSEL_CFG_Type:
| + | |
− | | + | |
− | typedef struct
| + | |
− | {
| + | |
− | uint8_t Portnum; /* Port Number: 0 to 4 */
| + | |
− | uint8_t Pinnum; /* Pin Number: 0 to 31 */
| + | |
− | uint8_t Funcnum; /* Function Number: 0 to 3 */
| + | |
− | uint8_t Pinmode; /* Pin Mode: 0 (Internal pull-up resistor), 2 (Tri-state), 3 (Internal pull-down resistor) */
| + | |
− | uint8_t OpenDrain; /* OpenDrain mode: 0 (Normal mode), 1 (Open drain mode) */
| + | |
− | } PINSEL_CFG_Type;
| + | |
− | | + | |
− | Now let's search PINSEL_CFG_Type.
| + | |
− | | + | |
− | [:)] PINSEL_CFG_Type
| + | |
− | 273 PINSEL_CFG_Type_malloc
| + | |
− | 274 PINSEL_CFG_Type_Portnum
| + | |
− | 275 PINSEL_CFG_Type_Pinnum
| + | |
− | 276 PINSEL_CFG_Type_Funcnum
| + | |
− | 277 PINSEL_CFG_Type_Pinmode
| + | |
− | 278 PINSEL_CFG_Type_OpenDrain
| + | |
− | | + | |
− | Using these functions you can allocate space in RoboVero RAM for a PINSEL_CFG_Type struct and access member values. This is how you can use PINSEL_CFG_Type functions to set up I2C communications for the accelerometer, compass, and gyroscope.
| + | |
− | | + | |
− | [:)] PINSEL_CFG_Type_malloc
| + | |
− | 10003900
| + | |
− | [:)] PINSEL_CFG_Type_Portnum 10003900 0
| + | |
− | [:)] PINSEL_CFG_Type_Pinnum 10003900 1B
| + | |
− | [:)] PINSEL_CFG_Type_Pinmode 10003900 0
| + | |
− | [:)] PINSEL_CFG_Type_OpenDrain 10003900 0
| + | |
− | [:)] PINSEL_CFG_Type_Funcnum 10003900 1
| + | |
− | [:)] PINSEL_ConfigPin 10003900
| + | |
− | [:)] PINSEL_CFG_Type_Pinnum 10003900 1C
| + | |
− | [:)] PINSEL_ConfigPin 10003900
| + | |
− | | + | |
− | Now for the sake of the exercise we can read some member values.
| + | |
− | | + | |
− | [:)] PINSEL_CFG_Type_Pinnum 10003900
| + | |
− | 1C
| + | |
− | [:)] PINSEL_CFG_Type_OpenDrain 10003900
| + | |
− | 0
| + | |
− | | + | |
− | And then free the memory where the struct was stored.
| + | |
− | | + | |
− | [:)] free 10003900
| + | |
− | | + | |
− | Note that this is all done for you if you call roboveroConfig.
| + | |
− | | + | |
− | | + | |
− | === Interrupts ===
| + | |
− | | + | |
− | Interrupts are currently unimplement. Enabling an interrupt will most likely lead to very bad things.
| + | |
− | | + | |
− | | + | |
− | = Software =
| + | |
− | | + | |
− | As demonstrated in the [[#Firmware|firmware]] section, it is possible to control RoboVero with a simple serial terminal application. However, for anything but the simplest of tasks, this can quickly become unwieldy. The solution is a language interface that allows RoboVero functions to be called from within a program. One such API is the RoboVero Python Client Library. Python has a comprehensive standard library and online documentation making it an accessible and powerful language for robotics applications.
| + | |
− | | + | |
− | == Source ==
| + | |
− | | + | |
− | The Python Client Library is available via github.
| + | |
− | | + | |
− | $ cd ~/robovero
| + | |
− | $ git clone git://github.com/robovero/python.git
| + | |
− | | + | |
− | | + | |
− | == Overo COM as Host ==
| + | |
− | | + | |
− | Depending on your distribution and image you might need to install python and some modules. On Angstrom,
| + | |
− | | + | |
− | # opkg install python
| + | |
− | # opkg install python-modules
| + | |
− | # opkg install python-pyserial
| + | |
− | | + | |
− | | + | |
− | == Examples ==
| + | |
− | | + | |
− | The easiest way to get started with the Python Client Library is to try some of the included examples. Make sure that your RoboVero is powered, USB is connected, and the device has been reset (see [[#Pitfalls|pitfalls]]).
| + | |
− | | + | |
− | $ cd ~/robovero/python
| + | |
− | | + | |
− | This examples measures a voltage on AD0_0.
| + | |
− | | + | |
− | $ python adc.py
| + | |
− | 1748
| + | |
− | 756
| + | |
− | 883
| + | |
− | 749
| + | |
− | 795
| + | |
− | ^C
| + | |
− | keyboard interrupt: how rude!
| + | |
− | | + | |
− | This example displays x, y, and z readings for the on-board accelerometer, compass, and gyro.
| + | |
− | | + | |
− | $ python IMU.py
| + | |
− | a [x, y, z]: [-880, -640, -16704]
| + | |
− | c [x, y, z]: [-257, -257, -257]
| + | |
− | g [x, y, z]: [-257, -257, -257]
| + | |
− |
| + | |
− | a [x, y, z]: [-832, -608, -16672]
| + | |
− | c [x, y, z]: [-257, -257, -257]
| + | |
− | g [x, y, z]: [-257, -257, -257]
| + | |
− |
| + | |
− | ^CTraceback (most recent call last):
| + | |
− | File "IMU.py", line 130, in <module>
| + | |
− | time.sleep(1)
| + | |
− | KeyboardInterrupt
| + | |
− | | + | |
− | This example requires an RC servo connected to PWM1.
| + | |
− | | + | |
− | New angle: 10
| + | |
− | New angle: 100
| + | |
− | enter an angle between 0 and 90 degrees
| + | |
− | New angle: 20
| + | |
− | New angle: 0
| + | |
− | New angle: ^CTraceback (most recent call last):
| + | |
− | File "servo.py", line 65, in <module>
| + | |
− | match_value = getServoAngle()
| + | |
− | File "servo.py", line 22, in getServoAngle
| + | |
− | user_angle = raw_input("New angle: ")
| + | |
− | KeyboardInterrupt
| + | |
− | | + | |
− | | + | |
− | == Usage ==
| + | |
− | | + | |
− | For the most part, you can call Python Client Library functions the same way as C Peripheral Driver functions - python will even forgive you if your function call is followed by a semi-colon. Some key differences are outlined below using the peripheral pin select as an example.
| + | |
− | | + | |
− | === Includes ===
| + | |
− | | + | |
− | #include "lpc17xx_pinsel.h"; /* C */
| + | |
− | | + | |
− | import robovero.lpc17xx_pinsel # Python
| + | |
− | | + | |
− | Additionally, unless you want to append each function call with the name of the module containing it, you need to import functions and types individually by name.
| + | |
− | | + | |
− | from robovero.lpc17xx_pinsel import PINSEL_CFG_Type, PINSEL_ConfigPin
| + | |
− | | + | |
− | | + | |
− | === Enums ===
| + | |
− | | + | |
− | C enums are represented by classes in Python. The enumerators are class variables. Here is the declaration of a function that accepts an enumerated type as its sole argument.
| + | |
− | | + | |
− | void PINSEL_ConfigTraceFunc (FunctionalState NewState);
| + | |
− | | + | |
− | And here is how it is used in python and C.
| + | |
− | | + | |
− | PINSEL_ConfigTraceFunc(ENABLE); /* C */
| + | |
− | | + | |
− | from robovero.lpc_types import FunctionalState # Python
| + | |
− | PINSEL_ConfigTraceFunc(FunctionalState.ENABLE);
| + | |
− | | + | |
− | | + | |
− | === Structs ===
| + | |
− | | + | |
− | Structs in C are treated as classes in Python. The main differences are declaration and referencing.
| + | |
− | | + | |
− | '''Declaration'''
| + | |
− | PINSEL_CFG_Type PinCfg; /* C */
| + | |
− | PinCfg = PINSEL_CFG_Type() # Python
| + | |
− | | + | |
− | '''Referencing'''
| + | |
− | PINSEL_ConfigPin(&PinCfg); /* C */
| + | |
− | PINSEL_ConfigPin(PinCfg.ptr) # Python
| + | |
− | | + | |
− | | + | |
− | === Arrays ===
| + | |
− | | + | |
− | You can use lists, tuples, strings, etc. to store data in memory on the machine where python is running. In certain cases you need to store an array of data in RoboVero memory. One such case is to use the function UART_SEND which expects a pointer to an array of data. Here is one of many ways this can be achieved in C.
| + | |
− | | + | |
− | #include "string.h"
| + | |
− | #include "lpc17xx_uart.h"
| + | |
− | #include "lpc_types.h"
| + | |
− | #include "LPC17xx.h"
| + | |
− | #include "extras.h"
| + | |
− | | + | |
− | char msg[] = "RoboVero smash!";
| + | |
− | | + | |
− | roboveroConfig();
| + | |
− | UART_Send(LPC_UART1, msg, strlen(msg), BLOCKING);
| + | |
− | | + | |
− | The robovero.extras module contains a class called Array. The initialization functions takes the number of elements, width of each element, and initialization values (optional) as arguments. Values can be a string, list, or single value to copy to RoboVero memory. In case a single value is provided, it is used for each element in the array.
| + | |
− | | + | |
− | from robovero.extras import Array, roboveroConfig
| + | |
− | from robovero.LPC17xx import LPC_UART1
| + | |
− | from robovero.lpc17xx_uart import UART_Send
| + | |
− | from robovero.lpc_types import TRANSFER_BLOCK_Type
| + | |
− |
| + | |
− | _msg = "RoboVero smash!"
| + | |
− | msg = Array(len(_msg), 1, _msg)
| + | |
− | | + | |
− | roboveroConfig()
| + | |
− | UART_Send(LPC_UART1, msg.ptr, msg.length, TRANSFER_BLOCK_Type.BLOCKING)
| + | |
− | | + | |
− | | + | |
− | == Recommended Workflow - Experts ==
| + | |
− | | + | |
− | Python can be used for developing your robotics applications quickly and interactively. If you get into a situation where USB communication latency is hindering performance, try this.
| + | |
− | * Port your code to C
| + | |
− | * Write a wrapper function that unpacks command line arguments and returns a USB string
| + | |
− | * Add your wrapper to the driver function table
| + | |
− | * Add a corresponding python function - this is typically one line
| + | |
− | extras.c and extras.py contain examples of how this is done. This is how the functions '''roboveroConfig''' and '''resetConfig''' were developed. This approach is also being used for the Arduino Compatibility Layer currently under development (some of which is you can find in arduino.py).
| + | |
− | | + | |
− | If you absolutely must use interrupts, there is no need to ditch the Python Client Library for a pure C firmware implementation. Simply write and test your interrupt service routine - you might be able to do so in python before porting to C - and then add it to the vector table in startup.c. Now, you can enable the interrupt through your python application and expect it to be handled with minimal latency.
| + | |
− | | + | |
− | | + | |
− | == Pitfalls ==
| + | |
− | | + | |
− | * When you first connect to RoboVero it asks you to press enter to begin. This is used to detect the line termination that your host machine is using - whether it be an Overo COM, desktop PC, etc. It is possible that PCL sends different line terminators than your favorite serial application (Kermit, Minicom, etc.). If such is the case, you will have to perform a hard reset when switching from Kermit to your program or vice-versa.
| + | |
− | | + | |
− | * The API currently only looks for '/dev/ttyACM0'. If your RoboVero appears under a different name, or you are porting to Windows, you will have to manually change this string in internals.py.
| + | |
RoboVero™ is a robotics expansion board for the Overo COM series.