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.
Building a 4WD Autonomous Car with Arduino
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.
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.
Below are images of the main components you need (apart from the wiring and batteries) – the different robot parts, shields, modules and sensors.
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)
- Arduino IDE software – free at http://www.arduino.cc
- 1x USB cable (A male plug to B male plug)
- A computer to program with
Below are images of the main components you need (apart from the wiring and batteries) – the different robot parts, shields, modules and sensors.
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!
Wiring diagram
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
- void setup() {
- // 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);
- }
- void loop() {
- // 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
- void motorAforward() {
- digitalWrite (pinA1, HIGH);
- digitalWrite (pinA2, LOW);
- }
- void motorBforward() {
- digitalWrite (pinB1, LOW);
- digitalWrite (pinB2, HIGH);
- }
- void motorAbackward() {
- digitalWrite (pinA1, LOW);
- digitalWrite (pinA2, HIGH);
- }
- void motorBbackward() {
- digitalWrite (pinB1, HIGH);
- digitalWrite (pinB2, LOW);
- }
- void motorAstop() {
- digitalWrite (pinA1, HIGH);
- digitalWrite (pinA2, HIGH);
- }
- void motorBstop() {
- digitalWrite (pinB1, HIGH);
- digitalWrite (pinB2, HIGH);
- }
- void motorAcoast() {
- digitalWrite (pinA1, LOW);
- digitalWrite (pinA2, LOW);
- }
- void motorBcoast() {
- digitalWrite (pinB1, LOW);
- digitalWrite (pinB2, LOW);
- }
- void motorAon() {
- digitalWrite (enableA, HIGH);
- }
- void motorBon() {
- digitalWrite (enableB, HIGH);
- }
- void motorAoff() {
- digitalWrite (enableA, LOW);
- }
- void motorBoff() {
- digitalWrite (enableB, LOW);
- }
- // Setup movement functions
- void forward (int duration) {
- motorAforward();
- motorBforward();
- delay (duration);
- }
- void backward (int duration) {
- motorAbackward();
- motorBbackward();
- delay (duration);
- }
- void right (int duration) {
- motorAbackward();
- motorBforward();
- delay (duration);
- }
- void left (int duration) {
- motorAforward();
- motorBbackward();
- delay (duration);
- }
- void coast (int duration) {
- motorAcoast();
- motorBcoast();
- delay (duration);
- }
- void breakRobot (int duration) {
- motorAstop();
- motorBstop();
- delay (duration);
- }
- void disableMotors() {
- motorAoff();
- motorBoff();
- }
- void enableMotors() {
- motorAon();
- motorBon();
- }
- // Setup Ultrasonic Sensor distance measuring
- int distance() {
- 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
- void car() {
- 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);
- }
- else if(servposnum == 1)
- {
- myservo.writeMicroseconds (2200);
- servposnum = 2;
- delay(100);
- }
- else if(servposnum == 2)
- {
- myservo.writeMicroseconds (1900);
- servposnum = 3;
- delay(100);
- }
- else if(servposnum == 3)
- {
- myservo.writeMicroseconds (1600);
- servposnum = 1;
- delay(100);
- }
- motorAon();
- motorBon();
- forward(1);
- distance_0 = distance();
- }
- breakRobot(0);
- }
- void avoid()
- {
- // 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
- void setup() {
- // 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);
- }
- void loop() {
- // 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
- void motorAforward() {
- digitalWrite (pinA1, HIGH);
- digitalWrite (pinA2, LOW);
- }
- void motorBforward() {
- digitalWrite (pinB1, LOW);
- digitalWrite (pinB2, HIGH);
- }
- void motorAbackward() {
- digitalWrite (pinA1, LOW);
- digitalWrite (pinA2, HIGH);
- }
- void motorBbackward() {
- digitalWrite (pinB1, HIGH);
- digitalWrite (pinB2, LOW);
- }
- void motorAstop() {
- digitalWrite (pinA1, HIGH);
- digitalWrite (pinA2, HIGH);
- }
- void motorBstop() {
- digitalWrite (pinB1, HIGH);
- digitalWrite (pinB2, HIGH);
- }
- void motorAcoast() {
- digitalWrite (pinA1, LOW);
- digitalWrite (pinA2, LOW);
- }
- void motorBcoast() {
- digitalWrite (pinB1, LOW);
- digitalWrite (pinB2, LOW);
- }
- void motorAon() {
- digitalWrite (enableA, HIGH);
- }
- void motorBon() {
- digitalWrite (enableB, HIGH);
- }
- void motorAoff() {
- digitalWrite (enableA, LOW);
- }
- void motorBoff() {
- digitalWrite (enableB, LOW);
- }
- // Setup movement functions
- void forward (int duration) {
- motorAforward();
- motorBforward();
- delay (duration);
- }
- void backward (int duration) {
- motorAbackward();
- motorBbackward();
- delay (duration);
- }
- void right (int duration) {
- motorAbackward();
- motorBforward();
- delay (duration);
- }
- void left (int duration) {
- motorAforward();
- motorBbackward();
- delay (duration);
- }
- void coast (int duration) {
- motorAcoast();
- motorBcoast();
- delay (duration);
- }
- void breakRobot (int duration) {
- motorAstop();
- motorBstop();
- delay (duration);
- }
- void disableMotors() {
- motorAoff();
- motorBoff();
- }
- void enableMotors() {
- motorAon();
- motorBon();
- }
- // Setup Ultrasonic Sensor distance measuring
- int distance() {
- 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
- void car() {
- 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
- void avoid()
- {
- 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
Video Player
00:00
00:21