The Ultrasonic Sensor

14
The Ultrasonic Sensor In my opinion, this is the coolest part about building this robot. It is here that we give our robot some very elementary autonomous capability with an ultrasonic distance sensor. This is an amazing little device that will quickly and accurately report the distance an object is away from out robot. With this we program our robot to have some basic collision avoidance. this sensor is sorta kinda like a little miniature radar. It works by emitting a sound pulse, and measuring how long it takes for the pulse to reflect back ( humans cannot hear the sound, hence the name ultrasonic). Velocity = distance / time ( i.e. mile per hour ). So then distance = velocity * time, the ultrasonic sensor will report the time it takes the pulse to reflect, we actually want half that amount, since the pulse going there and back is actually twice the distance to the object. Then we just need the velocity, which for us is the speed of sound in air.

description

In my opinion, this is the coolest part about building this robot. It is here that we give our robot some very elementary autonomous capability with an ultrasonic distance sensor. This is an amazing little device that will quickly and accurately report the distance an object is away from out robot. With this we program our robot to have some basic collision avoidance.

Transcript of The Ultrasonic Sensor

Page 1: The Ultrasonic Sensor

The Ultrasonic Sensor

In my opinion, this is the coolest part about building this robot. It is here that we give our robot

some very elementary autonomous capability with an ultrasonic distance sensor. This is an

amazing little device that will quickly and accurately report the distance an object is away from

out robot. With this we program our robot to have some basic collision avoidance.

this sensor is sorta kinda like a little miniature radar. It works by emitting a sound pulse, and

measuring how long it takes for the pulse to reflect back ( humans cannot hear the sound,

hence the name ultrasonic). Velocity = distance / time ( i.e. mile per hour ). So then distance =

velocity * time, the ultrasonic sensor will report the time it takes the pulse to reflect, we actually

want half that amount, since the pulse going there and back is actually twice the distance to the

object. Then we just need the velocity, which for us is the speed of sound in air.

Page 2: The Ultrasonic Sensor

To demonstrate this and get started with the sensor, lets hook up the sensor to the Arduino, and

write a simple program that displays the distance measured to the Serial Monitor. There are

three pins on the sensor, Vcc and Gnd, which supply power, and SIG . Connect the SIG pin to

port 11.

Page 3: The Ultrasonic Sensor

I found the following code online, you can find it, and a good description of it here.

const int pingPin = 11;

unsigned int duration, inches;

void setup() {

Serial.begin(9600);

}

void loop() {

Page 4: The Ultrasonic Sensor

pinMode(pingPin, OUTPUT); // Set pin to OUTPUT

digitalWrite(pingPin, LOW); // Ensure pin is low

delayMicroseconds(2);

digitalWrite(pingPin, HIGH); // Start ranging

delayMicroseconds(5); // with 5 microsecond burst

digitalWrite(pingPin, LOW); // End ranging

pinMode(pingPin, INPUT); // Set pin to INPUT

duration = pulseIn(pingPin, HIGH); // Read echo pulse

inches = duration / 74 / 2; // Convert to inches

Serial.println(inches); // Display result

delay(200); // Short delay

}

An very good explanation and example calculation is provided at the link I referenced for this

code. The key part is that the distance to the object in front of the sensor is equal to the time

reported divided by 74, divided by 2.

I got this to work simply using my hand.

Page 5: The Ultrasonic Sensor
Page 6: The Ultrasonic Sensor

There is an interesting little quirk about using the ultrasonic distance sensor, it sometimes won’t

work, and the way to get it to work is to disconnect and then reconnect the PWR wire, with the

others still connected. Put another way you should hook up the PWR wire last.

Now that we know how to use the ultrasonic sensor, lets incorporate it into our robot. All we

need to do for the hardware is connect 3 wires (PWR, GND, SIG) SIG is connected to port 11.

We also need to add some code to make use of the sensor. This is an area where we could get

pretty sophisticated trying to add Artificial Intelligence, and make our robot find its way around.

