Engineering

Outreach

Resources

Enrichment

Green Engineers

Mechatronics Studio

Contact Us

Mechatronics Learning Studio

 

RC Robot

 

Shannon Lee, Robert Rayson, and Brandon Greenlaw, University of Ottawa

 

 

 

The goal of our ELG3336 project was to construct a robot that could be used to remotely survey an area at a relatively far distance. The vision for this project was that it would be used by police and security personnel to get a visual of areas far too dangerous for them to be present in; particularly in the event of a terrorist attack.

 

For this vision to become a reality a more compact and durable version of our prototype would be developed such that it would be better accustomed to a hostile environment. This project consists of two sub-sections: the user interface and the robot itself. The user interface consists of a physical remote controller, transmitter, LCD screen and a 7.2V battery pack (6 AA batteries) to provide power to said components.

 

The electronic components of the robot are an Arduino microcontroller, motor-shield, receiver, camera, four DC motors, two servo motors, LED lights, a 3000mAh battery pack to power the Arduino and an additional 7.2V battery pack to provide power to the remaining components. The structural components were designed in Solidworks where the baseplate and wheels are made of ⅛ inch MDF particle board and laser cut while the mounting components were 3D printed. When operating the robot the user has the option of driving the robot as well as pivoting and rotating the camera independently.

 

The footage that the camera captures is wirelessly transmitted to the LCD screen which the user can use to confidently control the robot at a far distance. Initial testing in the SITE building at the University of Ottawa resulted in the robot being able to travel approximately 100 meters from the user before losing signal. Note this building is largely made of concrete so expected range is to be much higher if used outside or in different buildings.

 

Materials

 

       Arduino Microcontroller

       Adafruit Motorshield

       2 Servo Motors

       4 DC Motors

       2- 7.2V Battery Packs (6 AA Batteries in series, handmade)

       1- 3000mAh Battery Pack

       1 Transmitter

       1 Receiver

       1 Camera

       1- 4” LCD Screen

       1 Remote Controller

       4 LED Lights

       Jumper Wires

       PLA Plastic (3D print material)

       ⅛” MDF Particle Board

       8- M4x24mm hex bolts with washers

       8- M3x30mm hex bolts with washers

       Superglue

       Makerbot Replicator 2 3D Printer

       Epilog Laser Cutter

       Soldering Iron

       Solidworks 2014

 

Design Process

 

Structural

 

Every design needs a strong foundation therefore the first step in our design process was to ensure that the base platform was both large and strong enough to support all components as well as making sure that the wheels were properly secured to the dc motors.

 

Designing the baseplate was simple. The only criteria was that it had to have a large enough area to support the components and that there were holes cut such that both the motor mounts and the camera column in the center could be secured. The schematic (140mm x 220mm) was created on solidworks and laser cut onto ⅛ inch MDF particle board. Reasoning for choosing MDF was that it was strong enough to support the components, while being cost effective and easy to cut.

 

Figure 1. Top view of baseplate model (Solidworks)

 

Designing the motor mounts was a bit more of a challenge as it had to secure the dc motor while also being fixed to the baseplate. As seen below in Figure 2, the solution was to dimensionalize the mount around the DC motor and then use nut-bolt pairs to fix the motor to the mount and to then fix the mount to the baseplate. Due to the complexity of the mount, all four were 3D printed using Makerbot technology.

 

Figure 2. Motor Mount (Solidworks)

 

For this robot we wanted the wheels to be large enough such that it could move past small obstacles with ease therefore we modelled a 90mm diameter wheel (seen in Figure 3, left) and lasercut 4 of them on ⅛ inch MDF particle board. However due to the large ratio between the wheel diameter and the bore diameter the wheels wobbled extensively. Therefore an additional attachment was designed (Figure 3, right) where the small end was press fitted to the motor axle while the wider end was glued to the wheel thus reducing said ratio and increasing stability in the wheels.

 

Figure 3. Wheel (left), Wheel-Axle interface (right)

 

Camera Orientation

 

The camera orientation is an important feature of the robot where a user is able to control the robot without physically seeing it. To ensure a good range of view for the user, the camera can rotate 360 degrees horizontal to the ground, and 180 degrees in the vertical plane with the use of two servo motors controlling each rotation.  With the use of these two functions, the robot has a full range of motion with zero blind spots. Every element comprising the camera mechanism is an original design and 3D printed.

 

