Introduction: 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

Step 1: 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.

Step 2: 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.

Step 3: 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.

Step 4: 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.

Step 5: 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.

Step 6: 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.

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

Step 8: 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.

Step 9: 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.

Step 10: 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.

Step 11: 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.

Step 12: 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);

}

Step 13: 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

Step 14: Repeat Steps 1-12

Repeat these steps to create the second car.

Step 15: Enjoy

Wheels Contest 2017

Participated in the
Wheels Contest 2017

Remote Control Contest 2017

Participated in the
Remote Control Contest 2017

Arduino Contest 2017

Participated in the
Arduino Contest 2017