Go Down

Topic: Parallax Ping with Arduino Uno (Read 1 time) previous topic - next topic

ebun91

Hey guys. I'm new to robotics and this is going to be my first robot. I am trying to make an obstacle avoiding robot, and as the title suggests, am using the parallax ping ultrasonic rangefinder. I get how to connect it, but what i don't get is how to read the data I receive. How would I set up a code for  the sensor? I don't get what I am supposed to do, and am utterly stuck.

This somewhere along the lines of what I want to do.
Like if the sensor senses something closer than 5 inches, pin 7 voltage go low or something like that.

You don't have to write a code, but can anyone out there show me and example of how I would set it up and what if statements I would give? Thank you very much and please reply asap!!!

JasonK

http://tronixstuff.wordpress.com/2011/11/28/tutorial-parallax-ping-ultrasonic-sensor/

http://www.arduino.cc/playground/Main/UltrasonicSensor

ebun91

#2
Feb 03, 2012, 03:03 am Last Edit: Feb 03, 2012, 03:45 am by ebun91 Reason: 1
Thanks I like that. But now if I want to do something like if blablabla is the distance then do blablabla, how do I do that? What do I do for the if?

if ("distance" <= 2cm)
digitalWrite(ledPin, LOW)

something like that. thanks!

rwagg

#3
Feb 04, 2012, 07:04 am Last Edit: Feb 04, 2012, 07:06 am by rwagg Reason: 1
I'm doing something similar and have had success with the Ping class here.  
http://arduino.cc/playground/Code/Ping

I create a PING object and it lets me encapsulate all of the effort around getting distance.  I also added an additional method, getInches() that fires the PING and returns the distance... That way it's only one call.

double Ping::getInches()
{
// This function will fire the ping and then return the distance all in one call.

  this->fire();
  return this->inches();
}

I have one PING sensor mounted on a servo in the front of my bot.  The servo constantly pans the PING left (135 deg), center (90 deg) , right(45 deg), and back to center (90 deg) watching for obstacles.  I put the whole scanning action in an interrupt driven timer so it's constantly gathering data, my code just watches the distances posted in the array and takes action when I need to avoid something.

Here's some of my distance testing code...  dDistance is my array of the three distances LEFT, MIDDLE, and RIGHT.  TOOCLOSE is what I've defined as too close to an obstacle.  Once I come within the TOOCLOSE distance (for center 90 deg), or 1/2 of TOOCLOSE for the side angles (135 deg, or 45 deg) then I take action to turn away from the obstacle.  I define TOOCLOSE as 16".

 // If we are going to rub up against something, let's adjust our movement
 if ((dDistance[LOOKLEFT]   < (double)(TOOCLOSE/2)) &&
     (dDistance[LOOKMIDDLE] > (double)TOOCLOSE))
 {
   // We are getting too close on the left, so let's move right
   turnQuarterRight();
   bTurned = true;
 }
 
 // If we are going to rub up against something on the right, let's agjust.
 if ((dDistance[LOOKRIGHT]  < (double)(TOOCLOSE/2)) &&
     (dDistance[LOOKMIDDLE] > (double)TOOCLOSE))
 {
   turnQuarterLeft();
   bTurned = true;
 }


