RC Robot Tank
The RC Robot Tank is an Arduino remote controlled robot tank made from the Tamiya Track and Wheel, Tamiya Universal Plate, and Tamiya Double Gearbox. By using buttons on a PS2 Controller, the robot will be able to move forward, backwards, or turn left or right. After some modifications, it will become an autonomous robot and will be able to detect obstacles and avoid them.
Engineer
Timothy H
Area of Interest
Electrical Engineering
School
Silver Creek High School
Grade
Incoming Sophomore
Bill of Materials
Build Plan
Reflection
Presentation
Working Demo
When I first started BlueStamp, I had very little experience in engineering and coming here has changed my view of engineering. I have become more independent and knowledgeable throughout the program. When I first saw BlueStamp, I thought it was just another stereotypical class of lectures and teachers constantly droning. However, that was never the case. I had never been to a program where I was independent and learning on my own. By going through this, I was able to get a glimpse of what engineering truly is. After these 6 weeks, I have faced numerous problems and I had to solve each and every one of them. I had to diagnose the problems myself and fix them myself. One of my main problems was that the PS2 receiver was connecting to my controller intermittently. I had to troubleshoot it constantly, but eventually, I decided to remove the PS2 controller and receiver. I coded for the ultrasonic sensors and made my robot tank fully autonomous. After changing my motor shield once, gearboxes twice, DC motors three times, and PS2 receivers four times, I was finally able to overcome all those hardships. This taught me more about perseverance. After this 6 week engineering hands on program, I am more inspired to pursue a career in electrical engineering in the future.
Modification #1: Ultrasonic Sensors
Ultrasonic Sensors
Ultrasonic sensors measure the distance using ultrasonic waves. The sensors emit ultrasonic waves and then receive it. This allows them to detect whether there is an obstacle in front of it or not. In the case of my tank, when it senses an obstacle 30 cm away, it will use the two ultrasonic sensors on the sides to determine whether to turn left or right, depending on the distance on the left and right sides.
Autonomous Robot Tank
Autonomous Guiding
Knowing this, I began to write my code to make the tank autonomous. I had to add a 50 second delay so my ultrasonic sensors wouldn’t interfere with each other. After this, I cut four small pieces of wood to place my ultrasonic sensors on. I superglued the wood pieces together and hot glued the ultrasonic sensors onto it. I then attached wires from the battery and the motor shield to a button, so I wouldn’t have to constantly remove and attach the battery. I hot glued the button on top of the wood, and it can now turn on and off the battery. Some problems I faced was that sometimes, the ultrasonic sensors were getting a distance of 0 on the serial monitor. I secured the ultrasonic sensors to the wood, which allowed the ultrasonic sensors to not interfere with one another. For my next modification, I want to make my robot able to switch between autonomous and the PS2 controller.
#include <AFMotor.h> AF_DCMotor motor1(2); AF_DCMotor motor2(3); const int trigPin = 9; const int echoPin = 10; const int trigPin1 = 1; const int echoPin1 = 2; const int trigPin2 = 8; const int echoPin2 = 13; // defines variables long duration; int distance; long duration1; int distance1; long duration2; int distance2; long duration3; int distance3; void setup() { pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin, INPUT); // Sets the echoPin as an Input /*pinMode(trigPin1, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin1, INPUT); // Sets the echoPin as an Input pinMode(trigPin2, OUTPUT); // Sets the trigPin as an Output pinMode(echoPin2, INPUT);// Sets the echoPin as an Input */ Serial.begin(9600); // Starts the serial communication motor1.setSpeed(255); motor2.setSpeed(255); motor1.run(BACKWARD); motor2.run(BACKWARD); } void loop() { // Clears the trigPin digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn(echoPin, HIGH); // Calculating the distance distance= duration*0.034/2; // Prints the distance on the Serial Monitor Serial.print("Distance: "); Serial.println(distance); if(distance <30 && distance >1 ){ motor1.run(RELEASE); motor2.run(RELEASE); // Clears the trigPin digitalWrite(trigPin, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin1, HIGH); delayMicroseconds(10); digitalWrite(trigPin1, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration1 = pulseIn(echoPin1, HIGH); // Calculating the distance distance1= duration1*0.034/2; // Prints the distance on the Serial Monitor Serial.print("Distance1: "); Serial.println(distance1); delay(50); // Clears the trigPin digitalWrite(trigPin2, LOW); delayMicroseconds(2); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin2, HIGH); delayMicroseconds(10); digitalWrite(trigPin2, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration2 = pulseIn(echoPin2, HIGH); // Calculating the distance distance2= duration2*0.034/2; // Prints the distance on the Serial Monitor Serial.print("Distance2: "); Serial.println(distance2); if(distance2 > distance1){ motor1.run(FORWARD); motor2.run(BACKWARD); delay(500); } if(distance1 > distance2){ motor1.run(BACKWARD); motor2.run(FORWARD); delay(500); } } else{ motor1.run(BACKWARD); motor2.run(BACKWARD); } }
Autonomous Robot Tank
Final Milestone
H-Bridge
I ran into another problem which was that my DC motors weren’t strong enough to move the wheels through the gearbox. So, I changed the gearbox twice and changed my DC motors three times. Even after this, my robot tank couldn’t turn. So, I decided to stack an H-bridge on top of another H-bridge. Because of the extra H-bridge, my robot tank was able to take in more voltage and was able to turn. An H-bridge is an electronic circuit that controls the flow of current to a load. The RC robot tank finally works!
PS2 Receiver
If your PS2 receiver is not connecting with the PS2 controller even though all your connections are correct and your controller’s batteries are functional, then there is probably some interference with other PS2 controllers. Also, check with another receiver to see if the receiver is the problem. I had to change my receivers two or three times until it started working.
Controller not connecting
At first, the controller would not connect with the receiver, leading the serial monitor in the Elegoo to display “Dualshock controller not found!” After looking through the code, I realized that the way the pins were set up in the code was different from the schematics. I changed the code and the controller began to display the buttons pressed on the serial monitor.
#include <PS2X_lib.h> //for v1.6 PS2X ps2x; // create PS2 Controller Class //right now, the library does NOT support hot pluggable controllers, meaning //you must always either restart your Arduino after you conect the controller, //or call config_gamepad(pins) again after connecting the controller. int error = 0; byte type = 0; byte vibrate = 0; void setup(){ Serial.begin(57600); //CHANGES for v1.6 HERE!!! **************PAY ATTENTION************* error = ps2x.config_gamepad(13,11,10,12, true, true); //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error if(error == 0){ Serial.println("Found Controller, configured successful"); Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;"); Serial.println("holding L1 or R1 will print out the analog stick values."); Serial.println("Go to www.billporter.info for updates and to report bugs."); } else if(error == 1) Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips"); else if(error == 2) Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips"); else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it. "); //Serial.print(ps2x.Analog(1), HEX); type = ps2x.readType(); switch(type) { case 0: Serial.println("Unknown Controller type"); break; case 1: Serial.println("DualShock Controller Found"); break; case 2: Serial.println("GuitarHero Controller Found"); break; } } void loop(){ /* You must Read Gamepad to get new values Read GamePad and set vibration values ps2x.read_gamepad(small motor on/off, larger motor strenght from 0-255) if you don't enable the rumble, use ps2x.read_gamepad(); with no values you should call this at least once a second */ if(error == 1) //skip loop if no controller found return; if(type == 2){ //Guitar Hero Controller ps2x.read_gamepad(); //read controller if(ps2x.ButtonPressed(GREEN_FRET)) Serial.println("Green Fret Pressed"); if(ps2x.ButtonPressed(RED_FRET)) Serial.println("Red Fret Pressed"); if(ps2x.ButtonPressed(YELLOW_FRET)) Serial.println("Yellow Fret Pressed"); if(ps2x.ButtonPressed(BLUE_FRET)) Serial.println("Blue Fret Pressed"); if(ps2x.ButtonPressed(ORANGE_FRET)) Serial.println("Orange Fret Pressed"); if(ps2x.ButtonPressed(STAR_POWER)) Serial.println("Star Power Command"); if(ps2x.Button(UP_STRUM)) //will be TRUE as long as button is pressed Serial.println("Up Strum"); if(ps2x.Button(DOWN_STRUM)) Serial.println("DOWN Strum"); if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed Serial.println("Start is being held"); if(ps2x.Button(PSB_SELECT)) Serial.println("Select is being held"); if(ps2x.Button(ORANGE_FRET)) // print stick value IF TRUE { Serial.print("Wammy Bar Position:"); Serial.println(ps2x.Analog(WHAMMY_BAR), DEC); } } else { //DualShock Controller ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed if(ps2x.Button(PSB_START)) //will be TRUE as long as button is pressed Serial.println("Start is being held"); if(ps2x.Button(PSB_SELECT)) Serial.println("Select is being held"); if(ps2x.Button(PSB_PAD_UP)) { //will be TRUE as long as button is pressed Serial.print("Up held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC); } if(ps2x.Button(PSB_PAD_RIGHT)){ Serial.print("Right held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC); } if(ps2x.Button(PSB_PAD_LEFT)){ Serial.print("LEFT held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC); } if(ps2x.Button(PSB_PAD_DOWN)){ Serial.print("DOWN held this hard: "); Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC); } vibrate = ps2x.Analog(PSAB_BLUE); //this will set the large motor vibrate speed based on //how hard you press the blue (X) button if (ps2x.NewButtonState()) //will be TRUE if any button changes state (on to off, or off to on) { if(ps2x.Button(PSB_L3)) Serial.println("L3 pressed"); if(ps2x.Button(PSB_R3)) Serial.println("R3 pressed"); if(ps2x.Button(PSB_L2)) Serial.println("L2 pressed"); if(ps2x.Button(PSB_R2)) Serial.println("R2 pressed"); if(ps2x.Button(PSB_GREEN)) Serial.println("Triangle pressed"); } if(ps2x.ButtonPressed(PSB_RED)) //will be TRUE if button was JUST pressed Serial.println("Circle just pressed"); if(ps2x.ButtonReleased(PSB_PINK)) //will be TRUE if button was JUST released Serial.println("Square just released"); if(ps2x.NewButtonState(PSB_BLUE)) //will be TRUE if button was JUST pressed OR released Serial.println("X just changed"); if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) // print stick values if either is TRUE { Serial.print("Stick Values:"); Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX Serial.print(","); Serial.print(ps2x.Analog(PSS_LX), DEC); Serial.print(","); Serial.print(ps2x.Analog(PSS_RY), DEC); Serial.print(","); Serial.println(ps2x.Analog(PSS_RX), DEC); } } delay(50); }
#include <PS2X_lib.h> //for v1.6 #include <AFMotor.h> AF_DCMotor motor2(3); AF_DCMotor motor1(2); #define PS2_DAT 12 #define PS2_CMD 11 #define PS2_SEL 10 #define PS2_CLK 13 #define pressures false #define rumble true PS2X ps2x; int error = 0; byte type = 0; byte vibrate = 0; void setup() { // put your setup code here, to run once: Serial.begin(57600); delay(1); //added delay to give wireless ps2 module some time to startup, before configuring it //CHANGES for v1.6 HERE!!! **************PAY ATTENTION************* //setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble); if (error == 0) { Serial.print("Found Controller, configured successful "); Serial.print("pressures = "); if (pressures) Serial.println("true "); else Serial.println("false"); Serial.print("rumble = "); if (rumble) Serial.println("true)"); else Serial.println("false"); Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;"); Serial.println("holding L1 or R1 will print out the analog stick values."); Serial.println("Note: Go to www.billporter.info for updates and to report bugs."); } else if (error == 1) Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips"); else if (error == 2) Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips"); else if (error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it. "); // Serial.print(ps2x.Analog(1), HEX); type = ps2x.readType(); switch (type) { case 0: Serial.print("Unknown Controller type found "); break; case 1: Serial.print("DualShock Controller found "); break; case 2: Serial.print("GuitarHero Controller found "); break; case 3: Serial.print("Wireless Sony DualShock Controller found "); break; } motor1.setSpeed(255); motor2.setSpeed(255); } void loop() { // put your main code here, to run repeatedly: if (error == 1) //skip loop if no controller found return; if (type == 1) { ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'v if (ps2x.ButtonPressed(PSB_TRIANGLE)) { motor1.run(FORWARD); motor2.run(FORWARD); } if (ps2x.ButtonReleased(PSB_TRIANGLE)) { motor1.run(RELEASE); motor2.run(RELEASE); } if (ps2x.ButtonPressed(PSB_CROSS)) { motor1.run(BACKWARD); motor2.run(BACKWARD); } if (ps2x.ButtonReleased(PSB_CROSS)) { motor1.run(RELEASE); motor2.run(RELEASE); } if (ps2x.Button(PSB_CIRCLE)) { //Serial.print("Up held this hard: "); motor2.run(FORWARD); motor1.run(BACKWARD); } if (ps2x.ButtonReleased(PSB_CIRCLE)) { motor1.run(RELEASE); motor2.run(RELEASE); } if (ps2x.Button(PSB_SQUARE)) { Serial.print("Up held this hard: "); motor2.run(BACKWARD); motor1.run(FORWARD); } if (ps2x.ButtonReleased(PSB_SQUARE)) { motor1.run(RELEASE); motor2.run(RELEASE); } //if(ps2x.Button(PSB_PAD_RIGHT)) { //motor2.run(BACKWARD); // motor1.run(FORWARD); // } // if(ps2x.Button(PSB_PAD_DOWN)) { // motor2.run(BACKWARD); // motor1.run(BACKWARD); // } // if(ps2x.Button(PSB_PAD_LEFT)) { // motor2.run(FORWARD); //motor1.run(BACKWARD); // } if (ps2x.Button(PSB_R1)) { motor1.run(FORWARD); } if (ps2x.ButtonReleased(PSB_R1)) { motor1.run(RELEASE); } if (ps2x.Button(PSB_L1)) { motor2.run(FORWARD); } if (ps2x.ButtonReleased(PSB_L1)) { motor2.run(RELEASE); } if (ps2x.Button(PSB_R2)) { motor1.run(BACKWARD); } if (ps2x.ButtonReleased(PSB_R2)) { motor1.run(RELEASE); } if (ps2x.Button(PSB_L2)) { motor2.run(BACKWARD); } if (ps2x.ButtonReleased(PSB_L2)) { motor2.run(RELEASE); } } delay(1); }
Connecting PS2 Receiver to Motor Shield
To connect the PS2 receiver to the Adafruit Motor Shield, I used female to female jumper wires to connect the PS2 receiver to pins 13 (clock), 12 (data), 11 (command), 10 (attention), GND, and 3.3V on my Elegoo Mega. The color of the wires you use don’t matter, but the place where you put them does. Follow the schematic in front of this box. You don’t need to use the vibration, unknown, and acknowledge wires from the diagram by Bill Porter. Using this website, I was able to find out where the wires were supposed to go to connect the PS2 receiver to my motor shield. To connect the receiver to my motor shield, I had to attach jumper wires from the receiver to the pins. However, the pins I needed on the Elegoo were covered by my motor shield. This led me to soldering the headers to the pins sideways (as shown below) I needed onto the motor shield. By using a multimeter, I was able to see if any of the pins were connected to each other. After that I saw that two of the pins’ tin was connected to each other. I attempted to melt the tin for a significant amount of time, but after checking with an instructor, I discovered the solder was dull. I then used the copper wire to desolder the tin connecting the two connections together. I connected the jumper wires to the receiver and to my motor shield once again. I ran the PS2 library code with the PS2 controller to see if the receiver was working. I checked the serial monitor to check if the PS2 controller was connecting to the receiver, and it was. Whenever I pressed buttons such as triangle, circle, square, and triangle, it would show that they were being pressed on the serial monitor. This meant that I successfully connected the PS2 receiver to the motor shield!
My first modification would be to add ultrasonic sensors to my tank and make it autonomous.
First Milestone
Core Materials
Tamiya Track and Wheel Set
Tamiya Double Gearbox
Tamiya Universal Plate
Elegoo Mega 2560 R3
Adafruit Motor Shield for Arduino
My first milestone is to use the Elegoo Mega 2560 R3 and the L293D motor shield to make both of the motors in the gearbox move, allowing the chassis to move forwards and backwards. First, I assembled the Tamiya Double Gearbox which has the two DC motors for the robot tank and the chassis of the robot tank. The chassis consists of ten wheels which move the track, a Tamiya universal plate which holds everything together, and the twin-motor gearbox which allows the chassis to move. The two wheels in the back are connected to the gearbox. When the back wheels move, it moves the track, enabling the other wheels to move as well.
// DC Motors Test #include <AFMotor.h> AF_DCMotor motor1(3); // Left motor connected to port 3 AF_DCMotor motor2(2); // Right motor connected to port 4 void setup() { Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("Motor test!"); // turn on motor motor1.setSpeed(200); motor2.setSpeed(200); motor1.run(RELEASE); motor2.run(RELEASE); } void loop() { uint8_t i; Serial.print("tick"); motor1.run(FORWARD); motor2.run(FORWARD); for (i = 0; i < 255; i++) { motor1.setSpeed(i); motor2.setSpeed(i); delay(10); } for (i = 255; i != 0; i--) { motor1.setSpeed(i); motor2.setSpeed(i); delay(10); } Serial.print("tock"); motor1.run(BACKWARD); motor2.run(BACKWARD); for (i = 0; i < 255; i++) { motor1.setSpeed(i); motor2.setSpeed(i); delay(10); } for (i = 255; i != 0; i--) { motor1.setSpeed(i); motor2.setSpeed(i); delay(10); } Serial.print("tech"); motor1.run(RELEASE); motor2.run(RELEASE); delay(1000); }
Next, I connected the DC motors in the gearbox to my Elegoo and motor shield by soldering two red and two black wires. The Elegoo has a microcontroller which allows me to program it to do a certain function, which is to move the DC motors. I programmed one of the DC motors to test both of them to see if they worked. After that, I programmed both of the DC motors to run at the same time. This part was particularly challenging as I don’t have a lot of experience in programming or using the Arduino. However, after watching multiple videos and reading about the Arduino, I was able to program the DC motors. To test the DC motors, I connected a 6V Nickel-Metal Hydride Battery using a red wire and a black wire (positive and negative). This allowed my chassis to move forward and backward.
// Adafruit Motor shield library // copyright Adafruit Industries LLC, 2009 // this code is public domain, enjoy! #include <AFMotor.h> AF_DCMotor motor(3); void setup() { Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("Motor test!"); // turn on motor motor.setSpeed(200); motor.run(RELEASE); } void loop() { uint8_t i; Serial.print("tick"); motor.run(FORWARD); for (i=0; i<255; i++) { motor.setSpeed(i); delay(10); } for (i=255; i!=0; i--) { motor.setSpeed(i); delay(10); } Serial.print("tock"); motor.run(BACKWARD); for (i=0; i<255; i++) { motor.setSpeed(i); delay(10); } for (i=255; i!=0; i--) { motor.setSpeed(i); delay(10); } Serial.print("tech"); motor.run(RELEASE); delay(1000); }
Robot Tank
My next milestone would be to use a PS2 controller to control the tank’s movements.
Starter Project: Minty Boost
Boost Converter
The boost converter is a “direct current to direct current” power converter that increases the voltage from its input to its output. It increases the 3 V in the two “AA” batteries to 5V, which is enough to charge an iPhone or iPod.
Schottky Diode
The Schottky Diode is a semiconductor diode that has a low forward voltage drop and a very fast switching action, which forces the current to only pass through one direction. The current is then only able to go from the two “AA” batteries to the device. This stops the device from charging the batteries.
Read More
Minty Boost
There was a lot of soldering involved in this project, so not messing up on soldering is very crucial. Throughout the project, I learned what a lot of the parts did within the PCB and how to solder correctly. At the beginning, I was just placing the solder onto the soldering iron which kept melting the tin onto the iron, which doesn’t solder the parts to the PCB. Eventually, I learned to place the solder on top of the PCB and under the soldering iron and it led me to finish soldering all the parts to the PCB. However, when I was soldering one of the resistors on, some of the tin got connected to another part. This led me to do a process called desoldering. I used the soldering iron on a copper wick to melt the tin onto it. I successfully desoldered the excess tin from the PCB! I then connected my charger to my phone and it was able to charge my iPhone. After completing this starter project, I learned the functions and uses of a lot of the parts, how to solder and desolder something to or from a PCB, and how charging a phone works.