UltraSonic Sensor Problems

Hello Arduino Forum,

I am building a robot, that, among other things, should stop when there is something in front of it. I am planning on having 4 motors, but as of yet only have 1 DC motor hooked up to a Leonardo through the Arduino motor shield. I have also attached a parallax PING))) ultrasonic sensor to pin 7. I have written the code so the motor should go, until something is less than 5 inches away from it. Simple right. Apparently not. The motor just moves, no matter what happens, or how close I put something to the ultrasonic sensor. The sensor flashes every 5 or so seconds, not rapidly like it did when I tried the Arduino example code.

/*******************************\

(c) ma7730 2015
code to move motor until obstacle

\*******************************/
 



float inches;
float duration;  
const int pingPin = 7;        //ultrasonic sensor on pin 7
const int distance = 5;       // closest it can be


float detectObject(){
  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;  
   return inches;                //return distance to nearest object in inches
}


void moveForward(){
 
  //forward @ full speed
  digitalWrite(12, HIGH); //establishes forward direction
  digitalWrite(9, LOW);   //disengage the brake
  analogWrite(3, 255);   //spins the motor at full speed
  
  delay(3000);

}

void stopMotor(){
  
  digitalWrite(9, HIGH); //brake
  
}


void setup(){
  
  pinMode(12, OUTPUT); //initiates motor as output
  pinMode(9, OUTPUT); //initiates brake as output
 
  
}


void loop(){
  
  moveForward();     //move forward
  detectObject();     //look for obstacle
  if(detectObject() < distance) stopMotor();      //if there is something less than 5 inches away, stop
  else moveForward;                                //otherwise, keep moving
    
  
  

  
}

I think it nevers gets to the part where it is supposed to sense for an object, because if I remove the moveForward(); in the void loop, the motor doesn't move no matter what. Maybe I am missing something obvious, but I have been working on this forever and can't seem to figure out what the problem is. :cold_sweat:

Thanks,

ma7730

Hi,
You have 3second delays in your sketch, the program stops for 3seconds when it ancounters this statement.

Check out in the IDE examples, Blink Without Delay.

It shows how to delay an event, but still have the sketch running to service the other instructions.

Tom... :slight_smile:

Why does detectObject() return a global variable? Why is duration a float? Are you expecting to measure 3.7 microseconds? The pulseIn() function returns an unsigned long.

  detectObject();     //look for obstacle
  if(detectObject() < distance) stopMotor();      //if there is something less than 5 inches away, stop

Why do you call the function twice? The first time is useless.

  else moveForward;                                //otherwise, keep moving

That might as well be:

  else 47;

for all the good it is doing.

@TomGeorge - Thank you for your quick reply! I deleted the delay in the moveForward() functions, but, there is no difference whatsoever. Also, the delayMicroseconds in the detectObject() function are the exact same as those in the example, so why should that be a problem?

@PaulS - I changed the type of detectObject(), inches, and duration from an int to a long, and nothing changed. The function returns a global variable so that I can use that to evaluate if the motor should stop.

I am a little confused as to what you are saying in the second part of your post. I first look for an obstacle. If there is an obstacle less than distance away (5 inches) the motor should stop. Otherwise it should keep moving. I know, you don't need the else, but it doesn't do any harm. I commented it out and nothing changed.

I still don't know what the problem is.

Thanks,
ma7730

I think PaulS is talking about these two rows:

  detectObject();     //look for obstacle
  if(detectObject() < distance) stopMotor();

Why call detectObject() and don't do anything with it just to call detectObject again.
If you want to use your global variable you could do:

  detectObject();     //look for obstacle
  if(inches < distance) stopMotor();

But the function calls order as it is now without the delay in moveForward() and if an obstacle is < 5.

moveForward()
detectObject()
detectObject()
stopMotor()
moveForward()
detectObject()
detectObject()
stopMotor()
.... and so on.

moveForward() is called directly after stopMotor().
To just test if this is the problem and everything else in the code is correct you could put a delay of say 10 seconds in stopMotor() to see if it is stopped for 10 seconds when it should.

void stopMotor(){
  digitalWrite(9, HIGH); //brake
  delay(10000);
}

And about the else, as it is now it is unnecessary. The robot will always be moving forward if the else is executed as it is now?
You have also forgotten the function call operator () so the function moveForward isn't called. Now it only gives the functions address (if I remember correctly.) and discards it. (Basically the same as just writing 47 there instead of moveForward as PaulS pointed out.)

@Ruuhbah -
Thank you for your reply. I changed the void loop to look like this:

 detectObject();
  Serial.println(inches);   
  if(inches < 5) 
    stopMotor();
  else
    moveForward();

And it now works perfectly! Thank you so much! :open_mouth: :grin:

Thanks again, all of you,

ma7730