top of page

Smart Robotic Car using Arduino



This is a tutorial to help you build and assemble Smart Robotic Car which is built using Arduino Board, Motors and various sensors which will be explained in this story.


Robotic Car Features

  • Control using IR Remote

  • Control via Bluetooth

  • Autonomous Mode

  • Line following Mode

Require Components

  • 1x Arduino UNO

  • 4 x DC Motors (3 — 6 VDC)

  • 1x Servo Motor

  • 1x Motor Driver Module (L298N)

  • 1x Bluetooth Modules (HC-06)

  • 1x Ultrasonic Sensor

  • 3x IR Sensors

  • 1x IR Receiver

  • 1x Remote Control

  • Jumper Wires

  • 2x Car Chassis

  • 4x Wheels


Assembling Components


Step 1: Fixing DC Motors & L298N Motor Driver

First step is to assemble DC Motors on the lower chassis making sure to align right and left motors with each other and then wire each motor to the L298N Motor Driver as shown below.


The L298N Motor Driver Module will control 4 Motors while distributing balanced current to each motor to maintain the car speed at all time.


Just make sure the wiring of each motor is connected so that the front and back motors moves in the same direction or opposite to each other depending on how motor being fixed on the car chassis.

Wiring of Motors to Motor Driver Module
Wiring of Motors to Motor Driver Module

L298N Motors Technical Specifications

  • Motor output voltage: 5 - 35V

  • Motor output voltage (Recommended): 7 - 12V

  • Logic input voltage: 5 - 7V

  • Continuous current per channel: 2A

  • Max Power Dissipation: 25W


L298N will receive Pulse Width Modulation (PWM) signal from Arduino to control motors speed. Wiring between Arduino and L298N Motors Driver is shown below. The module need to be fixed on the car chassis as well.

Interfacing L298N with Arduino GPIO/PWM pins
Interfacing L298N with Arduino GPIO/PWM pins

Upon wiring DC Motors as explained above and fixing the Motor Driver Module we will have the lower part of the car as shown below, thus we could proceed to the next step.


Step 2: Microcontroller (Arduino UNO)


Arduino UNO
Arduino UNO

This project utilizes Arduino UNO to interface between Motor Driver Module, Motors and Sensors. It will receive input from various connected sensors and then control motors accordingly.


As we’ve mentioned above in order to control motor’s speed we need to connect PWM pins of Arduino to the L298N input pins.


In Arduino UNO we have 13 Digital Pins 6 of which are with PWM capability which are represented with the symbol (~) as shown on Arduino UNO figure above (Pins 3, 5, 6, 9, 10, 11).

Wiring between Arduino UNO and L298N
Wiring between Arduino UNO and L298N

We need 2 PWM pins to control motor’s speed which will be used for Enable Pins ENA,ENB. ENA will control speed of right (front and back) motors and ENB will control the left side motors.

Those 2 pins will receive trigger signal from Arduino Pins 11, 6 subsequently with a voltage range between 0–5 Volt, where 5V corresponds to maximum motor speed, 2.5V Mid Speed and 0V to will Stop Motors.


Step 3: Connecting Sensors


1- Line Following (IR Sensors)


To use the Robotic car as a line following robot, 3 IR Sensor are required to move the car along a black line surface (Black tape in our case) while detecting turns and curves along a path.


Those Sensors should be placed on the car lower chassis facing down towards the surface and leaving a distance of no more 20mm.


We need to make sure to align the three sensors with the chassis front side so that the middle sensor facing forward, left sensor about 45 degree to the left and right sensor about 45 to the right.

IR Sensors wiring to Arduino
IR Sensors wiring to Arduino

IR sensor has an LED that emits infrared lights and as you may know that black color absorbs lights, thus there is a phototransistor on the IR sensor module that receives the reflected light and sends signals to the microcontroller, but in case of the black light there will be no reflection of light from surface.


By placing a black thin tape on the surface and using the light’s reflection concept, we could find out if the car is aligned on the black line, and if not than the car should correct its position either to the right or to the left.