The biggest challenge was to overcome the amount of friction between the axle that rotates the camera 360 degrees and the MDF robot base plate. Originally, two spur gears was used to function the 360 degrees range of view where one of the gears is attached to a servo motor. However, since the camera mechanism was supported on one end of the base plate, it produced a large moment around the end of the camera mechanism, causing a large friction force against the base plate and camera axel. This can be shown in Figure 3. To overcome this problem, the camera mechanism needed to be supported on the base plate from the middle of the camera mechanism for much less friction. Figure 4 shows the changes from the original camera model where a 3D printed bracket (black) was added to the middle of the camera mechanism. This reduced the amount of friction dramatically where it allowed the camera mechanism to run more smoothly and having the servo motor do less work. To reduce even more friction, the gears were moved more towards the middle of the mechanism. The gears have been changed from spur gears to bevel gears for less gear slippage and more space efficiency.

 

 

 Figure 3                                    Figure 4

 

Regarding the mechanism for the 180 degree range of view, shown in Figure 5, the entire linkages were 3D printed and are an original design. The linkage allows for the camera to look directly downwards and directly upwards. With the use of the 360 degree movement from the second servo motor, the robot is able to see every single degree around itself  without any blind spots (with the exception of underneath the base plate). This full range of camera orientation is particularly useful for single level exploratory tasks such as hazardous areas. The camera is able to function in completely dark or illuminated areas.

 

Figure 5

 

Power Distribution System

 

The power distribution system employed by our robot is somewhat complex. The arduino uno is powered by a 5v usb battery pack, while the rest of the robot is powered by a 7.2v battery pack which consists of 6 AA batteries wired in series. We decided to isolate the power source for the arduino from the rest of the robot to ensure that the arduino was provided a clean, consistent power signal. Any fluctuations in the power system caused by the motors, transmitter, or receiver could have detrimental effects on the operation of the arduino if the power sources were not isolated like this.

 

The two servo motors required a steady voltage of 5V, while the motor shield, video transmitter, and camera required voltage in the range of 7.2V. As such, a step down transformer was used to drop the battery voltage down to 5V, as seen in Figure *. The breadboard seen in the same Figure was also used to form several connections in parallel between the different 7.2V components and the battery pack. Finally, as seen in the same figure, the breadboard was also used to house the connections and resistor required to step down the 5v signal from the arduino to a reasonable voltage to drive the LED light.

 

The power distribution system at the base station is relatively simple in comparison. A 7.2V battery pack, consisting once again of 6 rechargeable AA batteries, is connected in parallel with the power inputs for the monitor and receiver.

 

DC Motor Control:

 

Four DC motors are used to move the robot relative to its surroundings. They can be seen in Figure 6.  These DC motors are driven through an Adafruit Motor Shield V3. This motor shield allows us to power the motors separately from the arduino, the arduino provides the instructions for the motor but the actual power is provided from the 7.2V battery pack. It also allows us selectively set the speeds of each motor as well as selectively driving them in forwards or reverse modes. Controlling the motors was accomplished through the adafruit motor control arduino library that we included in our code, for more details on this please see the “code” section near the end of this report.

 

Figure 6. The 4 DC Motors

 

Logic

 

An Arduino Uno R3 microcontroller acts as the “brains” of the robot. The code that it runs is relatively simple, it essentially just listens for commands, interprets them, and executes them. This process is run as a simple loop, repeating several times a second.

 

 When the remote is turned on, it transmits pulses along six different channels many times a second. Each channel corresponds to a certain input on the remote, for example channel 2 refers to the lefts stick’s vertical axis. Whenever these inputs are modified, the pulse width corresponding to the modified input will change as well. These pulse widths range from a value of 1000 to 2000.

 

The arduino code for the robot begins with the instruction to “listen” to the outputs of the radio receiver, seen in Figure 7. Interestingly enough, the receiver only outputs data along certain time intervals, it essentially operates at a unknown frequency. As such, it was critical to ensure that the arduino and receiver were operating in sync, that is to say that the arduino “listened” while the receiver output data. We synchronized the arduino and receiver mainly through trial and error, adding and modifying delays present in our code until the arduino consistently received instructions from the remote. There most certainly would have been superior ways to approach this issue, for example we could have likely employed a conditional loop such that the arduino would wait until it had received the data it required before continuing with the rest of the main loop.

 

Figure 7. The RC Receiver

 

Once the arduino has received all of the data that it requires, it is then necessary to translate this data into commands that the outputs can accept. For example, the 180 degree servo motor used in the camera orientation assembly requires an input value between 0 and 180 to determine what it’s position should be. As such, the arduino code translates the value on the relevant channel, which ranges from 1000 to 2000, to a corresponding value from 0 to 180 degrees.

 

Once all of the above commands have been completed, the arduino then repeats them in order. This process occurs with a relatively high frequency, resulting in no perceptible lag between an input change (moving one of the sticks) and the desired output (motor movement . led brightness change). The code that the arduino runs can be seen in the “code” section near the end of this document.

 

