Hard- and software reference guide of the Rover-5 robot for the Mechatronics laboratory 2021.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
M. Stokroos 58acd24c08 update readme 1 month ago
Arduino add initializer for loopTimer 1 month ago
datasheets update readme 2 months ago
extra release 2021 2 months ago
figures update readme - encoder 1 month ago
LICENSE Initial commit 3 months ago
README.md update readme 1 month ago


Mechatronics 2021

Hard- and software reference guide of the Rover-5 robot for the laboratory course Mechatronics 2021

The robot used for the mechatronics laboratory is based on the Arduino MEGA2560 microcontroller board. Arduino is a standard prototyping platform for hobbyists, makers and developers. A wealth of information about the Arduino platform as the software reference guide and the programming IDE can be found here: https://www.arduino.cc
Arduino MEGA2560

The robot controller Printed Circuit Board (PCB) carries the interface circuits to connect the encoders, sensors and motors to the Arduino. The Arduino is plugged onto the controller board and is programmed via the USB interface.

When working in the Arduino IDE under Windows, select from the menu Tools :

  • Board: Arduino Mega or Mega 2560

  • Processor: ATmega2560 (Mega 2560)

  • Port: COMx , where x is the assigned serial communications port. Check the port number from the Windows device manager.

Robot Hardware Description


The Rover-5 robot chassis with four motors and encoders, is described in a separate document included in this git, see: Rover-5 Introduction.pdf (1).
The Rover-5 chassis used with the laboratory has four wheels instead of two track wheels. The front and rear motors from the left and right side are electrically connected in parallel. Only one wheel encoder from the left side and one from the right side are used for velocity feedback.


The Rover-5 has four permanent magnet DC-motors of type RP6 from TECO ELECTRIC CO LTD. They are nominal rated at 7.2V DC and 7.5V DC max. The no-load current is below 160mA and the no-load speed 8804±10% RPM. For the datasheet of the motors, see: RP6 motor TFK280SC-21138-45.pdf


There is a gearbox inbetween the DC-motor and each (track-)wheel to bring the nominal speed of the Rover to about 1km/h.

Gearbox Transmission

The number of teeth per gear are:

A = 12
B = 50
C = 12
D = 60
E = 12
F = 50

The gears ratio A-to-F is 86.8 : 1.

Wheel Encoders

The quadrature encoder is attached to gear B. The encoder is made from a disc shaped magnet glued to gear wheel B, that rotates very close above the surface of two Hall-sensors mounted on a small PCB.

Hall-sensors Disc shaped magnet Field map

The disc shaped magnet has 8 poles and will generate eight state-changes per revolution to be detected by the Hall-sensor(s). The Hall-effect sensor S1 is displaced over a distance of half of the magnetic pole length as can be seen from the most left picture above. With two Hall-sensors S1 and S2, there are two output signals A+B (sometimes called the in-phase and quadrature component).

If the signal from S2 leads the signal from S1, the magnet is rotating clockwise (CW) and when the signal from S1 leads the signal from S2, the magnet rotates counter clockwise (CCW). When using both signals from S1 and S2, all the information about the (relative) position, direction and speed is available.

Quadrature encoder signals

The Battery

There is fire and explosion risk involved when working with LiPo (Lithium Polymer) batteries. Take notice of the safety instructions before use! LiPo-batteries should be charged, attached or disconnected from the robot by the supervisors only!

A single unit LiPo cell has a nominal output voltage of 3.7V. The robot is powered from a 3-cell battery pack with a nominal output voltage of 11.1V. The battery should not be drained down to below 3V/cell. If this happens, it will irreversible damage the battery! When discharging, the battery voltage should be monitored continuously and shut off the load automatically at the moment the battery needs to be recharged.

Datasheet of the battery: TOPPFUEL_LIPO_AKKU_25C_ECO_X_500_de_en_it.pdf

Small Robot Controller board connections

The controller board carries the Arduino board and facilitates the interfaces with the sensors and the actuators of the robot. The following connections are relevant:

Controller board

A. motor outputs left+right
B. encoder1 (left) input
C. encoder2 (right) input
D. ON switch
E. OFF switch
F. pluggable battery connector
G. battery balancing connector
H. USB programming plug
I. Arduino UNO compatible shield connectors (×4)
J. sonar range sensor connector

Power on and off

Turn the robot on by pressing and holding the ON button until a beep is heard.
Turn the robot instantaneously off by pressing the OFF button.

