Hi! In this project, I will be making an Arduino-based car that can be controlled through an app using Bluetooth with an automatic braking feature that stops the car to avoid a crash. The car will use an ultrasonic sensor mounted on a servo to detect objects in front when the car is moving forward and will turn to face the back when the car is moving backwards. I will be using the l293d motor driver here to drive the geared motors. I have initially planned to make this a 4WD car, hence the smart car chassis kit I bought had 4 motors, however, after testing, a 9V battery was not powerful enough to drive all the components in the car. This is why I turned this to a 2 WD car and substituted the 2 front motors with one nylon wheel.
This car does not have any steering mechanism, so turning left and right will rely on friction. This can be done by making the right wheel rotate forward and the left rotate backward to turn left and vice versa. This way, the car can also turn around on the spot without moving forward or backwards.
Building the carSoldering
Before assembling the car, there will be some soldering that has to be done. Firstly, starting with the geared motors.
The wires came with the car kit that I got but they were not yet soldered.
Next, taking a look at the l293d motor shield, there were also some header pins that had to be soldered on. This is how my motor shield looks like before and after adding the pins.
pins 2 and 13 are unused by the board so I soldered pins on them for the ultrasonic sensor. Pins 0 and 1 are also needed for transmitting and recieving for the bluetooth module. I also soldered pins to the power pins at the bottom of the shield.
This is how I soldered the header pins to pins 13, 0 and 1.
Car assembly
The name of the the smart car kit I got is the ZK4WD. It comes with an instruction manual on how to install the motors onto the chassis. I will only be using two motors, this is how it would look.
I used double-sided tape to stick the nylon wheel in front.
Next, working on the upper chassis of the car, first I use nylon cable ties to hold the arduino on to the car and double-sided tape to stick the battery holder in front of the arduino.
To make turning on and off the car easier, I added a switch on to the wire of the battery holder.
At this point I realised that the only 18650 battery I had were only 3.7V each and wouldn't be powerful enough to power the car so I connected a 4x AA battery holder with 1.5V each so the total will be 8.9 V.
The ultrasonic sensor will be mounted on top of the servo. I created a holder for the ultrasonic sensor using cardboard and tape.
The servo is then mounted on the side of the battery using double-sided tape.
And the ultrasonic sensor will be mounted on top of the servo using double sided tape.
This is how the final design of the car will look like.
Connectingthecomponents
- Mount the motor shield onto the arduino
- Screw the motors into the terminal pairs. Don't worry about the polarity (you can switch them after testing)
- Connect the servo into the servo 1 header pin on the motor shield, the brown wire here should be connected to the negative terminal
- plug the cable from the battery holder to the power terminal. (Make sure the positive side of the battery is connected to the positive terminal and the negative side is connected to the ground).
- Connect the ultrasonic sensor to a cable and connect the Vcc and the ground wires to the 5V and the ground pins. Connect the echo pin to pin 13 and the trigger pin to pin 2.
- Connect the hc05 bluetooth module to a cable and connect the txd and rxd to pins 0 and 1 and connect the. Connect the vcc and gnd to the + and - of ther servo 2 pin on the motor shield.
Programming the Arduino
Programming the ArduinoThere are two libraries that is needed for my program, the AFMotor.h to control the motor shield, and the Servo.h to control the motors
The Arduino Bluetooth app sends commands/characters as an input when a button is pressed
I will be using a switch statement to assign specific instructions for when a button in the Arduino Bluetooth app is pressed.
The object sensing is done by the HC-SR04 ultrasonic sensor. The sensor emits an ultrasound through the air and if there is an object, it will bounce back to the module. Considering the travel time and speed of the sound, we can calculate the distance. In order to generate the ultrasound, the trigger pin needs to be set to high for 10 microseconds. This will transmit an 8 cycle sonic burst at 40kHz. The echo pin will then go high when the sensor detects the ultrasound that has been reflected. Using pulseIn(echo, HIGH)
this will wait for the echo pin to go high. I also added a timeout as a parameter for the pulseIn function to set a maximum time to wait for a return signal. With this, we have the time required for the ultrasonic sensor to transmit the signal and receive it back. Since the ultrasound travels at the speed of sound, we can calculate the distance from the sensor to an object by dividing the time taken for the signal to return by 2 and multiplying it by the speed of sound in air.
I have created a function called getDistance that will return the distance between the ultrasonic sensor and an object it is facing. I use this function whenever the car will move forward or backwards, which will automatically stop the car when the distance returned by the function is less than the maximum distance I set. the sensor will face forward when the car is moving forward and it will face backwards when the car is moving backwards. The direction the sensor is facing will be controlled by the servo as the sensor will be mounted on top of the servo.
The code
//Christopher Sutjiono
#include <AFMotor.h> //Import library to control motor shield
#include <Servo.h> //Import library to control the servo
AF_DCMotor leftBack(1);
AF_DCMotor rightBack(4);
Servo servoLook; //Create an object to control the servo
char command; //Global Variable to store input from BT app
int motorspeed = 100; // speed variable (0 - 255)
byte trig = 2; //Assign the ultrasonic sensor pins
byte echo = 13;
byte stopDist = 50; //Distance from an object to stop in cm
float timeOut = 2 * (maxDist + 10) / 100 / 340 * 1000000; //Maximum time to wait for a return signal
void setup() {
Serial.begin(9600); //Set the baud rate to the Bluetooth module.
StopMove(); //Ensure all motors are stopped
servoLook.attach(10); //Assign the servo pin
servoLook.write(180);
pinMode(trig, OUTPUT); //Assign ultrasonic sensor pin modes
pinMode(echo, INPUT);
}
void loop()
{
if (Serial.available() > 0)
{
command = Serial.read(); //Stores input to variable
switch (command) { //Use input as case for switch statement
case 'F':
servoLook.write(180); //Set the servo to look front
if (getDistance() >= stopDist) //If there are no objects within the stopping distance, move forward
{
Drive();
}
else StopMove(); //If there are object within stopping distance, stop the car
break;
case 'B':
servoLook.write(0); //Set the servo to look back
if (getDistance() >= stopDist) //If there are no objects within the stopping distance, move backward
{
Reverse(); //If there are object within stopping distance, stop the car
}
else StopMove();
break;
case 'L': TurnLeft(); break;
case 'R': TurnRight(); break;
case 'G': DriveLeft(); break;
case 'I': DriveRight(); break;
case 'H': ReverseLeft(); break;
case 'J': ReverseRight(); break;
case 'S': StopMove(); break;
case '0': motorspeed = 0; break;
case '1': motorspeed = 25; break;
case '2': motorspeed = 50; break;
case '3': motorspeed = 75; break;
case '4': motorspeed = 100; break;
case '5': motorspeed = 125; break;
case '6': motorspeed = 150; break;
case '7': motorspeed = 175; break;
case '8': motorspeed = 200; break;
case '9': motorspeed = 225; break;
case 'q': motorspeed = 250; break;
}
}
}
void Drive()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(FORWARD); //rotate the motor clockwise
rightBack.setSpeed(motorspeed);//Define maximum velocity
rightBack.run(FORWARD); //rotate the motor clockwise
}
void Reverse()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(BACKWARD); //rotate the motor anti-clockwise
rightBack.setSpeed(motorspeed); //Define maximum velocity
rightBack.run(BACKWARD); //rotate the motor anti-clockwise
}
void TurnLeft()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(BACKWARD); //rotate the motor anti-clockwise
rightBack.setSpeed(motorspeed); //Define maximum velocity
rightBack.run(FORWARD); //rotate the motor clockwise
}
void TurnRight()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(FORWARD); //rotate the motor clockwise
rightBack.setSpeed(motorspeed); //Define maximum velocity
rightBack.run(BACKWARD); //rotate the motor anti-clockwise
}
void DriveRight()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(FORWARD); //rotate the motor clockwise
rightBack.setSpeed(motorspeed / 4); //Define maximum velocity
rightBack.run(FORWARD); //rotate the motor clockwise
}
void ReverseRight()
{
leftBack.setSpeed(motorspeed / 4); //Define maximum velocity
leftBack.run(BACKWARD); //rotate the motor anti-clockwise
rightBack.setSpeed(motorspeed); //Define maximum velocity
rightBack.run(BACKWARD); //rotate the motor anti-clockwise
}
void DriveLeft()
{
leftBack.setSpeed(motorspeed / 4); //Define maximum velocity
leftBack.run(FORWARD); //rotate the motor clockwise
rightBack.setSpeed(motorspeed); //Define maximum velocity
rightBack.run(FORWARD); //rotate the motor clockwise
}
void ReverseLeft()
{
leftBack.setSpeed(motorspeed); //Define maximum velocity
leftBack.run(BACKWARD); //rotate the motor clockwise
rightBack.setSpeed(motorspeed / 4); //Define maximum velocity
rightBack.run(BACKWARD); //rotate the motor anti-clockwise
}
void StopMove() //Set all motors to stop
{
leftBack.setSpeed(0); //Define minimum velocity
leftBack.run(RELEASE); //rotate the motor clockwise
rightBack.setSpeed(0); //Define minimum velocity
rightBack.run(RELEASE); //stop the motor when release the button
}
int getDistance() //Get the distance between the ultrasonic sensor and an object
{
unsigned long pulseTime; //Create a variable to store the pulse travel time
int distance; //Create a variable to store the calculated distance
digitalWrite(trig, HIGH); //Generate a 10 microsecond pulse
delayMicroseconds(10);
digitalWrite(trig, LOW);
pulseTime = pulseIn(echo, HIGH, timeOut); //Measure the time for the pulse to return
distance = (float)pulseTime * 340 / 2 / 10000; //Calculate the object distance based on the pulse time
return distance;
}
Video demo
Comments