Video System

 

The video system for our project consists of four main parts. They are the camera, the video transmitter, the video receiver, and the monitor, The camera on the robot outputs an analogue video signal to the video transmitter (also attached to the robot), which transmits this signal at a frequency of approximately 2.4 GHz. This wireless signal is then received at the base station by the video receiver, which then outputs the analogue video signal over composite video wires to the monitor. As long as all elements of the system are operating nominally, the monitor will display whatever the robot’s camera is directed at.

 

Code

 

//Robot Firmware V4.1.2

//

//Written by Robert Rayson, with some inspiration drawn from several online resources,

//including "RC PulseIn Serial Read out" by Nick Poole, and the

//Adafruit Motor Shield V2 Documentation.

 

 

#include <Servo.h>

#include <Wire.h>

#include <Adafruit_MotorShield.h>

#include "utility/Adafruit_PWMServoDriver.h"

 

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

 

Adafruit_DCMotor *myMotor = AFMS.getMotor(3);

Adafruit_DCMotor *myMotor2 = AFMS.getMotor(4);

Adafruit_DCMotor *myMotor3 = AFMS.getMotor(1);

Adafruit_DCMotor *myMotor4 = AFMS.getMotor(2);

 

Servo myservo;

Servo myservo2;

 

int ch1;  //referes top right stick horizontal (997 L, 1485 m, 1968r

int ch2;  //refers to left stick vertical   

int ch3;  //refers to right stick vertical

int ch4;  //refers to VRA

int ch5;  //refer to left stick horizontal

int ch6;  //Refers to VRB (1000 to 2000)

 

int ch22; //values used to filter data stream to ignore 0 values (Do this for all used channels)

int ch11; //This feature is not required in this version of the code; legacy support

int ch33;

int ch44;

int ch55;

int ch66;

 

int t = 8; //10 also works, 7 does not

 

int ch111;  //legacy code

 

const int ledPin2 = 11;

const int ledPin = 13;

 

int servoangle;

int servoangle2;

int servoangle22;

 

int ch22motorvar;

int ch44motorvar;

int ch55motorvar;

 

int ch22deadspace;  //legacy

 

int ch44deadspace;  //legacy

 

int LEDBrightness;

 

int drivemode;  //Drivemode refers to the forward/backward (int = 0)

//or turn left/right state of the robot (int =1)

 

void setup() {

 

  pinMode(2, INPUT); // Sets up the input pins for RC control receiving

  pinMode(3, INPUT);

  pinMode(4, INPUT);

  pinMode(5, INPUT);

  pinMode(6, INPUT);

  pinMode(7, INPUT);

 

  myservo.attach(8);

  myservo2.attach(9);

  //myservo2.write(95);

 

  pinMode(13, OUTPUT);

 

  AFMS.begin();

  myMotor->setSpeed(0); //initializes the DC motors

  myMotor->run(FORWARD);

  myMotor->run(RELEASE);

 

  myMotor2->setSpeed(0);

  myMotor2->run(FORWARD);

  myMotor2->run(RELEASE);

 

  myMotor3->setSpeed(0);

  myMotor3->run(FORWARD);

  myMotor3->run(RELEASE);

 

  myMotor4->setSpeed(0);

  myMotor4->run(FORWARD);

  myMotor4->run(RELEASE);

 

  Serial.begin(115200); // Updated BAUD Rate, helps keep ardiuino and radio in sync.

 

}

