Arduino obstacle avoiding car

Arduino based self-driving car was just another thing on my mind. This project will give you basic understanding of robotic rovers. You can mount whatever you want on this car (what it can carry) and can perform wide range of task such as mount a camera for surveillance but you need to make a few changes add a Bluetooth receiver and control it with you phone. Its capabilities are limited by your imagination, if you can imagine something else you can achieve that.

This car uses an ultrasonic sensor to detect objects in its path and then changes direction towards a direction which has more open scope.

Components used:

  1. Robotic car kit: Chassis for mounting boards, motors, and other stuff. Two wheels and two motors, screw.
  2. Arduino board
  3. Motor driving shield for Arduino
  4. Servo motor 9G tower pro
  5. Utrasonic sensor HC-SR04:
  6. Battries AA 4
  7. Battrey holder
  8. On-Off switch
  9. Programming cable
  10. Screw driver

Components used:

Utrasonic sensor HC-SR04: The HC-SR04 Ultrasonic Sensor is a very affordable proximity/distance sensor that has been used mainly for object avoidance in various robotics projects. It essentially gives your Arduino eyes / special awareness and can prevent your robot from crashing or falling off a table. It has also been used in turret applications, water level sensing, and even as a parking sensor. This simple project will use the HC-SR04 sensor with an Arduino and a Processing sketch to provide a neat little interactive display on your computer screen.

Specification:

Working Voltage: DC 5V

Working Current: 15mA

Working Frequency: 40Hz

Max Range: 4m

Min Range: 2cm

Measuring Angle: 15 degree

Trigger Input Signal: 10μS TTL pulse

Echo Output Signal Input TTL lever signal and the range in proportion

Size: 46*20.4mm

Weight: 9g

Servomotor : Servomotor is a position control rotary actuator. It mainly consists of housing, circuit board, core-less motor, gear and position sensor. The receiver or MCU outputs a signal to the servomotor. The motor has a built-in reference circuit that gives out reference signal, cycle of 20ms and width of 1.5ms. The motor compares the acquired DC bias voltage to the voltage of the potentiometer and outputs a voltage difference. The IC on the circuit board will decide the rotate direction accordingly and drive the core-less motor. The gear then pass the force to the shaft. The sensor will determine if it has reached the commanded position according to the feedback signal. Servomotors are used in control systems that requires to have and maintain different angles. When the motor speed is definite, the gear will cause the potentiometer to rotate. When the voltage difference reduces to zero, the motor stops. Normally, the rotation angle range is among 0-180 degrees.

Servomotor comes with many specifications. But all of them have three connection wires, distinguished by brown, red, orange colours (different brand may have different colour). Brown one is for GND, red one for power positive, orange one for signal line.

Motor Driving Shield: The Arduino Motor Shield is based on the L298 (datasheet), which is a dual full-bridge driver designed todrive inductive loads such as relays, solenoids, DC and stepping motors. It lets you drive two DC motors with your Arduino board, controlling the speed and direction of each one independently.

IMAG1125

Assembling the car kit:

  1. Mounting front wheel on chassis:
    1. Connect the spacer on wheel body as shown in image below:
  1. Repeat above step for rest of the holes, mounted spaces will look like as shown in image below:

IMAG1130

  1. Screw in the spacers on chassis body as shown in the figure below
  2. Repeat above step for rest of the spacers,chasis mounted wheel will look as shown in the figure below:
  1. Mounting drive wheels with motors:
    1. Insert the motor drive gear into the socket provided on the wheel rim, motor and connected will look as shown in the figure below:
  1. Repeat above step for second motor wheel pair. Now, you are ready to mount the motors on the chasis.

IMAG1135

  1. Aluminium socket connected with motor have holes for mounting it with the chassis screw in the motor as shown in the figure below.

IMAG1136

  1. Mount the battery holder using double sided tape.

IMAG1127

Mounting the board:

Mount motor driver shield over Arduino as shown in figure below:

Add some insulating material over the screws on chassis so that they don’t touch the board. Or mount your board in such a way that it does not touch any of the screws.

IMAG1142

Once mounted connect the motor wires with the shield as shown in the following figure:

IMAG1144

Mounting the servo:

I have used a double sided tape and cardboard piece and placed it on the chassis as shown on the figure below:

IMAG1145

Slide in the servo motor into the grove on card board as shown below:

Connect the servo on motor driving shield servo slots:

Mounting ultrasonic sensor on Servo motor:

For this I have used card board and created following ultrasonic sensor holder following images show this:

Mount the ultrasonic sensor holder on servo motor gear as shown below:

