This is an excellent project which demonstrates how to control a 4WD Arduino Car.
However this car cannot spin but it is easy to modify the code to allow it to spin instead of just turning left and right.
This Arduino car has a better turning radius than cars that have steering wheels because it can spin.
If the left wheels are run forward and the right wheels are run reversed, the car will spin.
It allows the car to manoeuvre in tight spaces, but when spinning it cannot move forward at the same time.
To left or right while moving forward, just move the left wheels at a different speed from that of the right wheels.
It means that there is no need to use 4 speed controllers. Only 2 speed controllers are required. One speed controller for the left and another for the right wheels.
If we can control the speed of 3 wheels independently, we can spin the car around one wheel. I do not see much advantage out of it.
In this tutorial you will learn to make a 4WD robotic car with
built-in obstacle avoidance. This project involves building a 4WD car
with an ultrasonic sensor that can detect nearby objects and change its
direction to avoid these objects. The ultrasonic sensor will be attached
to a servo motor which is constantly scanning left and right looking
for objects in its way. 4WD autonomous robotic car
You can extend this project by adding more sensors such as ultrasonic
sensor to the rear so that the car doesn’t reverse into objects, speed
detection sensors to determine speed, line following sensors, and LED
brake lights. You could even add light sensors and LEDs to turn
headlights on in low-light conditions or a Bluetooth connection to
control the car through a mobile app.
Parts required
Here is what you will need:
1x Arduino Uno board
1x 4WD Robotic Car kit (4 wheels, 4 motors, chassis, AA battery enclosure, screws)
6x AA batteries
1x 9V battery
1x 9V battery power cable barrel jack connector
1x L298N Motor Module
1x Arduino Sensor Shield v5.0
1x HC-SR04 Ultrasonic Sensor
1x Servo motor (any small servo motor will do but if you don’t have one you can leave it out)
Assorted colour wires:
4x female-to-female wires for Ultrasonic Sensor
8x female-to-female wires for the Motor Module to Sensor Shield
8x bare-ended wires to go from the four motors to the Motor Module
2x bare-ended wires to go from the Motor Module to Sensor Shield
3x wires for the servo motor with female end attaching to Sensor Shield (should already be included with the servo motor)
2x bare-ended wires to go from AA Battery enclosure to the motor Module (should already be included with the battery enclosure)
Note: Make sure you get a range of different colours
for the wires (eg. red for voltage, black for ground, etc.). Some items
such as the battery enclosure, motors and servo motor may come with
wires so you may not need to purchase these separately. Some motor
modules or sensor shields may use different pins (eg. male or female or
just bare-ended wires).
Below are images of the main components you need (apart from the
wiring and batteries) – the different robot parts, shields, modules and
sensors. Click for larger image
Assembling the robotic car
The first thing to do is to assemble all the car chassis parts and
attach the motors to the wheels. This is explained in detail in the
video below.
Video Player
00:00
15:59
Wiring it up
Now that the chassis is assembled and the wheels and motors are
attached, you will need to wire up all of the components. You can watch
the video below or scroll down for the step-by-step instructions and
wiring diagram.
Video Player
00:00
18:38
Connect the red wire (voltage) from the battery enclosure to VCC on the L298N Motor Module.
Connect the black wire (ground) from the battery enclosure to GND on the Motor Module.
Connect the red wire from Motor A1 (rear left) and the red wire from
Motor A2 (front left) to OUT1 on the Motor Module (both wires can be
twisted together and will go into OUT1 – the wiring diagram further down this page shows how to do this).
Connect the black wire from Motor A1 (rear left) and the black wire from Motor A2 (front left) to OUT2 on the Motor Module.
Connect the red wire from Motor B1 (rear right) and the red wire from Motor B2 (front right) to OUT3 on the Motor Module.
Connect the black wire from Motor B1 (rear right) and the black wire from Motor B2 (front right) to OUT4 on the Motor Module.
Connect a female-to-female end wire from ENA (Engine A) on the Motor
Module to signal pin 1 on the Sensor Shield (the #2 pin in the S row.
There are three rows – S stands for Signal, V for Voltage and G for
Ground).
Connect a female-to-female end wire from 5V (next to ENA) on the
Motor Module to voltage pin 1 on the Sensor Shield (it doesn’t really
matter which pin for voltage as long as it is in the V row).
Connect a female-to-female end wire from IN1 on the Motor Module to signal pin 2 on the Sensor Shield.
Connect a female-to-female end wire from IN2 on the Motor Module to signal pin 3 on the Sensor Shield.
Connect a female-to-female end wire from IN3 on the Motor Module to signal pin 4 on the Sensor Shield.
Connect a female-to-female end wire from IN4 on the Motor Module to signal pin 5 on the Sensor Shield.
Connect a female-to-female end wire from 5V (next to ENB) on the
Motor Module to voltage pin 6 on the Sensor Shield (it doesn’t really
matter which pin for voltage as long as it is in the V row).
Connect a female-to-female end wire from ENB (Engine B) on the Motor Module to signal pin 6 on the Sensor Shield.
Connect the signal wire from the servo motor to signal (S) pin 7 on
the Sensor Shield, the voltage wire from the servo motor to the voltage
(V) pin 7 on the Sensor Shield, and the ground wire from the servo motor
to the GND (G) pin 7 on the Sensor Shield.
Attach the Ultrasonic Sensor to the servo motor and then attach the
servo motor to the front of the car so that it can scan left and right
looking for objects in its path.
You can use sticky tape, blu-tack, glue or a 3D printed/laser cut mount
or whatever you like to attach everything, as long as everything is
firmly mounted.
Use female-to-female end plugs to connect the Ultrasonic sensor to
the Sensor Shield. Firstly, attach the TRIG pin from the Ultrasonic
sensor to signal (S) pin 8 on the Sensor Shield. Attach the ECHO pin
from the ultrasonic sensor to signal (S) pin 9 on the Sensor
Shield. Attach the VCC pin from the Ultrasonic Sensor to the voltage (V)
pin 10 on the Sensor Shield. Lastly, attach the GND pin from the
Ultrasonic Sensor to the GND (G) pin 11 on the Sensor Shield.
Now attach the Sensor Shield on top of the Arduino Uno board making
sure to not bend any pins. Connect a 9V Battery Barrel Jack Connector to
a 9V battery and then plug this in to the Arduino’s barrel jack (see
diagram below).
That’s it! Now all you need is batteries and the code!
Please note: There are several variations of the
sensors and modules and several different ways to wire this up. For
example, you can add a charging component to charge batteries and you
can also add different switches. There may be other better methods to
use, but I have gone for the simplest way I know of to set this up.
Wiring diagram
Click for larger image
Writing the code
Here is the code to get your robot moving. The code is written in C
language and is written in the Arduino IDE software. The code for a
robot with a servo motor and the code for a robot without a servo motor
is shown below. If you don’t have an ultrasonic sensor and just want to
use Bluetooth control via a phone app, then you can just extract the
parts of the code that you need and then add the Bluetooth code.
Code to use with a servo motor
// Setup the servo motor
#include <Servo.h>
Servo myservo;
int servposnum = 0;
int servpos = 0;
// Setup Motor A (front and rear) pins
int enableA = 1;
int pinA1 = 3;
int pinA2 = 2;
// Setup Motor B (front and rear) pins
int enableB = 6;
int pinB1 = 5;
int pinB2 = 4;
// Setup Ultrasonic Sensor pins
#define trigPin 8
#define echoPin 9
voidsetup(){
// The setup code goes here and runs once only
// Configure the pin modes for each drive motor
pinMode(enableA, OUTPUT);
pinMode(pinA1, OUTPUT);
pinMode(pinA2, OUTPUT);
pinMode(enableB, OUTPUT);
pinMode(pinB1, OUTPUT);
pinMode(pinB2, OUTPUT);
// Configure the pin modes for the Ultrasonic Sensor
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// Turn pin into servo driver. Calls pinMode. Returns 0 on failure.
myservo.attach(7);
}
voidloop(){
// Main code goes here and will run repeatedly:
car(); // function keeps moving car forward while distance > 15cm
avoid(); // function makes car go back, turn slightly right to move forward in new direction
}
// Create motor functions
voidmotorAforward(){
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, LOW);
}
voidmotorBforward(){
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, HIGH);
}
voidmotorAbackward(){
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, HIGH);
}
voidmotorBbackward(){
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, LOW);
}
voidmotorAstop(){
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, HIGH);
}
voidmotorBstop(){
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, HIGH);
}
voidmotorAcoast(){
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, LOW);
}
voidmotorBcoast(){
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, LOW);
}
voidmotorAon(){
digitalWrite(enableA, HIGH);
}
voidmotorBon(){
digitalWrite(enableB, HIGH);
}
voidmotorAoff(){
digitalWrite(enableA, LOW);
}
voidmotorBoff(){
digitalWrite(enableB, LOW);
}
// Setup movement functions
voidforward(int duration){
motorAforward();
motorBforward();
delay(duration);
}
voidbackward(int duration){
motorAbackward();
motorBbackward();
delay(duration);
}
voidright(int duration){
motorAbackward();
motorBforward();
delay(duration);
}
voidleft(int duration){
motorAforward();
motorBbackward();
delay(duration);
}
voidcoast(int duration){
motorAcoast();
motorBcoast();
delay(duration);
}
voidbreakRobot(int duration){
motorAstop();
motorBstop();
delay(duration);
}
voiddisableMotors(){
motorAoff();
motorBoff();
}
voidenableMotors(){
motorAon();
motorBon();
}
// Setup Ultrasonic Sensor distance measuring
intdistance(){
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
return distance;
}
// Setup the main car function
voidcar(){
int distance_0;
distance_0 = distance();
// Keep moving forward in a straight line while distance of objects > 15cm
while(distance_0 > 15)
{
// Keep moving servo motor back and forth to scan surroundings
// This allows the ultrasonic sensor to see more to its left and right
if(servposnum == 0)
{
myservo.writeMicroseconds(1900);
servposnum = 1;
delay(100);
}
elseif(servposnum == 1)
{
myservo.writeMicroseconds(2200);
servposnum = 2;
delay(100);
}
elseif(servposnum == 2)
{
myservo.writeMicroseconds(1900);
servposnum = 3;
delay(100);
}
elseif(servposnum == 3)
{
myservo.writeMicroseconds(1600);
servposnum = 1;
delay(100);
}
motorAon();
motorBon();
forward(1);
distance_0 = distance();
}
breakRobot(0);
}
voidavoid()
{
// Go back and turn slightly right to move car in new direction if object detected < 15cm away
backward(500);
right(360);
}
Code to use without a servo motor
// Setup Motor A (front and rear) pins
int enableA = 1;
int pinA1 = 3;
int pinA2 = 2;
// Setup Motor B (front and rear) pins
int enableB = 6;
int pinB1 = 5;
int pinB2 = 4;
// Setup Ultrasonic Sensor pins
#define trigPin 8
#define echoPin 9
voidsetup(){
// The setup code goes here and runs once only
// Configure the pin modes for each drive motor
pinMode(enableA, OUTPUT);
pinMode(pinA1, OUTPUT);
pinMode(pinA2, OUTPUT);
pinMode(enableB, OUTPUT);
pinMode(pinB1, OUTPUT);
pinMode(pinB2, OUTPUT);
// Configure the pin modes for the Ultrasonic Sensor
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
voidloop(){
// Main code goes here and will run repeatedly:
car(); // function keeps moving car forward while distance of objects in front are > 15cm away
avoid(); // function makes car go back, turn slightly right to move forward in new direction
}
// Create motor functions
voidmotorAforward(){
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, LOW);
}
voidmotorBforward(){
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, HIGH);
}
voidmotorAbackward(){
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, HIGH);
}
voidmotorBbackward(){
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, LOW);
}
voidmotorAstop(){
digitalWrite(pinA1, HIGH);
digitalWrite(pinA2, HIGH);
}
voidmotorBstop(){
digitalWrite(pinB1, HIGH);
digitalWrite(pinB2, HIGH);
}
voidmotorAcoast(){
digitalWrite(pinA1, LOW);
digitalWrite(pinA2, LOW);
}
voidmotorBcoast(){
digitalWrite(pinB1, LOW);
digitalWrite(pinB2, LOW);
}
voidmotorAon(){
digitalWrite(enableA, HIGH);
}
voidmotorBon(){
digitalWrite(enableB, HIGH);
}
voidmotorAoff(){
digitalWrite(enableA, LOW);
}
voidmotorBoff(){
digitalWrite(enableB, LOW);
}
// Setup movement functions
voidforward(int duration){
motorAforward();
motorBforward();
delay(duration);
}
voidbackward(int duration){
motorAbackward();
motorBbackward();
delay(duration);
}
voidright(int duration){
motorAbackward();
motorBforward();
delay(duration);
}
voidleft(int duration){
motorAforward();
motorBbackward();
delay(duration);
}
voidcoast(int duration){
motorAcoast();
motorBcoast();
delay(duration);
}
voidbreakRobot(int duration){
motorAstop();
motorBstop();
delay(duration);
}
voiddisableMotors(){
motorAoff();
motorBoff();
}
voidenableMotors(){
motorAon();
motorBon();
}
// Setup Ultrasonic Sensor distance measuring
intdistance(){
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
return distance;
}
// Setup the main car function
voidcar(){
int distance_0;
distance_0 = distance();
// Keep moving forward in a straight line while distance of objects in front > 15cm away
while(distance_0 > 15)
{
motorAon();
motorBon();
forward(1);
distance_0 = distance();
}
breakRobot(0);
}
// Go back and turn slightly right to move car in new direction
// This function only runs if an obstacle within 15cm is detected
voidavoid()
{
backward(500);
right(360);
}
Finishing up
Once you have the code you will need to verify it and then upload it to your Arduino Uno board. Make
sure you have either the Arduino disconnected from the Sensor Shield or
all batteries disconnected when uploading the code to prevent any
errors while uploading. Make sure to also arrange the different components carefully in the chassis to prevent any short circuits. And that’s it! There is so much more
that can be done with this project. Try extending your project by adding
the following features:
Line following
Low-light activated headlights (using light sensors and LEDs)
Brake lights
Speed measuring
Bluetooth/mobile app control
More ultrasonic sensors to avoid reversing into objects or falling off edges
The video below shows a demo of the 4WD autonomous car using an
Arduino and the ultrasonic sensor attache to a servo motor. Six AA
batteries power the motors while the Arduino board is powered using a
separate 9V battery.
No comments:
Post a Comment