I also check for what I call "STOPCLOSE" so that if the bot is too close (4" for me), then it doesn't have time to turn away, or my hand is in front of the sensor.  Either condition makes the bot just stop.

 if (((dDistance[LOOKMIDDLE] < (double) STOPCLOSE) && dDistance[LOOKMIDDLE] > 0.1))
 {

I check to ensure my distance > 0.1 because sometimes the PING sensor returns a zero.  Instead of fighting with the random zeros, I put this check in to make sure I'm a real distance from an obstacle.  

Below is my scan code [scanAhead()].  Since I'm using Timer based on interrupts, my ISR needs to be on the "quicker side", so I take my distance reading and then move the servo to the next position making it ready to take a measurement the next time the ISR is called.

I use iScanPos to track the servo's angle and position in the array.  I've included it and my iDegrees array below, both are referenced in my scanAhead code below.  
const int iArrayPointer[12]       = {0,1,2,1,0,1,2,1,0,1,2,1};
const int iDegrees[]  = {135, 90, 45};

//scanAhead is my ISR

void scanAhead()
{
//  
// const int iArrayPointer[12]       = {0,1,2,1,0,1,2,1,0,1,2,1};

 dDistance[iArrayPointer[iScanPos]] = pingSensor.getInches();
 
 // Just in case we get a zero, let's try again and take what we get
 if (dDistance[iArrayPointer[iScanPos]] == 0)
 {
     dDistance[iArrayPointer[iScanPos]] = pingSensor.getInches();
 }
 iScanPos++;
 if (iScanPos >= iArrayPointerLen)
 {
   iScanPos = 0;
 }

 pingServo.write(iDegrees[iArrayPointer[iScanPos]]);

 bDisplayed = false;    // This is a global variable that is checked showDiags()
                        //to make sure we only print the distances when there is actually a change
 checkStopClose();
}


The last line, pingServer.write(...)  is where I move my servo controlling my PING sensor.  I then return from the ISR and count on the fact that the servo will complete the movement to the next stop before the ISR gets called again.  This way I don't have to code delays() to wait on the servo sensor to move.  I've found that anytime I code a delay(), I end up running into something before I can get another reading.  

I setup my ISR as one of the last things I do in setup().  I use the class Timer3 as my timer.  He's how I defined it in setup()

 Timer3.initialize(500);
 Timer3.attachInterrupt(scanAhead);

One last thing I learned, once I make a turn, my distances are now "out of whack" which is why I set the variable bTurned = true.  After my turn is complete, I run through this code:
 if (bTurned)
 {
   stopRobot();
   delay(1500);      // get our new bearings.
   bTurned = false;
 }

It stops the bot and waits 1 1/2 seconds.  This gives the bot time to do three scans and gather current distances before it starts driving again.
My goal was to keep the bot moving as much as possible, but this is one time when I just needed to stop the bot and look around.



HTH...

irbia

Hello,

I would like to ask a question I hope you guys could help me out in it. I am using an Ultra Sonic Sensor to monitor the the distance of an obstacle. So I want to take the first reading/output from the sensor and keep comparing it with the present reading and show the difference in the serial monitor.

I would be waiting for your response. Your help is highly appreciated

Regards

Cactusface

Hi All,
            I can't count how many times this as been ask of late. So for them that need to know I will post my full code for my last bot, no I'm doing you any favours!! because you will learn nothing!! But might get your bot into action sooner, then perhaps you can alter the code and the timing in there.

You will I'm sure need to alter all the motor pin numbers also the U/S etc.

My code, my bot uses a home made PCB with a DVR8833 driver.

Code: [Select]
/*
 ;*******************************
 ;    Filename:        DoubleRound
 ;    Date:        12/08/2013
 ;    File Version:    Ex ZumoNanoLCD
 ;    Written by :     Mel Saunders
 ;    Function:        DR-BuggyDrive
 ;    Last Revision:   18/09/2014
 ;    Target           Uno/Nano Double Round chassis, etc.
 ; *******************************
 
 This program demonstrates the use of a TI DRV8833 dual H bridge (Module).
 This can run 2x DC motors control their speed and direction.
 Also uses a U/S Detecter, etc.
 */
//#include <FastIO.h>
//#include <I2CIO.h>
//#include <LiquidCrystal_I2C.h>
//#include <Wire.h>
//LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE);  // Set the LCD I2C address 

// Define constants and varibles
const int LMpos=6,LMneg=8,RMneg=7,RMpos=9;  //Motor pins
int distance,cm,FRQ,TD,A,B,MotorTime,switches,action,Lspeed,Rspeed,Tilt;
long int randNumber,motorSpeed,TwirlTime;
float unit,val,bv,factor;
boolean go;

void setup()
{
// lcd.begin(16,2);
// battCheck();
// lcd.clear();
// lcd.setCursor(2,0);
// lcd.print("I am Waiting");
delay(1000);
// lcd.setCursor(3,1);
// lcd.print("Wave me off");
pinMode(LMpos, OUTPUT);      // sets the digital pin as output     
pinMode(LMneg, OUTPUT);      // sets the digital pin as output
pinMode(RMneg, OUTPUT);      // sets the digital pin as output     
pinMode(RMpos, OUTPUT);      // sets the digital pin as output
go = true;
Lspeed=200;
Rspeed=200;
}

// * * * start of Main program * * * *

void loop()
{
if (go == true)
{
distance=scanner(cm);
do
{
distance=scanner(cm);
delay(200);
sound(1800,6);
delay(200);
}
while(distance > 25);

// lcd.clear();
// lcd.setCursor(2,0);
// lcd.print("Here we GO!");

Startup();
}
// If go=false, start here.

distance=scanner(cm);
if(distance <=18)
{
Radar();
}
distance=scanner(cm);
if(distance >10)

{
analogWrite(LMpos,Lspeed);       //Left motor forward
digitalWrite(LMneg,LOW);
digitalWrite(RMpos,LOW);         //Right motor forward
analogWrite(RMneg,Rspeed);
// lcd.clear();
// lcd.print("   Forward go!");
randomSeed(millis());
MotorTime = random(450,750);     // Speed for turning, reverese, etc.

go = false;
}// end Main loop


//------------------------------------------------------------------
void Startup()
{

for(int i=0; i <= 220; i++)  //Slow start, ramp up speed
{
analogWrite(LMpos,i);        //Left motor forward.
digitalWrite(LMneg,LOW);
digitalWrite(RMpos,LOW);     
analogWrite(RMneg,i);     //Right motor forward, +25 to compensate for slower motor!!
delay(30);
}
go = false;
}

//-----------------------------------------------------------------
void Halt()//Both motors STOP
{
digitalWrite(LMpos,LOW);           
digitalWrite(LMneg,LOW);
digitalWrite(RMpos,LOW);     
digitalWrite(RMneg,LOW);
delay(300);
}
//------------------------------------------------------------------
void Rturn()//Turn right
{
digitalWrite(LMpos,LOW);       //Left motor forward
analogWrite(LMneg,180);
digitalWrite(RMpos,LOW);       //Right motor reverse
analogWrite(RMneg,180);
delay(200);
}

//------------------------------------------------------------------
void Lturn()//Turn left
{

analogWrite(LMpos,180);       //Left motor reverse
digitalWrite(LMneg,LOW);
analogWrite(RMpos,180);       //Right motor forward
digitalWrite(RMneg,LOW);
delay(450);
}

//------------------------------------------------------------------
void Forward()//forward
{
analogWrite(LMpos,Lspeed);       //Left motor forward
digitalWrite(LMneg,LOW);
digitalWrite(RMpos,LOW);       //Right motor forward
analogWrite(RMneg,Rspeed);
}

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

int  Back(int TD)//Reverse
{
digitalWrite(LMpos,LOW);       //Left motor reverse
digitalWrite(LMneg,HIGH);
digitalWrite(RMpos,HIGH);      //Right motor reverse
digitalWrite(RMneg,LOW);
delay(TD);
}
//------------------------------------------------------------------
void BackOff()                  //back off!
{
battCheck();
// lcd.clear();
// lcd.print("   Back off   ");
int speed=190;               //Reversinig, so larger numbers = slower speed??
{
     for(int i=0; i <= 5; i++)
        {
        sound(1500,20);
        delay(100);
        }
analogWrite(LMpos,speed);       //Left motor reverse
digitalWrite(LMneg,HIGH);
digitalWrite(RMpos,HIGH);      //Right motor reverse
analogWrite(RMneg,speed);
        delay(3000);
       
        }
  }
//------------------------------------------------------------------
void sound(int FRQ,int TD)
{
tone(13,FRQ,TD);
}
//------------------------------------------------------------------
long scanner(long cm)
{
const int pingPin=2, EchoPin=3;
long duration;

// The SRF005 is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse before to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
pinMode(EchoPin, INPUT); 

digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(2);
digitalWrite(pingPin, LOW);
duration = pulseIn(EchoPin, HIGH);
delay(100);

// convert the time into a distance
// inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
return (cm);
}
//------------------------------------------------------------------
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
//------------------------------------------------------------------

void Radar()
{
Halt();
BackOff();
Lturn();
sound(2200,20);
Halt();
A=scanner(cm);
delay(100);
Rturn();
Rturn();
sound(2200,20);
Halt();
B=scanner(cm);
delay(100);
Lturn();
delay(50);

if (A>B)
{
Lturn();  //Then turn left
A=0;
}
else 
{
Rturn();  //Then turn right
B = 0;
}
}
//------------------------------------------------------------------ 
void Twirl()
{
action=MotorTime & 0000000000000001;
if(action==1)

// Left twirl
{
digitalWrite(LMpos,LOW);       //Left motor reverse
digitalWrite(LMneg,HIGH);
digitalWrite(RMpos,LOW);      //Right motor forward
digitalWrite(RMneg,HIGH);
delay(TwirlTime);
}
else
// Right twirl
{
digitalWrite(LMpos,HIGH);       //Left motor forward
digitalWrite(LMneg,LOW);
digitalWrite(RMpos,HIGH);       //Right motor reverse
digitalWrite(RMneg,LOW);
delay(TwirlTime);
}
}
void battCheck()
{
unit=0.00488;                  //4.88mV per analoge step
val=analogRead(A2);            //Analogue value
bv=(unit*val)*2;
// lcd.clear();
// lcd.setCursor(1,0);
// lcd.print("Battery Status");
val=bv;
if(val>4.80)
{
// lcd.setCursor(1,1);
// lcd.print(val);
// lcd.print(" V+ -Full");
delay(2000);
factor=1;
}
if(val<=4.80)
{
// lcd.setCursor(1,1);
// lcd.print(val);
// lcd.print(" V -Good");
delay(1000);
factor=1.2;
}
if (val <4.50 and val>4.0)
{
// lcd.setCursor(1,1);
// lcd.print(val);
// lcd.print(" V -OK ?");
delay(1000);
factor=1.4;
}
if (val <4.0 and val>3.70)
{
// lcd.setCursor(1,1);
// lcd.print(val);
// lcd.print(" V -Low");
delay(1000);
factor=1.6;

if (val <3.70)
{
// lcd.setCursor(0,1);
// lcd.print(val);
// lcd.print(" V -Recharge!");
delay(3000);



}



Hope it helps. I too have been deperate for an answer.

Regards

Mel.
Open your mind! But not too far, your brains might fall out.
Also like Photography, model building and my 300+ Cacti and Succs.

Go Up