void loop() {

 

    delay (t);    //delay is used to keep the arduino in sync with the transmitter

  ch1 = pulseIn(2, HIGH, 21000);//  Reads the puls width of this channel

    delay (t);

  ch2 = pulseIn(3, HIGH, 21000);

    delay (t);

  ch3 = pulseIn(4, HIGH, 21000);

    delay (t);

  ch4 = pulseIn(5, HIGH, 21000);

    delay (t);

  ch5 = pulseIn(6, HIGH, 21000);

    delay (t);

  ch6 = pulseIn(7, HIGH, 21000);

    delay (t);

 

 

  if (ch2 != 0) //legacy code to filter non zero values

   {

    ch22 = ch2;

   }

 

  if (ch1 != 0)

   {

    ch11 = ch1;

   } 

 

  if (ch3 != 0)

   {

    ch33 = ch3;

   }

 

  if (ch4 != 0)

   {

    ch44 = ch4;

   }

 

   if (ch5 != 0)

   {

    ch55 = ch5;

   }

  

   if (ch6 != 0)

   {

    ch66 = ch4;

   }

 

  Serial.print("           Channel 1:"); // Prints the value of each channel; for troubleshooting

  Serial.println(ch1);       

 

  Serial.print("         Channel 2:");

  Serial.println(ch2);

 

  Serial.print("       Channel 3:");

  Serial.println(ch3);

 

  Serial.print("     Channel 4:");

  Serial.println(ch4);

 

  Serial.print("   Channel 5:");

  Serial.println(ch5);

 

  Serial.print(" Channel 6:");

  Serial.println(ch6);

 

  Serial.println(ch11); //for troubleshooting

  Serial.println(ch22);

 

  servoangle = map(ch33, 990, 2000, 0, 180);  //basically, used to get a valid servoangle from the

                                                                                    //channel value.

  myservo.write(servoangle);

 

  servoangle2 = map(ch11, 1000, 2000, 50, 130);

 

  if (80 < servoangle2 && 100 > servoangle2) 

  {

    myservo2.write(95);

  }

  else

  {

    servoangle22=servoangle2;

    myservo2.write(servoangle22);

   

  }

 

 

  Serial.println(servoangle2);  //for troubleshooting, mostly

  Serial.println(servoangle22);

 

   if ( 1400 < ch22 && ch22 < 1600 )  //initiates a drivemode

   {

    drivemode = 1;

   }

  else

  {

    drivemode = 0;

  }

  if ( 1400 < ch22 && ch22 < 1600 && 1400 < ch55 && ch55 < 1600 )  //tells the motors to stop      //turning if the left stick is close to neutral (in either x or y planes)

  {

   ch22deadspace=1;

   myMotor->run(BACKWARD);

   myMotor->setSpeed (0);  

   myMotor2->run(BACKWARD);

   myMotor2->setSpeed (0);

   myMotor3->run(BACKWARD);

   myMotor3->setSpeed (0);

   myMotor4->run(BACKWARD);

   myMotor4->setSpeed (0);

  }

 

  if  ( 1400 >= ch55)

  {

    myMotor->run(FORWARD);

    myMotor2->run(BACKWARD);

    myMotor3->run(FORWARD);

    myMotor4->run(BACKWARD);

    ch55motorvar = map(ch55, 1000, 1400 , 225, 0);  

    myMotor->setSpeed (ch55motorvar);

    myMotor2->setSpeed(ch55motorvar);

    myMotor3->setSpeed(ch55motorvar);

    myMotor4->setSpeed(ch55motorvar);

  }

  else if ( 1600 <= ch55)   

  {

    myMotor->run(BACKWARD);

    myMotor2->run(FORWARD);

    myMotor3->run(BACKWARD);

    myMotor4->run(FORWARD);

    ch55motorvar = map(ch55, 1600, 2000, 0, 225);

    myMotor->setSpeed(ch55motorvar);

    myMotor2->setSpeed(ch55motorvar);

    myMotor3->setSpeed(ch55motorvar);

    myMotor4->setSpeed(ch55motorvar);

  }

 

  if  ( 1400 >= ch22) //try adding in && drivemode == 0)

  {

    myMotor->run(BACKWARD);

    myMotor2->run(BACKWARD);

    myMotor3->run(BACKWARD);

    myMotor4->run(BACKWARD);

    ch22motorvar = map(ch22, 1000, 1400 , 225, 0);  

    myMotor->setSpeed (ch22motorvar);

    myMotor2->setSpeed(ch22motorvar);

    myMotor3->setSpeed(ch22motorvar);

    myMotor4->setSpeed(ch22motorvar);

  }

  else if ( 1600 <= ch22)    

  {

    myMotor->run(FORWARD);

    myMotor2->run(FORWARD);

    myMotor3->run(FORWARD);

    myMotor4->run(FORWARD);

    ch22motorvar = map(ch22, 1600, 2000, 0, 225);

    myMotor->setSpeed(ch22motorvar);

    myMotor2->setSpeed(ch22motorvar);

    myMotor3->setSpeed(ch22motorvar);

    myMotor4->setSpeed(ch22motorvar);

  }

 

 

  if (ch22 > 1550)  //lights up the on board led on arduino for diagnostic purposes

    {

      digitalWrite(ledPin, HIGH);

    }

  else //if ((ch2 <= 1500) && (ch2 != 0))

    {

      digitalWrite(ledPin, LOW);

    }

 

  LEDBrightness = map(ch44, 900, 2000, 0, 255);  //allows us to control a LED from the remote

 

  analogWrite(ledPin2, LEDBrightness);

  Serial.println(LEDBrightness);

 

  delay(20);  //This delay helps keep the rc transmission and arduino in sync, as well as ensuring //that the servos have time to move like they have to.

 

}