Firefly Eindhoven - Ground Robots

From Control Systems Technology Group
Jump to navigation Jump to search


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.


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.


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 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.


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:

  1. 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).
  2. The script and all dependencies are copied to every ground robot.
  3. 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)..
  4. Required package such as python3 are downloaded and installed.
  5. The ground robot switches back to its original network.
  6. The ground robot flashes the Arduino with the latest firmware
  7. The ground robot starts the 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.


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.

Groundrobot12.jpg Groundrobot3.jpg


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 Uno pin specification for ground robot 1 and 2
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
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


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 Uno pin specification for ground 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
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 and inB have equal values (either LOW or HIGH), the motor stops;
  • when inA is HIGH and inB is LOW, 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 Arduino setup() function.
  • clearEncoderCount() is used to clear the current encoder count and reset it to 0. This function is called in the Arduino setup() function.
  • readEncoder(int encoder) is used to read an encoder value at a specific point in time. It is used throughout the Arduino loop().

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.