Illustration of line following concept using IR Sensors
Illustration of line following concept using IR Sensors


2- Autonomous Mode (Ultrasonic Sensor)


In autonomous mode, Ultrasonic sensor used to enable the car to move autonomously by scanning the surrounding and deciding which route should the car head to. Which is obviously the route with no obstacles then moving the car in that direction.

Ultrasonic Sensor Wiring to Arduino
Ultrasonic Sensor Wiring to Arduino

The Ultrasonic sensor should be fixed on a servo motor to swing the sensor back and forth while the sensor emits signals to measure distance in all directions.

The next step would be handled by the microcontroller (Arduino UNO) which will compute the distance in every direction and find the longest distance, and then moves the car towards that direction.

In other words, the movement sequence will be as follows:

  • Align the sensor to front direction by moving the servo motor to 90 degree

  • Move forward

  • Detect Obstacles and if detected, then

  • Stop the Car

  • Scan Surrounding

  • Compute the direction with longest distance reading

  • Rotate the car in the computed direction

  • Align the sensor to front direction by moving the servo motor to 90 degree

  • Move forward


3- IR Remote Control (IR Sensor)


Other way to control the car is using an IR receiver module and remote control with an IR Transmitter.


Basically, each button in the remote control will send a unique code to the receiver, then the receiver will send that code to the microcontroller (Arduino UNO).


For each code sent, Arduino will decide to the corresponding action to be taken, either to move the car in a certain direction, move servo motor, read distance, or any other possible action could be taken.

IR Receiver Module Wiring to Arduino
IR Receiver Module Wiring to Arduino


4- Bluetooth Control Mode (Bluetooth Module)


In Bluetooth Mode, we will pair the Bluetooth module on board with a mobile app, and through that app we’ll send codes that could be translated by the microcontroller and move the car accordingly.

Bluetooth Module HC-06 Wiring to Arduino
Bluetooth Module HC-06 Wiring to Arduino
Bluetooth Car Control Mobile App
Bluetooth Car Control Mobile App

Download the Bluetooth Car Control Mobile App (Android | IOS)


Video



Design



Code


/* This code is written by Eng. Mohammed AlMehaiza (Go Invent)
    This code was uploaded and tested on the Robotic Car kit as per the following
    video link: https://www.youtube.com/watch?v=-wUMs36Cf2M
    This code should enable user to communicate with the car using the IR Remote control, bluetooth via mobile apps
    And it should enabel the car to move autonomously.
    Any comments or inquiry please send via the contact form at (https://diylab.io)
    Thank you, have fun!
*/
#include<SoftwareSerial.h> // Including softSerial  header file
#include <IRremote.h>  // Including infrared remote header file     
#include <Servo.h>     // Including servo motor header file

// ------------------------- Pins Definition ------------------------------

// Pins assigned for the L298N motor driver control pins
#define IN1 10
#define IN2 9
#define IN3 8
#define IN4 7
#define EN1 11       // Should be PWM pin
#define EN2 6      // Should be PWM pin

#define echoPin 4   // pin number to Echo of the Ultrasonic Sensor
#define trigPin 3   // pin number to Trig of the Ultrasonic Sensor

#define servoPin 5  // Define servo control pin
int RECV_PIN = 2;   // IR Receiver pin

// ------------------------- Configurable Variables ------------------------------
int time_to_stop = 150;

String Forward_Bluetooth = "F";
String Reverse_Bluetooth = "B";
String Right_Bluetooth = "R";
String Left_Bluetooth = "L";
String Stop_Bluetooth = "S";

long Forward_IR = 16718055;
long Reverse_IR = 16726215;
long Left_IR = 16716015;
long Right_IR = 16734885;
long Autonomous_IR = 16761405;
long Bluetooth_IR = 16769565;
long Action_IR = 4294967295;  // This code is sent by the IR Remote after pressing and holding a button on the remote
long Move_Servo_Left_IR = 16754775;
long Move_Servo_Right_IR = 16769055;
long Move_Servo_90_IR = 16748655;

// ------------------------------------------------------------------------------