Lets keep it simple for now and just have tracky stop, backup, and turn left when an obstacle is

encountered. Here is the code to do it.

const int pingPin = 6;

// test for obstacle

int duration, inches=3;

pinMode(pingPin, OUTPUT); // Set pin to OUTPUT

digitalWrite(pingPin, LOW); // Ensure pin is low

delayMicroseconds(2);

digitalWrite(pingPin, HIGH); // Start ranging

delayMicroseconds(5); // with 5 microsecond burst

digitalWrite(pingPin, LOW); // End ranging

pinMode(pingPin, INPUT); // Set pin to INPUT

Page 7: The Ultrasonic Sensor

duration = pulseIn(pingPin, HIGH); // Read echo pulse

inches = duration / 74 / 2; // Convert to inches

Serial.println(inches); // Display result

delay(200); // Short delay

if( inches < 3 && inches > 0)

{

Serial.println("obstacle detected");

tracky.Stop();

tracky.DriveBackward();

delay(1000); // go backwards briefly

tracky.TurnLeft();

tracky.Stop();

tracky.DriveForward();

}

delay(200);

And finally here is the full code implementing both remote control and the ultrasonic sensor!

// adds second motor and 2 button control

#include <IRremote.h>

// pin assignments

const int pingPin = 6; // need to set these

const int RECV_PIN = 4;

const int directionPinA = 12;

const int directionPinB = 13;

const int motorPinA = 3;

const int motorPinB = 11;

const int brakePinA = 9;

const int brakePinB = 8;

// hex code assigned to a button press

const long forward_button = 0xFD807F; // uses 'VOL+' button

Page 8: The Ultrasonic Sensor

const long stop_button = 0xFDA05F; // uses 'Play' button

const long reverse_button = 0xFD906F; // uses 'VOL-' button

const long left_button = 0xFD20DF; // uses 'prev' button

const long right_button = 0xFD609F; // uses 'next' button

const long repeat = 0xFFFFFFFF;

// global vars

const int AFORWARD = LOW;

const int BFORWARD = HIGH;

IRrecv irrecv(RECV_PIN);

decode_results results;

long current_command = 0;

long previous_command = 0;

// speed is used globally for motion and steering

const int MAX_SPEED = 255; // use speed 255

// main class to represent our robot

class Robot

{

private:

int _lts; // left track speed

int _rts; // right track speed

int _ltd; // left track direction

int _rtd; // right track direction

void drive(int lts, int rts, int ltd, int rtd);

public:

Robot(int lts, int rts, int ltd, int rtd);

void Stop(); // engage both brakes

void DriveForward(); // both forward

void DriveBackward(); // both backward

void TurnLeft(); // opposite directions

void TurnRight(); // opposite directions

};

Page 9: The Ultrasonic Sensor

// create a new robot

Robot tracky(0, 0, AFORWARD, BFORWARD); // our robot is named tracky

void setup()

{

Serial.begin(9600);

irrecv.enableIRIn(); // Start the receiver

// setup channels A

pinMode(motorPinA, OUTPUT); //Initiates Motor Channel A pin

pinMode(brakePinA, OUTPUT); //Initiates Brake Channel A pin

// setup Channel B

pinMode(motorPinB, OUTPUT); //Initiates Motor Channel B pin

pinMode(brakePinB, OUTPUT); //Initiates Brake Channel B pin

digitalWrite(brakePinA, LOW); // disengage the Brake for channel A

digitalWrite(brakePinB, LOW); // disengage the brake for channel B

// setup ports for ultrasonic sensor

pinMode(pingPin, OUTPUT);

}

void loop()

