Tag Archives: robotic

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.

4WD autonomous robotic car
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)
  • Arduino IDE software – free at http://www.arduino.cc
  • 1x USB cable (A male plug to B male plug)
  • A computer to program with

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

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.

  1. Connect the red wire (voltage) from the battery enclosure to VCC on the L298N Motor Module.
  2. Connect the black wire (ground) from the battery enclosure to GND on the Motor Module.
  3. 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).
  4. Connect the black wire from Motor A1 (rear left) and the black wire from Motor A2 (front left) to OUT2 on the Motor Module.
  5. Connect the red wire from Motor B1 (rear right) and the red wire from Motor B2 (front right) to OUT3 on the Motor Module.
  6. Connect the black wire from Motor B1 (rear right) and the black wire from Motor B2 (front right) to OUT4 on the Motor Module.
  7. 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).
  8. 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).
  9. Connect a female-to-female end wire from IN1 on the Motor Module to signal pin 2 on the Sensor Shield.
  10. Connect a female-to-female end wire from IN2 on the Motor Module to signal pin 3 on the Sensor Shield.
  11. Connect a female-to-female end wire from IN3 on the Motor Module to signal pin 4 on the Sensor Shield.
  12. Connect a female-to-female end wire from IN4 on the Motor Module to signal pin 5 on the Sensor Shield.
  13. 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).
  14. Connect a female-to-female end wire from ENB (Engine B) on the Motor Module to signal pin 6 on the Sensor Shield.
  15. 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.
  16. 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.
  17. 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.
  18. 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).
  19. 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
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


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

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.

More photos

Building a 2WD Arduino robotic car

This tutorial will show you how to use an Arduino to build a 2WD robotic car. You can extend this project by using sensors to measure wheel speed (for improved accuracy when steering or maintaining a straight line) or sensors to avoid objects or follow a line.

Parts required

Here is what you will need:

  • Arduino Uno board
  • 2WD robotic car kit (2 wheels, 2 motors, chassis)
  • 4 x AA batteries
  • Motor shield with 6 wires
  • Arduino IDE software (free at http://www.arduino.cc/)
  • USB cable
  • 2 x wheel speed encoders and infrared sensors (optional)

car1 car2 Assembling the robot

robotassembly

 

  1. Assemble all chassis parts and attach the motors to the wheels (if not already assembled).
  2. Connect the red wire from the battery enclosure to VIN on the Motor Shield.
  3. Connect the black wire from the battery enclosure to GND on the Motor Shield.
  4. Connect the red wire from Motor A to A+ on the Motor Shield, and the black wire from Motor A to A- on the Motor Shield.
  5. Connect the red wire from Motor B to B+ on the Motor Shield, and the black wire from Motor B to B- on the Motor Shield.
  6. Attach the Motor Shield to the top of the Arduino Uno board – be careful not to bend or damage any of the pins!
  7. Connect the Arduino Uno board to the computer via the USB cable and upload the code using the Arduino IDE software.
  8. Insert four AA batteries in the battery enclosure.
  9. Test your robot! If your robot goes in the wrong direction or doesn’t move, check that you have the Motor pins in the correct places and make sure no pins are loose.
Extra challenges:
  • Control your robotic car using an Android app on a smartphone via Bluetooth (refer to the Controlling an LED by Bluetooth tutorial for instructions on how to make an app using App Inventor and how to attach a Bluetooth module).
  • Add code that will control the speed of the motors using the encoder discs and infrared sensors.
The code to test your robot

Use this code to test that your wheels spin and that your robot is wired up correctly.

void setup() {
    //Setup Channel A
  pinMode(12, OUTPUT); //Initiates Motor Channel A pin
  pinMode(9, OUTPUT); //Initiates Brake Channel A pin
  //Setup Channel B
  pinMode(13, OUTPUT); //Initiates Motor Channel B pin
  pinMode(8, OUTPUT);  //Initiates Brake Channel B pin
  }
void loop(){
  //Motor A forward @ full speed
  digitalWrite(12, HIGH); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 255);   //Spins the motor on Channel A at full speed
  //Motor B backward @ half speed
  digitalWrite(13, LOW);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 123);    //Spins the motor on Channel B at half speed
  delay(3000);
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(8, HIGH);  //Engage the Brake for Channel B
  delay(1000);
  //Motor A forward @ full speed
  digitalWrite(12, LOW);  //Establishes backward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 123);    //Spins the motor on Channel A at half speed
  //Motor B forward @ full speed
  digitalWrite(13, HIGH); //Establishes forward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 255);   //Spins the motor on Channel B at full speed
  delay(3000);
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(8, HIGH);  //Engage the Brake for Channel B
  delay(1000);
}

Click here if you would like a PDF copy of these instructions.