// Enumeration of differnt car movement actions
enum motion {
  Forward,  // 1
  Reverse,  // 2
  Left,     // 3
  Right,    // 4
  Stop      // 5
};

//Defining a softserial object to communication with the bluetooth module
SoftwareSerial mySerial(12, 13); // RX, TX  (Bluetooth module Rx to 13 and Tx to 12)
IRrecv irrecv(RECV_PIN);         // Define IR receiver object using the predefined pin (2)
decode_results results;          // Object to store the received code sent by the IR remote control
Servo myservo;                   // Define Servo object

motion dir;                      // Define a variable of the enumerated type (motion)
String data = "n";               // String variable to store the data sent via the bluetooth module

int pos = 90;                    // Variable to store the position of the servo (default is 90) to face the ultrasonic sensor front of the car
int old_pos = 0;                 // Variable to store the old positon of the servo
int heading_direction = 90;;     // Variable to decide in which direction and angle the car has to turn
float saved_pos = 90;            // Variable to store the heading servo postion

float ful_cycle = 1000;          // How long it will take the car to rotate 180 degree (Assumption is 1 second)
// using this variable we try to predict the angle of rotation by -> (full_cycle*heading_angle)/180
// This equation should convert the angle to interval so that the car will turn the correct angle
// to avoid collision with other obstacles.

int rotation = 1;                // Variable to change the servo motor rotation direction (1 = clockwise, -1 = counterclockwise)
boolean autonomous = false;      // Boolean variable to enable/disable autonomous mode
boolean bluetooth = false;       // Boolean variable to enable/disable bluetooth control mode
boolean move_servo = false;      // Boolean variable to enable/disable servo motor movement

long duration;                   // Duration of sound wave travel
float distance;                  // Distance from the obstacle
float max_distance = 0;          // Variable to store the maximum distance from obstacles
float safeDistance = 20.00;       // Safe distance to stop car before collision 
long currentmillis = 0;          // Store current millis()

void setup()
{
  // Serial.begin(9600);  ------> Enable this line to check the code sent by the IR Remote
  
  // Set the defined pins to OUTPUT/INPUT
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(EN1, OUTPUT);
  pinMode(EN2, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  // Initialize Motor control pins to LOW
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);

  // Change the motors speed (1023 = Maximum speed, 0 = stop)
  analogWrite(EN1, 1023);
  analogWrite(EN2, 1023);

  // Begin serial communication with the bluetooth module
  mySerial.begin(9600);

  // Attach the servo motor on the defined pin and move to initial position
  myservo.attach(servoPin);
  myservo.write(pos);

  // Enable IR receiver data communication
  irrecv.enableIRIn();
}