The Arduino Pin Assignment

The table below shows the Arduino pin assignments to connect with the Robot Controller Board. These pins can not be used to connect to other things.

AI = analog input
DI = digital input
DO = digital output
PWM = Pulse Width Modulation output
INTn = Interrupt input

A8 AI INPUT Battery Vcell1 scaled
A9 AI INPUT Battery Vcell1+Vcell2 scaled
A10 AI INPUT Battery Vcell1+Vcell2+Vcell3 scaled
D5 DO OUTPUT motor enable outputs 1+2 (left motor)
D6 DO OUTPUT motor enable outputs 3+4 (right motor)
D9 PWM OUTPUT PWM-A, motor left
D10 PWM OUTPUT PWM-B, motor left
D11 PWM OUTPUT PWM-C, motor right
D12 PWM OUTPUT PWM-D, motor right
D18 INT3 INPUT encoder1 (left)
D19 INT2 INPUT encoder2 (right)
D22 DI INPUT encoder channel-A (right)
D23 DI INPUT encoder channel-B (right)
D24 DI INPUT encoder channel-A (left)
D25 DI INPUT encoder channel-B (left)

Software Description

The Arduino Sketch Program Structure

A program for Arduino, named Sketch, is written in the C++ program language and features two main program functions namely setup() and loop().

setup() runs only once after startup and is meant to setup and initialize things. De code placed between the braces of the function loop() is be repeated indefinitely. Code inside loop() should not be blocking for example when using the Delay() function or in situations where the program is waiting for state changes depending on external events.

