Firefly Eindhoven - Ground Robots: Difference between revisions
(9 intermediate revisions by the same user not shown) | |||
Line 10: | Line 10: | ||
|- | |- | ||
! Attribute | ! Attribute | ||
! v_x | ! <math>v_x</math> | ||
! v_y | ! <math>v_y</math> | ||
! | ! <math>v_{psi}</math> | ||
|- | |- | ||
! Data type | ! Data type | ||
Line 25: | Line 25: | ||
|- | |- | ||
! Unit | ! Unit | ||
| meters/second | | <math>meters/second</math> | ||
| meters/second | | <math>meters/second</math> | ||
| radians/second | | <math>radians/second</math> | ||
|} | |} | ||
The baud rate is 115200. | The baud rate is 115200. | ||
'''Nota bene''' No headers or terminators are used, the user must guarantee that exactly 12 bytes are sent per message, or trailing bytes will mess up new messages. | |||
==ground-robot== | |||
The ground-robot repository contains, among others, scripts to remotely control the ground robot by sending commands over UDP, one to manual control the groub robot with the WASD keys, and another script to detect ground robots on the local network and setup all of them to allow remote control of the robots. | |||
Running the <nowiki>remote_control.py</nowiki> script listens on a UDP socket at port 12000 for messages using the following protocol: | |||
{| class="wikitable" border="1" | |||
|- | |||
! Attribute | |||
! flag | |||
! <math>v_x</math> if flag == 2, <math>a_x</math> if flag == 1 | |||
! <math>v_y</math> if flag == 2, <math>a_y</math> if flag == 1 | |||
! <math>v_{psi}</math> | |||
|- | |||
! Data type | |||
| byte | |||
| double | |||
| double | |||
| double | |||
|- | |||
! Size (bytes) | |||
| 1 | |||
| 3 | |||
| 3 | |||
| 3 | |||
|- | |||
! Unit | |||
| n/a | |||
| <math>meters/second</math> or <math>meters/second^2</math> | |||
| <math>meters/second</math> or <math>meters/second^2</math> | |||
| <math>radians/second</math> | |||
|} | |||
It then integrates them into speeds (only if flag == 1) and send the new target speed over serial to the omnibot-controller. | |||
===deployment=== | |||
The need for a nice system to deploy code to the ground robots arose quickly as we started to use more ground robots simultaneously: they all had to run the same code that was frequently updated, but this was hard to maintain without proper tools. In practice there was usually one ground robot with up to date software, which was developed on the pi itself, and sometimes copy-pasted between two Putty windows to copy it to the next ground robot. A putty session had to be open for each ground robot to keep the remote control script running. Sometimes a powerbank would become disconnected during aggressive movements, resulting in the Raspberry Pi losing power and corrupting the SD-card. Flashing Arduino code was an even greater pain, as they had to be disconnected from the Pi, hooked up to a laptop and then flashed, one by one. | |||
All the ground robots are now flashed with '''volatile write firmware'''. This means that all changes made to the filesystem are stored in volatile RAM instead of being written to disk, and so the ground robot will be reset to its initial state after every reboot. Because the SD-card is never written to, a power loss does not corrupt the SD-card. It also renders the bad practice of developing on the Pi itself impossible, as all files written will be gone after a reboot. Instead, development takes place on a laptop, and when the software is ready for testing it is deployed to all ground robot simultaneously. | |||
A script was developed to make deployment to all ground robots easy. When run it executes the following sequence of commands: | |||
# The local network is scanned for ground robots, the user is presented a list of ip address for these ground robots and can confirm deployment (the user can also choose a subset using a command line parameter). | |||
# The remote_control.py script and all dependencies are copied to every ground robot. | |||
# The ground robot disconnects from its current network, switches to the TUe-Guest network and logs in to the hotspot (this is needed because the default access point used to control the robots does not have internet access).. | |||
# Required package such as python3 are downloaded and installed. | |||
# The ground robot switches back to its original network. | |||
# The ground robot flashes the Arduino with the latest firmware | |||
# The ground robot starts the remote_control.py script, the actuators make a chirping sound to signal the user that the ground robot is ready. | |||
The script is fully cross-platform, requiring only python3 and a few python libraries to work. | |||
=Hardware= | =Hardware= |
Latest revision as of 22:59, 24 May 2018
Software
Every ground robot contains both an Arduino to control the actuators, and a Raspberry Pi for high level control and wireless communication. The code for these devices are in the omnibot-controller and ground-robot repositories respectively.
omnibot-controler
This is a fairly simple Arduino sketch that reads a target speed over the x and y axis as well as a target rotation speed, and controls the actuators to reach this speed. A Makefile is provided that reads the serial ID of the currently connected Arduino, and automatically sets up the pin configuration accordingly, as these are different for every ground robot.
Serial protocol
The serial protocol is defined as follows:
Attribute | [math]\displaystyle{ v_x }[/math] | [math]\displaystyle{ v_y }[/math] | [math]\displaystyle{ v_{psi} }[/math] |
---|---|---|---|
Data type | float | float | float |
Size (bytes) | 4 | 4 | 4 |
Unit | [math]\displaystyle{ meters/second }[/math] | [math]\displaystyle{ meters/second }[/math] | [math]\displaystyle{ radians/second }[/math] |
The baud rate is 115200.
Nota bene No headers or terminators are used, the user must guarantee that exactly 12 bytes are sent per message, or trailing bytes will mess up new messages.
ground-robot
The ground-robot repository contains, among others, scripts to remotely control the ground robot by sending commands over UDP, one to manual control the groub robot with the WASD keys, and another script to detect ground robots on the local network and setup all of them to allow remote control of the robots.
Running the remote_control.py script listens on a UDP socket at port 12000 for messages using the following protocol:
Attribute | flag | [math]\displaystyle{ v_x }[/math] if flag == 2, [math]\displaystyle{ a_x }[/math] if flag == 1 | [math]\displaystyle{ v_y }[/math] if flag == 2, [math]\displaystyle{ a_y }[/math] if flag == 1 | [math]\displaystyle{ v_{psi} }[/math] |
---|---|---|---|---|
Data type | byte | double | double | double |
Size (bytes) | 1 | 3 | 3 | 3 |
Unit | n/a | [math]\displaystyle{ meters/second }[/math] or [math]\displaystyle{ meters/second^2 }[/math] | [math]\displaystyle{ meters/second }[/math] or [math]\displaystyle{ meters/second^2 }[/math] | [math]\displaystyle{ radians/second }[/math] |
It then integrates them into speeds (only if flag == 1) and send the new target speed over serial to the omnibot-controller.
deployment
The need for a nice system to deploy code to the ground robots arose quickly as we started to use more ground robots simultaneously: they all had to run the same code that was frequently updated, but this was hard to maintain without proper tools. In practice there was usually one ground robot with up to date software, which was developed on the pi itself, and sometimes copy-pasted between two Putty windows to copy it to the next ground robot. A putty session had to be open for each ground robot to keep the remote control script running. Sometimes a powerbank would become disconnected during aggressive movements, resulting in the Raspberry Pi losing power and corrupting the SD-card. Flashing Arduino code was an even greater pain, as they had to be disconnected from the Pi, hooked up to a laptop and then flashed, one by one.
All the ground robots are now flashed with volatile write firmware. This means that all changes made to the filesystem are stored in volatile RAM instead of being written to disk, and so the ground robot will be reset to its initial state after every reboot. Because the SD-card is never written to, a power loss does not corrupt the SD-card. It also renders the bad practice of developing on the Pi itself impossible, as all files written will be gone after a reboot. Instead, development takes place on a laptop, and when the software is ready for testing it is deployed to all ground robot simultaneously.
A script was developed to make deployment to all ground robots easy. When run it executes the following sequence of commands:
- The local network is scanned for ground robots, the user is presented a list of ip address for these ground robots and can confirm deployment (the user can also choose a subset using a command line parameter).
- The remote_control.py script and all dependencies are copied to every ground robot.
- The ground robot disconnects from its current network, switches to the TUe-Guest network and logs in to the hotspot (this is needed because the default access point used to control the robots does not have internet access)..
- Required package such as python3 are downloaded and installed.
- The ground robot switches back to its original network.
- The ground robot flashes the Arduino with the latest firmware
- The ground robot starts the remote_control.py script, the actuators make a chirping sound to signal the user that the ground robot is ready.
The script is fully cross-platform, requiring only python3 and a few python libraries to work.
Hardware
Below are two pictures of the ground robots, the left one being ground robot 2 during it's re-wiring operation and the right picture being ground robot 3.
Introduction
This document describes the build process of ground robot 1, 2 and 3. It mostly considers things that were changed with respect to the first two ground robots. Hardware as well as software changes will be discussed. Pinout tables are provided in case hardware changes or fixes are ever required.
Attention: Always use LiPo alarms when using the ground robots to prevent battery failure!
Robot 1 and 2
General description
The ground robots have a triangular shape and use three omniwheels to move around. The wheels are driven by DC motors, which are controlled by LMD18200-based H-bridge motor controllers. The motor controllers are controlled by an Arduino Uno R3 microcontroller. The motorΓÇÖs motion is fed back to the Arduino using motor encoders. The whole system is powered by a Lithium Polymer (LiPo) battery.
Arduino pin specification
Ground robot 1 and 2 were built around the same time and have identical parts. Their original wiring has been re-done because it was of rather poor quality and required regular fixes. Below is the pin specification for robot 1 and 2. Note that it is different from the pinout configuration of robot 3, since it use different motor drivers which requires an additional pin.
Arduino pin | In/Out | Connects to | Comments |
---|---|---|---|
2 | Output | DIR motor 1
|
|
3 | Output | PWM motor 1
|
It is required to use a PWM-enabled Arduino pin |
4 | Output | DIR motor 2
|
|
5 | Output | PWM motor 2
|
|
6 | Output | PWM motor 3
|
|
7 | Output | DIR motor 3
|
|
11 | Output | Encoder MOSI
|
SPI interface |
12 | Input | Encoder MISO
|
SPI interface |
13 | Output | Encoder SCLK
|
SPI interface |
8 | Input | SS encoder 1
|
SS = Slave Select; used to select SPI device on bus
|
10 | Output | SS encoder 2
|
|
9 | Output | SS encoder 3
|
|
ICSP VCC
|
Output | Encoder VCC
|
5V |
ICSP GND
|
N/A | Encoder GND
|
|
5V
|
Input | Power | Provided by motor driver regulator (5V@1A) (3x) |
GND (2x)
|
N/A | Power | Common ground pins - connected to all devices |
VIN
|
Input | N/A | Do not use for now - might be bad for Arduino |
Hardware verification sketches
Several Arduino sketches were created which can be used to verify that all hardware subsystems work. These are included with this report. A summary of the available tests is provided below.
encoderTest12.ino
is a sketch which can be used to verify that all three encoders are working. Compile the sketch and upload it to the Arduino. Open the serial monitor and verify that the numbers change when the wheels are manually rotated.motorTest12.ino
runs all motors in a simple pattern (clockwise and anticlockwise) to verify wiring and rotation direction.speedTest12.ino
runs the motors such that the ground robot moves forward in a straight line. It can be used to assess the maximum speed of the ground robot while moving.
Robot 3
Changes
The build of robot 3 was completed on August 1, 2017. The following things are different with respect to robot 1 and 2:
- The DC gear motors are smaller than those on the first two robots. Consequently, PID gains might have to be re-tuned for optimal/uniform performance across all three robots. Additionally, performance might be different;
- The old LMD18200-based H-bridge motor controllers have been discontinued and have been replaced by a new board which is based on the VNH3SP30 motor driver IC. The latter is much better performance-wise and also has a smaller footprint. One downside is that the VNH3SP30 pin specification is different from the LMD18200 specification - more on this later;
- The encoder boards are different from the old ones, but the communication protocol is the same (SPI), thus no changes are required for this part;
- Motor wires are now routed through ferrite beads to reduce EMI;
- The motor drivers provide a 5V@1A protected & regulated power output, completely eliminating the need for a powerbank to power either the Raspberry Pi or Arduino. Special attention must be paid to wire polarity since the pin header 5V inputs on both the Arduino Uno and Raspberry Pi are not protected against reverse polarity.
- No cluttered wiring and also no electronics on the top plate of the robot, leaving enough room to mount a quadcopter (or similar)
Arduino pin specification
Below is the (new) pin specification for robot 3.
Arduino pin | In/Out | Connects to | Comments |
---|---|---|---|
2 | Output | inA motor 1
|
Motor 1 is closest to the Arduino chip |
3 | Output | PWM motor 1
|
It is required to use a PWM-enabled Arduino pin |
4 | Output | inB motor 1
|
|
5 | Output | inA motor 2
|
Motor 2 is closest to the encoder breakout chip stack |
6 | Output | PWM motor 2
|
|
7 | Output | inB motor 2
|
|
8 | Output | inA motor 3
|
|
9 | Output | PWM motor 3
|
|
10 | Output | inB motor 3
|
|
11 | Output | Encoder MOSI
|
SPI interface |
12 | Input | Encoder MISO
|
SPI interface |
13 | Output | Encoder SCLK
|
SPI interface |
A0 (Analog) | Input | SS encoder 1
|
SS = Slave Select; used to select SPI device on bus
|
A1 (Analog) | Output | SS encoder 2
|
|
A2 (Analog) | Output | SS encoder 3
|
|
ICSP VCC
|
Output | Encoder VCC
|
5V |
ICSP GND
|
N/A | Encoder GND
|
|
5V
|
Input | Power | Provided by motor driver regulator (5V@1A) (3x) |
GND (2x)
|
N/A | Power | Common ground pins - connected to all devices |
VIN
|
Input | N/A | Do not use for now - might be bad for Arduino |
Motor control
As mentioned before, the pins on the new motor drivers do not match the old ones. The old motor drivers used a dir
pin to control direction - pulling it LOW
or setting it HIGH
makes it rotate either clockwise or counterclockwise. The new driver uses two pins to reach the same goal:
- when
inA
andinB
have equal values (eitherLOW
orHIGH
), the motor stops; - when
inA
isHIGH
andinB
isLOW
, the motors rotate anticlockwise; - when this is reversed (
inA
=LOW
,inB
=HIGH
), the motors rotate in clockwise direction.
Motor speed is controlled by setting the PWM values PWM1
, PWM2
and PWM3
. The chosen value should be between 0 and 255, 255 being top speed.
Reading encoders
The encoders communicate to the Arduino device using an SPI communications bus. Each of the three encoder boards has its own SS
(Slave Select) wire which is used to select the specific device. A device is selected when the corresponding SS
pin is pulled LOW
(while the others are HIGH
).
The functions that are used in the robot Arduino software are the same as those provided by SuperDroidRobots, the boardΓÇÖs manufacturer. The important ones will be explained below:
initEncoders()
is used to initialize the encoders and configure the output data dimensions. This function is called in the Arduinosetup()
function.clearEncoderCount()
is used to clear the current encoder count and reset it to 0. This function is called in the Arduinosetup()
function.readEncoder(int encoder)
is used to read an encoder value at a specific point in time. It is used throughout the Arduinoloop()
.
One full wheel rotation equals 2000 encoder steps. Rotating the wheels clockwise results in an increase of the encoder count, whereas rotating the wheels anticlockwise results in a decrease of the encoder count.
Hardware verification sketches
Hardware verification sketches are also available for robot 3. They are very similar to the ones as provided for robot and 1 and 2, except for the fact that pinouts have changed and motors are controlled in a slightly different fashion. The sketches are named encoderTest3.ino
, motorTest3.ino
and speedTest3.ino
. Refer to Section 2.3 for accurate descriptions of these sketches.