void loop()
{
  // For Autonomous mode
  if (autonomous) {
    delay(50);
    // Check if distance from objects ahead is less than the safe distance 
    if (check() <= safeDistance) {
      dir = Stop;
      movement(Stop);       // Stop the car
      movement(search());   // Search for the best and safe direction to turn car to then turn the car to that direction
      
      if (saved_pos > 90) saved_pos = saved_pos - 90;   // Return the corrsponding position between 0 to 90 if the position is more than 90
                                                        // So that the car could turn to the correct direction in relation with time delay.
        delay((ful_cycle * saved_pos) / 180);           // Calculate the correct delay in relation with the time required for 180 rotation
        distance = 200;                                 // Reset the distance to 200 to clear the Ultrasonic sensor readings
        dir = Forward;
        movement(dir);                                  // After the car turned to the correct position move the car forward
        delay(500);
        
        pos = 90;                                     
        myservo.write(pos);                             // Return the servo position again to 90 to let the Ultrasonic sensor face forward again
    }
    else
      dir = Forward;

    movement(dir);  

  }

  // For Bluetooth mode
  else if (bluetooth) {
    // If the bluetooth module received data
    if (mySerial.available())
    {
      
      data = mySerial.readStringUntil('\n');      // Check the received data
      data.trim();                                // Trim the string received to remove any spaces and unnecessary characters 

      // Check the character recevied and set the (dir) variable the corresponding direction
      if (data == Forward_Bluetooth) dir = Forward;
      else if (data == Reverse_Bluetooth) dir = Reverse;
      else if (data == Right_Bluetooth) dir = Right;
      else if (data == Left_Bluetooth) dir = Left;
      else if (data == Stop_Bluetooth) {
        dir = Stop;
        data = "n";
      }
      movement(dir);

    }

  }

  // For IR Remote mode
  while (irrecv.decode(&results) && data == "n") {
    //Serial.println(results.value);                ------> Enable this line to check the code sent by the IR Remote
    if (results.value == Forward_IR) dir = Forward;
    else if (results.value == Reverse_IR && !autonomous) dir = Reverse;
    else if (results.value == Left_IR && !autonomous) dir = Left;
    else if (results.value == Right_IR && !autonomous) dir = Right;
    else if (results.value == Autonomous_IR) {    // TO enable/disable autonomous mode
      autonomous = !autonomous;
      myservo.write(90);
    }
    else if (results.value == Bluetooth_IR) {   // TO enable/disable bluetooth mode
      dir = Stop;
      movement(dir);
      bluetooth = !bluetooth;
      myservo.write(90);
    }

    // Most of the actions are done by this if statement
    else if (results.value == Action_IR && !autonomous && !bluetooth) {   
      movement(dir);
      if (pos != old_pos && pos < 180 && pos > 0 && move_servo) {
        move_servo = false;
        myservo.write(pos);
        pos = pos + (rotation * 5);
      }
    }

    // Move servo left manually 
    else if (results.value == Move_Servo_Left_IR && !autonomous) {
      if (pos <= 175) {
        pos = pos + 5;
        rotation = 1;
        move_servo = true;
      }
    }

    // Move servo right manually
    else if (results.value == Move_Servo_Right_IR && !autonomous) {
      if (pos >= 5) {
        pos = pos - 5;
        rotation = -1;
        move_servo = true;
      }
    }

    // Center the servo to the middle
    else if (results.value == Move_Servo_90_IR && !autonomous) {
      pos = 90;
      old_pos = 0;
      rotation = 0;
    }

    // Clear the remaining codes from the IR Receiver data buffer
    irrecv.resume();
    
    currentmillis = millis();

  }

  // After certain time of no IR code is received stop the motors  
  if ( (millis() - currentmillis) > time_to_stop && dir != Stop && !autonomous && data == "n") {

    dir = Stop;
    movement(dir);
    old_pos = pos;
  }

}

// Function to check the distance of objects from the Ultrasonic sensor
float check() {
  // Ultrasonic
  // Clears the trigPin condition
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(2);
  // Sets the trigPin HIGH (ACTIVE) for 2 microseconds
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  // Serial.println(distance);
  return distance;
}

// Function to search for the maximum distance from the Ultrasonic sensor by moving 
// the servo to the right and left and testing the Distance from objects 
int search() {

  max_distance = 0;
  saved_pos = 90;

  for (pos; pos >= 0; pos--) {

    myservo.write(pos);
    delay(15);
    if (check() > max_distance) {
      max_distance = distance;
      saved_pos = pos;
    }

  }
  delay(500);
  for (pos = 0; pos <= 180; pos++) {

    myservo.write(pos);

    delay(15);
    if (check() > max_distance) {
      max_distance = distance;
      saved_pos = pos;        // Saved position of the maximum distance
    }
  }

  if (saved_pos > 90) dir = Left;
  else if (saved_pos < 90) dir = Right;

  for (pos; pos >= saved_pos; pos--) {

    myservo.write(pos);
    delay(15);
  }
  
  return dir;               // Return the direction of the maximum distance
}


// Function to move the motors in certain direction which a receiving a control parameter (1 -5)
void movement(int direction) {

  switch (direction)
  {
    case Forward:
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
      break;

    case Reverse:
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
      break;

    case Left:
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
      break;

    case Right:
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
      break;

    default:
      // Will stop the car;
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, LOW);
      break;
  }
}
308 views

Comments


bottom of page