Car Convoy
This is an instructable on how to make a Car Convoy that can be controlled by a phone.
Materials:
- 2 Arduino's
- Computer
- Cardboard
- Hot Glue Gun
- Blade and Ruler
- 4 360 Degree Servos
- 4 Extra Wheels
- 2 Red LED's
- 2 Green LED's
- 2 Yellow LED's
- 6 220 Ω Resistors
- 1 Ultrasonic Sensor
- 2 Portable Chargers
- 2 A-B Cable
- String
- Wires
Create the Box
Use the blade and ruler to cut the cardboard into a box that has a flap that can open at the top.The flap should be able to close fully and make a completely closed box. The structure should be glued securely and should be strong.
Cut Holes for Servos
Use a blade to cut out two holes that will fit the two servos. The holes for the servos should be near the back of the box.
Attach Servos
Insert the two servos into the holes cut in the previous step. Use a hot glue gun to glue the servos in its place, so it cannot be moved.
Attach 2 Front Wheels
Poke two Holes through the Cardboard that your front wheels can go through. Be sure to measure the Holes to ensure that the height of both wheels is equal. Put the axle of both wheels through the cardboard. Then use a hot glue gun to ensure that it does not move.
Create Battery Holder
To Create a slot for the battery pack you must first measure the length of your box. Cut two slits of cardboard that are of equal length and can fit in your box vertically. Make the space between the cardboard slits the width of the battery pack. Then you can use the hot glue gun to glue the slits permanently to the box.
Insert Battery
Place your battery inside along with the power cord. The power cord must be placed with the battery to prevent spacing problems while creating the rest of the car.
Create Holder for Arduino and Circuit Board
Now we must create the board that will hold the circuit and arduino board. this platform will be placed above the battery pack, covering it. Cut out a cardboard piece that has the same measurements as the inside of the box. Then place holes on either side of the board. Place a string through the hole and then hot glue gun it to make sure it does not come out. Do this to the other side as well. These two pieces of string will crate the holders that will be used to easily remove the circuit and arduino board out of the box.
Paint the Car
Now you can close the box and begin painting the car. Be creative and try to make a unique design that is special to you.
Add LED's and Ultrasonic Sensor
We can now begin to insert the LED's and the ultrasonic sensor (only second car). In both cars cut out three holes, one at the top and two at the bottom. The top LED will display the leader car. The bottom two LED's will display whether the Bluetooth has connected or not. Insert the LED's through the holes and hot glue gun them to the cardboard.
Poke A hole through the front of the second car. That is wide enough for the four ultrasonic sensor pins. Insert the sensor through the hole.
Add Lock to Flap
The last part in creating your car is to create the flap that will be used to lock the lid of the box. There are many ways to do this and this is simply one of the ways.
Take a wire or a string-like piece. Connect a small flat cardboard piece to the wire and glue it together. Then glue the wire onto the box. Poke a hole through the outside of the box that will allow the small flat cardboard piece to fit through. Simply put this piece through the box then through the flap.
Create Circuit
Now that we have created the cars and we can now create the circuit. Use the circuit diagram above to help you create circuit/wiring of the parts. The second car will not require the ultrasonic sensor.
Create Program
//CODE FOR CAR 1
/************************************************
/instantiate servo
#include
Servo RServo;//create servo object to control right servo
Servo LServo;//create servo object to control left servo
/************************************************
************************************************
/variables for car movements
int RServoPin = 13; //left wheel
int LServoPin = 12; //right wheel
int RServoSpeed = 90; //right wheel speed
int LServoSpeed = 90; //left wheel speed
int speed = 0; //speed set by bluetooth
//variables for car positions
int carPosition = 0; // 1 = Arrow, 2 = Vertical Line, 3 = Horizontal Line
int prevCarPosition = 2;
int carLeader = 1; // 1 = car 1, 2 = car 2, 3 = car 3
int prevCarLeader = 0;
int flag = 0; // count for loop checks
int flag2 = 1;
int lastAction = 0;
/************************************************
/variables for timing
long startTime = 0;
long endTime = 0;
long waitTime = 0;
long currentTime = 0;
/************************************************/
char data = 'S';
// Data is used for inputs from bluetooth /
/ S = stop
// F = forward
// L = left
// R = right
// G = forward/left
// I = forward/right
// B = backward
// H = backward/left
// J = backward/right
//variables for ultrasonic sensor
int trigPin = 10;
int echoPin = 11;
long duration;
int distance = 0;
/************************************************/
void setup() {
//servo attach and setup
RServo.attach(RServoPin);//attachs the servo on pin 13 to servo object
RServo.write(RServoSpeed);//back to stop
LServo.attach(LServoPin);//attachs the servo on pin 12 to servo object
LServo.write(LServoSpeed);//back to stop
// Default connection rate for BT module
Serial.begin(9600);
delay(1500);
pinMode(6, OUTPUT); // set pin to input
digitalWrite(6, HIGH); // turn on pullup resistors
pinMode(5, OUTPUT);
pinMode(7, OUTPUT);
/************************************************
/lineup cars
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
}
/************************************************/
void loop() {
//Checks to see if car is leader or not
if (carLeader == 1) //this car is leader
{
LeaderMovement(); //calls normal bluetooth check with no timing
Speed(); //checks to see if speed was adjusted
CarPosition();
Leader(); // check to see if leader has changed and changes leaders
digitalWrite(5, HIGH);
}
else if (carLeader == 2) //other car is leader
{
FollowerMovement(); //calls second bluetooth check with timing
Speed();
CarPosition(); //checks to see if car positions were changed
Leader();
digitalWrite(5, LOW);
}
if(Serial.available() > 0)
{
data = Serial.read(); //debug variable
Serial.println(data); //debug input
digitalWrite(6, LOW);
digitalWrite(7, HIGH);
}
if (data == 'V')
{
while(distance != 14)
{
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance= duration*0.034/2;
//Prints the distance on the Serial Monitor
//Serial.print("Distance: ");
//Serial.println(distance);
if (distance > 14)
{
RServo.write(85);
LServo.write(95);
}
else if (distance < 14)
{
RServo.write(95);
LServo.write(85);
}
}
data = 'S';
}
}
/************************************************/
void LeaderMovement()
{
//check to see bluetooth for input and move car according to input//
switch(data)
{
case 'S':
if (lastAction == 0)
{
RServo.write(90);
LServo.write(90);
}
else if (carPosition == 2 && lastAction == 1) //leader turned left
{
RServo.write(80);
LServo.write(100);
delay (1800);
}
else if (carPosition == 2 && lastAction == 2) //leader turned right
{
RServo.write(80);
LServo.write(100);
delay (1800);
}
lastAction = 0;
break;
case 'F':
RServo.write(RServoSpeed);
LServo.write(LServoSpeed);
break;
case 'L':
if (carPosition == 1)
{
RServo.write(85);
LServo.write(93);
}
if (carPosition == 2)
{
RServo.write(RServoSpeed);
LServo.write(90);
lastAction = 1;
}
else if (carPosition == 3)
{
RServo.write(87);
LServo.write(90);
}
else
{
RServo.write(RServoSpeed);
LServo.write(90);
}
break;
case 'R':
if (carPosition == 1)
{
RServo.write(86);
LServo.write(97);
}
if (carPosition == 2)
{
RServo.write(90);
LServo.write(LServoSpeed);
lastAction = 2;
}
else if (carPosition == 3)
{
RServo.write(86);
LServo.write(96);
}
else
{
RServo.write(90);
LServo.write(LServoSpeed);
}
break;
case 'G':
RServo.write(RServoSpeed);
LServo.write(LServoSpeed - (2 * (speed - 1)));
break;
case 'I':
RServo.write(RServoSpeed + (2 * (speed - 1)));
LServo.write(LServoSpeed);
break;
case 'B':
RServo.write(RServoSpeed + (speed * 4));
LServo.write(LServoSpeed - (speed * 4));
break;
case 'H':
RServo.write(RServoSpeed + (speed * 4));
LServo.write(LServoSpeed + (2 * (speed - 1)) - (speed * 4));
break;
case 'J':
RServo.write(RServoSpeed - (2 * (speed - 1)) + (speed * 4));
LServo.write(LServoSpeed - (speed * 4));
break;
default:
RServo.write(90);
LServo.write(90);
break;
}
}
void Speed()
{
switch(data)
{
case '0':
speed = 0;
RServoSpeed = 90;
LServoSpeed = 90;
break;
case '1':
speed = 1;
RServoSpeed = 88;
LServoSpeed = 92;
break;
case '2':
speed = 2;
RServoSpeed = 86;
LServoSpeed = 94;
break;
case '3':
speed = 3;
RServoSpeed = 84;
LServoSpeed = 96;
break;
case '4':
speed = 4;
RServoSpeed = 82;
LServoSpeed = 98;
break;
case '5':
speed = 5;
RServoSpeed = 80;
LServoSpeed = 100;
break;
}
}
void FollowerMovement()
{
//check to see bluetooth for input and move car according to input//
switch(data)
{
case 'S': //stop
if (lastAction == 0)
{
RServo.write(90);
LServo.write(90);
}
else if (carPosition == 2 && lastAction == 1) //leader turned left
{
RServo.write(80);
LServo.write(100);
delay (1800);
RServo.write(RServoSpeed);
LServo.write(90);
delay (waitTime);
}
else if (carPosition == 2 && lastAction == 2) //leader turned right
{
RServo.write(80);
LServo.write(100);
delay (1800);
RServo.write(90);
LServo.write(LServoSpeed);
delay (waitTime);
}
//reset variables below
flag = 0;
flag2 = 1;
lastAction = 0;
break;
case 'F': //forward
RServo.write(RServoSpeed);
LServo.write(LServoSpeed);
break;
case 'L': //left
lastAction = 1;
if (carPosition == 2 && flag2 == 1) //*vertical line*
{
startTime = millis();
flag2 = 0;
flag = 1;
}
else if (flag == 1)
{
waitTime = (millis() - startTime);
}
if (carPosition == 3)
{
RServo.write(83);
LServo.write(94);
}
if (carPosition == 1)
{
RServo.write(85);
LServo.write(94);
}
break;
case 'R': //right
lastAction = 2;
if (carPosition == 2 && flag2 == 1) //*vertical line*
{
startTime = millis();
flag2 = 0;
flag = 1; //turn is done
}
else if (flag == 1)
{
waitTime = (millis() - startTime);
//waitTime = (waitTime/15) + waitTime;
}
if (carPosition == 3)
{
RServo.write(90);
LServo.write(92);
}
if (carPosition == 1)
{
RServo.write(89);
LServo.write(93);
}
break;
case 'G': //forward left
/*if (carPosition == 2 && flag == 0) //*vertical line*
{
RServo.write(80);
LServo.write(100);
delay(500);
flag = 1;
}
else if (flag == 1)
{
RServo.write(80);
LServo.write(96);
}*/
RServo.write(RServoSpeed);
LServo.write(LServoSpeed - (2 * (speed - 1)));
break;
case 'I': // forward right
/*if(carPosition == 2 && flag == 0) //*vertical line*
{
RServo.write(80);
LServo.write(100);
delay(500);
flag = 1;
}
else if (flag == 1)
{
RServo.write(84);
LServo.write(100);
}*/
RServo.write(RServoSpeed + (2 * (speed - 1)));
LServo.write(LServoSpeed);
break;
case 'B':
RServo.write(RServoSpeed + (speed * 4));
LServo.write(LServoSpeed - (speed * 4));
break;
case 'H':
RServo.write(RServoSpeed + (speed * 4));
LServo.write(LServoSpeed + (2 * (speed - 1)) - (speed * 4));
break;
case 'J':
RServo.write(RServoSpeed - (2 * (speed - 1)) + (speed * 4));
LServo.write(LServoSpeed - (speed * 4));
break;
}
}
/*************************************************************/
void CarPosition()
{
switch (data)
{
case 'X':
prevCarPosition = carPosition;
carPosition = 1;
ChangeCarPosition();
break;
case 'Y':
prevCarPosition = carPosition;
carPosition = 2;
ChangeCarPosition();
break;
case 'Z':
prevCarPosition = carPosition;
carPosition = 3;
ChangeCarPosition();
break;
}
}
void ChangeCarPosition()
{
if(carLeader == 2)
{
if (prevCarPosition == 1 && carPosition == 2)//
{
RServo.write(100);
LServo.write(90);
delay(1500);
RServo.write(100);
LServo.write(80);
delay(500);
RServo.write(90);
LServo.write(80);
delay(1500);
Stop();
}
else if (prevCarPosition == 1 && carPosition == 3)//
{
RServo.write(80);
LServo.write(100);
delay(1100);
Stop();
}
else if (prevCarPosition == 2 && carPosition == 1)//
{
RServo.write(90);
LServo.write(100);
delay(1500);
RServo.write(80);
LServo.write(100);
delay(500);
RServo.write(80);
LServo.write(90);
delay(1550);
Stop();
}
else if (prevCarPosition == 2 && carPosition == 3)//
{
RServo.write(90);
LServo.write(100);
delay(1500);
RServo.write(80);
LServo.write(100);
delay(500);
RServo.write(80);
LServo.write(90);
delay(1500);
RServo.write(80);
LServo.write(100);
delay(1100);
Stop();
}
else if (prevCarPosition == 3 && carPosition == 1)//
{
RServo.write(100);
LServo.write(80);
delay(1100);
Stop();
}
else if (prevCarPosition == 3 && carPosition == 2)//
{
RServo.write(100);
LServo.write(80);
delay(1000);
RServo.write(100);
LServo.write(90);
delay(1500);
RServo.write(100);
LServo.write(80);
delay(500);
RServo.write(90);
LServo.write(80);
delay(1500);
Stop();
}
}
}
void Leader()
{
switch (data)
{
case 'A':
prevCarLeader = carLeader;
carLeader = 1;
ChangeLeader();
break;
case 'C':
prevCarLeader = carLeader;
carLeader = 2;
ChangeLeader();
break;
}
}
void ChangeLeader()
{
if(carLeader == 2)
{
if ((prevCarLeader == 1 && carLeader == 2) || (prevCarLeader == 2 && carLeader == 1))
{
if (carPosition == 1)
{
RServo.write(80);
LServo.write(100);
delay(200);
RServo.write(90);
LServo.write(100);
delay(1300);
RServo.write(80);
LServo.write(100);
delay(1900);
RServo.write(80);
LServo.write(90);
delay(1300);
RServo.write(100);
LServo.write(80);
delay(3050);
Stop();
}
else if (carPosition == 2)
{
RServo.write(90);
LServo.write(100);
delay(1400);
RServo.write(80);
LServo.write(100);
delay(600);
RServo.write(90);
LServo.write(100);
delay(1400);
RServo.write(80);
LServo.write(100);
delay(3600);
RServo.write(90);
LServo.write(100);
delay(1400);
RServo.write(80);
LServo.write(100);
delay(500);
RServo.write(90);
LServo.write(100);
delay(1350);
Stop();
}
else if (carPosition == 3)
{
RServo.write(80);
LServo.write(100);
delay(1000);
RServo.write(90);
LServo.write(100);
delay(1200);
RServo.write(80);
LServo.write(100);
delay(2200);
RServo.write(80);
LServo.write(90);
delay(1300);
RServo.write(100);
LServo.write(80);
delay(2000);
Stop();
}
}
}
}
void Stop()
{
RServo.write(90);
LServo.write(90);
}
Create App
We are now on the final, but hardest step. We must create an app that can be used to control the cars by sending data through the Bluetooth. You can use the very simple MIT App Inventor (android user only). Use may use the above pics to create the style of the app. The pictures above also contain the code that will be required.
Follow the instructions above to create the app by yourself, or use the link below to open it.
ai2.appinventor.mit.edu/?galleryId=5614395115438080
Repeat Steps 1-12
Repeat these steps to create the second car.