void setup() {
  // put your setup code here, to run once:


void loop() {
  // put your main code here, to run repeatedly:


The Startup_sketch

The start-up sketch to begin experimenting with the robot is located here in this git: Mechatronics_2021/Arduino/Startup_sketch/Startup_sketch.ino
Clone this repository and copy the directory+file to your local Arduino directory under your home/Arduino or My Documents\Arduino folder and edit from there or paste the code from the repository into a blank project.

Also copy the companion libraries from: Mechatronics_2021/Arduino/libraries/ to your local ..\Arduino\libraries directory.

The way how to use the software functions from the Rover5lib can be copied from other parts of the Startup_sketch and are self explanatory.

The Rover-5 library

A special Arduino library was created for the Rover-5 and it contains all pin definitions for the Robot together with some low level functions which can be called from the Arduino sketch.

To use the library, include:

#include <Rover5lib.h>

The library must be located in My Documents\Arduino\libraries

Main-loop Program Timing

For real-time control, the main program loop must be executed at a fixed loop rate. Here we use a simple mechanism (without using interrupts) to create a constant 20Hz loop rate. The code responsible for the loop timing is:

#define LOOP_TIME 50000 // loop time in us
unsigned long loopTimer;

void setup() {
  loopTimer = micros() + LOOP_TIME; //Set the loopTimer variable for the next loop-end time.

void loop() {

  // put your main code here, to run repeatedly @20Hz:

  // Wait for the remaining time in the loop and set the new loop-end time.
  while (loopTimer > micros()) {;}
  loopTimer += LOOP_TIME;

Take care that the total execution time in the loop stays within 50ms.
A mechanism to carry out tasks at a much lower rate then the loop rate, could be something like:

int loopCounter = 0;

if (loopCounter > 100) { 

  // do something here each 100*50ms
  loopCounter = 0; //reset the counter.

loopCounter++; //increment the counter


Interrupts are used to call task that have a high priority and that must be executed asynchronous from the main function loop. In the robot application, the following interrupts can occur:

  • when the encoder state changes. On each interrupt, caused by the the left or right wheel encoder, the position data is updated.
  • when the user presses the 'power-OFF' button, the program must respond immediately.
  • when the received echo from the sonar sensor arrives.

An interrupt can be attached to reserved input pins only (see table below) with the function attachInterrupt(). For the robot, all required interrupt functions are handled internally by the Rover-5 library. The user doesn't need to bother about interrupts.

Arduino Interrupt pins

Encoder Readout

The position units from the encoders will depend on the wheel diameter, encoder resolution and the gear ratio. The velocity reading also depends on the sampling interval. If desired, the units can be converted into SI-units.

Some relevant Rover-5 chassis parameters are:

  • Wheel base width = 0.245m (use 0.194 for track wheels).
  • Wheel radius = 32.5mm (use 32mm for track wheels).

The Encoder(s) generates 1000 pulses each 3 wheel revolutions.

  • 1rev/s = 1333.33 pps. At 20Hz sample rate this is 1333.33/20 = 66.67 pulses/sampling-interval.
  • 1rev/s = 2×PI×0.0325 = 0.2m/s.
  • 1m/s = 333.33 pulses/sampling-interval (at 20Hz)

The raw encoder data is read by:

  Rover.readEncoders(); //fetch the data
  position_left = Rover.encPos[0]; //get the data
  position_right = Rover.encPos[1];
  step_increment_left = Rover.encDeltaStep[0];
  step_increment_right = Rover.encDeltaStep[1];

PID Controllers

For the PID wheel velocity controllers an external PID library is used. See: PID-tutorial.

The Motor PWM-signals

The average motor voltage is set by Pulse Width Modulation PWM.
The amplitude of the pulse width signal is the same as the battery voltage. Because the Robot Controller Board uses a H-bridge switch configuration, it is possible to reverse the polarity of motor drive voltage to switch between forward, reverse operation.
In software the PWM can be steered between -100 to +100. In this case this does not mean from -100% to 100% (-12V to 12V), but from -100/127 ×12V = -9.45V to 100/128 × 12V = 9.38V. The maximum (average) output voltage is clamped between absolute upper limits to protect the motors.

Internal Protections

The motors will switch off immediately if no battery is connected or when the battery is almost depleted. This protects withdrawing too much current from the USB port of the computer when the motors are running.


Infrared Line Tracking Sensor(s)

There are two types of InfraRed (IR) line follow sensors in circulation. The blue IR-array from Waveshare has five opto-reflective sensors and the red sensor board has eight opto-reflective sensors, of wich the middle six IR's are connected to the Arduino only.

Waveshare Red IR-line array
Tracking-Sensor A Tracking-Sensor B

These sensors work over a certain distance range, depending on the infrared reflective properties of the surface they illuminate.

Each IR sensor outputs a voltage which varies between 0 and 5V. The voltage is read by the Arduino analog input pins. The pin mapping is as follows:

Arduino analog input pin Waveshare pin 'Red sensor array' pin*
A0 alias IR1 IR1 D2
A1 alias IR2 IR2 D3
A2 alias IR3 IR3 D4
A3 alias IR4 IR4 D5
A4 alias IR5 IR5 D6
A5 alias IR6 nc D7

nc = not connected

(*) outer most IR sensors D1 and D8 are not used.

Analog voltages measured with the Arduino are digitized by the 10-bit internal ADC of the micro-controller. 10 bit means 2^10 = 1024 discrete steps. The 0 to 5V input voltage range is mapped on a 0 to 1023 integer value range and the measuring resolution is: 5V/1024 = 4.88mV. A single ADC channel can be read by the instruction:

int value;

value = analogRead(IR1);

A large variance in the sensitivity of the IR sensors can occur. To use the line follow sensor successfully, the IR output data must be calibrated and normalized first.

A hint on how to solve the line follow problem can be found here:



In the example from Mathworks, sensors are used with a digital or binary (0 or 1) output. In our case, for using sensors with a continuous output signal, one can:

  1. adapt the weight function to be used with the discretized signals from the ADC, or
  2. first, convert the discretized signals from the ADC to binary signals by applying a threshold function.

Some remarks:

In the weighted average function given by Waveshare, the first sensor's weight factor is 0. This is not a nice implementation, because the contribution of first sensor is omitted completely.

The sensor symmetry around the central axis is different between the two sensor types.

The response to black is inverted between the two sensor types.

Ultrasonic Ranging Module HCSR04

Use this sensor for example to avoid obstacles or for anti collision detection.
The Ultrasonic ranging module HCSR04 provides 2cm - 400cm non-contact measurement function, the ranging accuracy can reach to 3mm.


The round device at the left side works as the transmitter and sends out a burst of ultrasonic acoustic waves at a frequency of 40kHz. The round device at the right side is the microphone that detects the echo's reflecting of from the surface of objects in the vicinity.

A 10μs trigger pulse to start the transmission of a sonar acoustic burst is initiated with:


When the HCSR04 receives the first strong echo, it will trigger the interrupt service routine. In this routine, the final ping time (turn-around time in μs) is calculated. The last received ping time is fetched and read from the main loop with:


The ping time from the last received sonar echo is available for use in the main loop. The distance to an object can be calculated from the ping time.