Connecting the ultrasonic sensor on Arduino:

  1. Connect VCC pin of ultrasonic sensor with +5v on motor driver shield or Arduino board
  2. Connect GND pin of ultrasonic sensor with GND on motor driver shield or Arduino board
  3. Connect Echo pin of ultrasonic sensor with on digital 48 of Arduino
  4. Connect Trig pin of ultrasonic sensor with on digital 50 of Arduino
  5. Make sure wire are long enough for the movement of ultrasonic sensor mounted on servo, as the sensor will move left and right to scan for open spaces.

Circuit diagram:

circuit_diagram

Fully assembled:

The Software:

#include

//   Connector X1:

//     M1 on outside = MOTOR1_A   (+) north

//     M1 on inside  = MOTOR1_B   (-)

//     middle        = GND

//     M2 on inside  = MOTOR2_A   (+)

//     M2 on outside = MOTOR2_B   (-) south

//

//   Connector X2:

//     M3 on outside = MOTOR3_B   (-) south

//     M3 on inside  = MOTOR3_A   (+)

//     middle        = GND

//     M4 on inside  = MOTOR4_B   (-)

//     M4 on outside = MOTOR4_A   (+) north

//

//

//         ——————————-

//         | -+s                         |

//         | -+s                         |

//    M1 A |                             | M4 A

//    M1 B |                             | M4 B

//    GND  |                             | GND

//    M2 A |                             | M3 A

//    M2 B |                             | M3 B

//         |                       ….. |

//         ——————————-

//                + –

// Arduino pins for the shift register

#define MOTORLATCH 12

#define MOTORCLK 4

#define MOTORENABLE 7

#define MOTORDATA 8

// 8-bit bus after the 74HC595 shift register

// (not Arduino pins)

// These are used to set the direction of the bridge driver.

#define MOTOR1_A 2

#define MOTOR1_B 3

#define MOTOR2_A 1

#define MOTOR2_B 4

#define MOTOR3_A 5

#define MOTOR3_B 7

#define MOTOR4_A 0

#define MOTOR4_B 6

// Arduino pins for the PWM signals.

#define MOTOR1_PWM 11

#define MOTOR2_PWM 3

#define MOTOR3_PWM 6

#define MOTOR4_PWM 5

#define SERVO1_PWM 10

#define SERVO2_PWM 9

// Codes for the motor function.

#define FORWARD 1

#define BACKWARD 2

#define BRAKE 3

#define RELEASE 4

// Declare classes for Servo connectors of the MotorShield.

VarSpeedServo myservo;

int HIGH_SPEED = 255;

int LOW_SPEED = 128;

//Ultrasonice sensor

#define echoPin 48 // Echo Pin

#define trigPin 50 // Trigger Pin

#define LEDPin 13 // Onboard LED

int maximumRange = 200; // Maximum range needed

int minimumRange = 0; // Minimum range needed

long duration, distance; // Duration used to calculate distance

void setup()

{

Serial.begin(9600);

Serial.println(“Simple Motor Shield sketch”);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

pinMode(LEDPin, OUTPUT);

myservo.attach(SERVO1_PWM);

myservo.write(90, 50, true);

}

void loop()

{

// Suppose a DC motor is connected to M1_A(+) and M1_B(-)

// Let it run full speed forward and half speed backward.

// If ‘BRAKE’ or ‘RELEASE’ is used, the ‘speed’ parameter

// is ignored.

long objectDistance = getDistanceFromObject();

if (objectDistance >= maximumRange || objectDistance <= minimumRange){

/* Send a negative number to computer and Turn LED ON

to indicate “out of range” */

//Serial.println(“-1”);

motor(3, FORWARD, HIGH_SPEED);

motor(4, FORWARD, HIGH_SPEED);

//digitalWrite(LEDPin, HIGH);

}else {

motor(3, FORWARD, HIGH_SPEED);

motor(4, FORWARD, HIGH_SPEED);

/* Send the distance to the computer using Serial protocol, and

turn LED OFF to indicate successful reading. */

//descide here which way to go

if(objectDistance = maximumRange || leftDistance = maximumRange || rightDistance <= minimumRange){

isRightValid = false;

rightDistance = -1;

Serial.print(“Right “);

Serial.println(rightDistance);

}else{

isRightValid = true;

Serial.print(“Right “);

Serial.println(rightDistance);

}

if(isLeftValid && isRightValid){

if(leftDistance rightDistance){

// go left

Serial.print(“2. Go left”);

Serial.print(” “);

Serial.print(leftDistance);

Serial.print(” : right “);

Serial.println(rightDistance);

//reset servo

myservo.write(90, 50, true);

motor(3, BACKWARD, HIGH_SPEED);

motor(4, FORWARD, HIGH_SPEED);

delay(250);

motor(3, RELEASE, 0);

motor(4, RELEASE, 0);

delay(250);

}

}else if(isLeftValid && !isRightValid){

// go left

Serial.print(“3. Go left”);

Serial.print(” “);

Serial.print(leftDistance);

Serial.print(” : right “);

Serial.println(rightDistance);

//reset servo

myservo.write(90, 50, true);

motor(3, BACKWARD, HIGH_SPEED);

motor(4, FORWARD, HIGH_SPEED);

delay(250);

motor(3, RELEASE, 0);

motor(4, RELEASE, 0);

delay(250);

}else if(!isLeftValid && isRightValid){

// go right

Serial.print(“4. Go right”);

Serial.print(” “);

Serial.print(rightDistance);

Serial.print(” : left “);

Serial.println(leftDistance);

//reset servo

myservo.write(90, 50, true);

motor(3, FORWARD, HIGH_SPEED);

motor(4, BACKWARD, HIGH_SPEED);

delay(250);

motor(3, RELEASE, 0);

motor(4, RELEASE, 0);

delay(250);

}

}

}

}

