Code issue with PING Sensor and while loop Heeelp!

Hey guys,

I have a robot with a PING Sensor and a Motor Shield from adafruit. At the moment, I am trying to get my robot to move forward until an object is located within a certain distance, and then move backward and turn right once an object is located within a certain distance.

With the code I have right now, my robot just moves forward into the object, and doesn't recognize that an object is in the way. My PING sensor is functional and works with other test code, so I know that is not the problem.

Here is what I have so far:

#include <AFMotor.h>

 
AF_DCMotor motor1(1, MOTOR12_8KHZ);
AF_DCMotor motor2(2, MOTOR12_8KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor1.setSpeed(200);     // set the speed to 200/255
  motor2.setSpeed(200);
  motor3.setSpeed(200);
  motor4.setSpeed(200);
}

void forward()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward()
{
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void haltMotors()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  
}

void turnRight()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);

void loop() {
  long duration, inches;
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
  
  while (inches > 5)  //while robot is 5 inches away from object
    {
     forward();
    }
  haltMotors();      //stop the motors before reversing direction
  while (inches < 10) //move robot back 10 inches before turning
   {
     backward();
    }
  turnRight();
}
long microsecondstoInches (long microseconds)
{
  return microseconds / 74 / 2;
}
while (inches > 5)  //while robot is 5 inches away from object
{
  forward();
}

That's the problem. You will always stay in that while loop because "inches" never gets the chance to be changed. You need to look for the distance in that while loop to.

Ditto for the other while loop, you must check the new distance some times :slight_smile:

JanD

Would I check the distance with an if-statement inside of the while loop?

Would I check the distance with an if-statement inside of the while loop?

No, you just read it - the check is performed by the "while".

Brennn10:
Would I check the distance with an if-statement inside of the while loop?

No, just update the distance reading while inside the while.

Lefty

So, inches = microsecondstoInches(duration); should go inside of the while loop?

Brennn10:
So, inches = microsecondstoInches(duration); should go inside of the while loop?

To obtain a new updated distance value inside your while statement you need to do both:

duration = pulseIn(pingPin, HIGH);
inches = microsecondstoInches(duration);

Lefty

Now the motors just seem to be randomly moving and twitching. Should all of the PING code go inside of the loop? Here is what I have at the moment.

#include <AFMotor.h>

 
AF_DCMotor motor1(1, MOTOR12_8KHZ);
AF_DCMotor motor2(2, MOTOR12_8KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor1.setSpeed(200);     // set the speed to 200/255
  motor2.setSpeed(200);
  motor3.setSpeed(200);
  motor4.setSpeed(200);
}

void forward()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward()
{
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void haltMotors()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  
}

void turnRight()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);

}
void loop() {
  const int pingPin = 19;
  long duration, inches;
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
  
  while (inches > 5)  //while robot is 5 inches away from object
    {
      duration = pulseIn(pingPin, HIGH);
      inches = microsecondstoInches(duration);
      forward();
    }
  haltMotors();      //stop the motors before reversing direction
  while (inches < 10) //move robot back 10 inches before turning
   {
     duration = pulseIn(pingPin, HIGH);
     inches = microsecondstoInches(duration);
     backward();
    }
  turnRight();
}
long microsecondstoInches (long microseconds)
{
  return microseconds / 74 / 2;
}

Should all of the PING code go inside of the loop?

Make life easy on yourself. Write a function that does the pinging, and returns a distance. Call that function when you need to know a distance.

Ok, so I created a function called, getDistance(). Here is what I have, but it is still not moving correctly. I hate to ask for answers, but I am unsure where I am going wrong.

#include <AFMotor.h>

 
AF_DCMotor motor1(1, MOTOR12_8KHZ);
AF_DCMotor motor2(2, MOTOR12_8KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor1.setSpeed(200);     // set the speed to 200/255
  motor2.setSpeed(200);
  motor3.setSpeed(200);
  motor4.setSpeed(200);
}

void forward()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward()
{
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void haltMotors()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  
}

void turnRight()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);

}
void loop() {
  long duration, inches;
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
  
  while (inches > 5)  //while robot is 5 inches away from object
    {
      getDistance();
      forward();
    }
  haltMotors();      //stop the motors before reversing direction
  while (inches < 10) //move robot back 10 inches before turning
   {
     getDistance();
     backward();
    }
  turnRight();
}
long microsecondstoInches (long microseconds)
{
  return microseconds / 74 / 2;
}
float getDistance()
{
  long duration, inches;
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
}
  while (inches > 5)  //while robot is 5 inches away from object
    {
      getDistance();

Perhaps if you actually returned a value in getDistance, and stored the value returned by getDistance in inches...

Should the getDistance function hold the parameter 'inches'? How do I fix this problem?

The getDistance function is defined to return a float. There needs to, then, be a return statement, with the value to return. Since, presumably, the value to return is the distance in inches, and inches is a local variable, of type long, it is strange that getDistance()'s return type is not long.

Alright, so I changed float getDistance(), to long getDistance(). I also added a return statement, to return the duration and the inches. But it is still having problems.

#include <AFMotor.h>

 
AF_DCMotor motor1(1, MOTOR12_8KHZ);
AF_DCMotor motor2(2, MOTOR12_8KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;


void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor1.setSpeed(200);     // set the speed to 200/255
  motor2.setSpeed(200);
  motor3.setSpeed(200);
  motor4.setSpeed(200);
}

void forward()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward()
{
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void haltMotors()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  
}

void turnRight()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);

}
void loop() {
  long duration, inches;
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
  
  while (inches > 5)  //while robot is 5 inches away from object
    {
      getDistance();
      forward();
    }
  haltMotors();      //stop the motors before reversing direction
  while (inches < 10) //move robot back 10 inches before turning
   {
     getDistance();
     backward();
    }
  turnRight();
}
long microsecondstoInches (long microseconds)
{
  return microseconds / 74 / 2;
}
float getDistance()
{
  long duration, inches;
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  
  inches = microsecondstoInches(duration);
}

I get an error that says inches was not declared in the scope, and the first while loop was highlighted.

Change "getDistance();" inside the while loops to "inches = getDistance();" and add "return inches;" at the end of the getDistance() function. Also, I would change all places where you define "inches" as long so that it defines "inches" as float.

JanD