{

// test for obstacle

int duration, inches=3;

pinMode(pingPin, OUTPUT); // Set pin to OUTPUT

digitalWrite(pingPin, LOW); // Ensure pin is low

delayMicroseconds(2);

digitalWrite(pingPin, HIGH); // Start ranging

delayMicroseconds(5); // with 5 microsecond burst

digitalWrite(pingPin, LOW); // End ranging

Page 10: The Ultrasonic Sensor

pinMode(pingPin, INPUT); // Set pin to INPUT

duration = pulseIn(pingPin, HIGH); // Read echo pulse

inches = duration / 74 / 2; // Convert to inches

Serial.println(inches); // Display result

delay(200); // Short delay

if( inches < 3 && inches > 0)

{

Serial.println("obstacle detected");

tracky.Stop();

tracky.DriveBackward();

delay(1000); // go backwards briefly

tracky.TurnLeft();

tracky.Stop();

tracky.DriveForward();

}

delay(200);

if (irrecv.decode(&results)) { // results is an instance of a

decode_results class, decode() returns an int

Serial.println(results.value, HEX);

if( results.value == repeat )

{

current_command = previous_command;

}

else

{

current_command = results.value;

previous_command = current_command;

}

// channel A is the left motor as viewed from a "driver"

viewpoint"

Page 11: The Ultrasonic Sensor

// channel B is the right motor as viewed from a "driver"

viewpoint"

switch (current_command)

{

//Serial.println("in switch statement");

case forward_button:

tracky.DriveForward();

break;

case stop_button:

tracky.Stop();

break;

case reverse_button:

tracky.DriveBackward();

break;

case left_button:

tracky.TurnLeft();

break;

case right_button:

tracky.TurnRight();

break;

}

irrecv.resume(); // Receive the next value

}

}

Robot::Robot(int lts, int rts, int ltd, int rtd)

{

_lts = lts;

_rts = rts;

_ltd = ltd;

_rtd = rtd;

}

void Robot::drive(int lts, int rts, int ltd, int rtd)

{

Page 12: The Ultrasonic Sensor

//Serial.println(lts);

digitalWrite(directionPinA, ltd); // Establishes direction of

Channel A

//digitalWrite(brakePinA, LOW); // Disengage the Brake for Channel

A

analogWrite(motorPinA, lts); // Spins the motor on Channel A

//Serial.println(rts);

digitalWrite(directionPinB, rtd); // Establishes direction of

Channel B

//digitalWrite(brakePinB, LOW); // Disengage the Brake for Channel

B

analogWrite(motorPinB, rts); // Spins the motor on Channel B at

full speed

}

void Robot::Stop()

{

//Serial.println("Stop");

//digitalWrite(brakePinA, HIGH); // engage the Brake for channel A

//digitalWrite(brakePinB, HIGH); // engage the brake for channel B

_lts = 0;

_rts = 0;

drive(_lts, _rts, _ltd, _rtd);

}

void Robot::DriveForward()

{

//Serial.println("Forward");

_lts = MAX_SPEED;

_rts = MAX_SPEED;

_ltd = AFORWARD;

_rtd = BFORWARD;

drive(_lts, _rts, _ltd, _rtd);

Page 13: The Ultrasonic Sensor

}

void Robot::DriveBackward()

{

//Serial.println("Backwards");

_lts = MAX_SPEED;

_rts = MAX_SPEED;

_ltd = !AFORWARD;

_rtd = !BFORWARD;

drive(_lts, _rts, _ltd, _rtd);

}

void Robot::TurnLeft()

{

//Serial.println("Turn Left");

Serial.println(_lts);

Serial.println(_rts);

// the robot does not have to be moving to turn, we will spin in

place

drive(MAX_SPEED, MAX_SPEED, !AFORWARD, BFORWARD); // drive the left

track in the opposite direction

delay(750);

drive(_lts, _rts, _ltd, _rtd); // resume whatever we were doing when

this function was called

}

void Robot::TurnRight()

{

//Serial.println("Turn Right");

// the robot does not have to be moving to turn, we will spin in

place

drive(MAX_SPEED, MAX_SPEED, AFORWARD, !BFORWARD); // drive the left

track in the opposite direction

delay(500);

Page 14: The Ultrasonic Sensor

drive(_lts, _rts, _ltd, _rtd); // resume whatever we were doing when

this function was called

}