// ———————————

// motor

//

// Select the motor (1-4), the command,

// and the speed (0-255).

// The commands are: FORWARD, BACKWARD, BRAKE, RELEASE.

//

void motor(int nMotor, int command, int speed)

{

int motorA, motorB;

if (nMotor >= 1 && nMotor = 0 && speed <= 255)

{

analogWrite(motorPWM, speed);

}

}

}

// ———————————

// shiftWrite

// The parameters are just like digitalWrite().

// The output is the pin 0…7 (the pin behind

// the shift register).

// The second parameter is HIGH or LOW.

// There is no initialization function.

// Initialization is automatically done at the first

// time it is used.

void shiftWrite(int output, int high_low)

{

static int latch_copy;

static int shift_register_initialized = false;

// Do the initialization on the fly,

// at the first time it is used.

if (!shift_register_initialized)

{

// Set pins for shift register to output

pinMode(MOTORLATCH, OUTPUT);

pinMode(MOTORENABLE, OUTPUT);

pinMode(MOTORDATA, OUTPUT);

pinMode(MOTORCLK, OUTPUT);

// Set pins for shift register to default value (low);

digitalWrite(MOTORDATA, LOW);

digitalWrite(MOTORLATCH, LOW);

digitalWrite(MOTORCLK, LOW);

// Enable the shift register, set Enable pin Low.

digitalWrite(MOTORENABLE, LOW);

// start with all outputs (of the shift register) low

latch_copy = 0;

shift_register_initialized = true;

}

// The defines HIGH and LOW are 1 and 0.

// So this is valid.

bitWrite(latch_copy, output, high_low);

// Use the default Arduino ‘shiftOut()’ function to

// shift the bits with the MOTORCLK as clock pulse.

// The 74HC595 shiftregister wants the MSB first.

// After that, generate a latch pulse with MOTORLATCH.

shiftOut(MOTORDATA, MOTORCLK, MSBFIRST, latch_copy);

delayMicroseconds(5);    // For safety, not really needed.

digitalWrite(MOTORLATCH, HIGH);

delayMicroseconds(5);    // For safety, not really needed.

digitalWrite(MOTORLATCH, LOW);

}

long lookLeft(void){

myservo.write(0, 50, true);

//give sensor some time to read values

//delay(1000);

long objectDistance = getDistanceFromObject();

return objectDistance;

}

long lookRight(void){

myservo.write(180, 50, true);

//give sensor some time to read values

//delay(1000);

long objectDistance = getDistanceFromObject();

return objectDistance;

}

// calculate the distance from object when moving straight

long getDistanceFromObject(){

//read input from ultrasonic sensor

long objDistance, duration;

digitalWrite(trigPin, LOW);

delayMicroseconds(2);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

//Calculate the distance (in cm) based on the speed of sound.

objDistance = duration/58.2;

return objDistance;

}

The logic behind this cars functioning is that the ultrasonic sensor is continuously detecting distance from any obstacle in front of the car. When the distance is less than specified threshold then servo motor checks left and right side of the car and in whichever direction it finds more open space it turns the car into that direction by rotation both the wheels in opposite direction.

Although, in robotics you can turn a wheeled robot either by rotating one wheel and using the other wheel as pivot. Other approach which I am using is to move both the wheels in opposite direction. The benefit of the later one is that the turning speed increases allowing your robot to change direction quickly. You can catch the robot live in action on youtube.

In next article on this series I will try to integrate Bluetooth and control the car using my Android phone.

Advertisements

2 thoughts on “Arduino obstacle avoiding car

  1. Pingback: Carduino: Control Arduino Car From Android Phone | I <3 Technology

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s