Ping-Servo problem

I got my Ping))) Ultrasonic Rangefinder working so that it turns on a light and turns a servo one way when an object is more than 3 inches away. It then turns off the light and turns the servo in an opposite direction when an object gets within 3 inches of the “eyes”. This may be hard to explain, but here goes: There is a major problem either with my code or the servo. I think its the servo it which case ill have to buy another, The problem is that if i do not put an object in front of the servo within 2 seconds of me letting it go with no object, it takes over 10 seconds for the servo to realize that there is an object in its way and it should change to the opposite direction. The LED responds immediately though, leading me to believe that it is the servo’s error. I cannot figure out the problem. The counter argument that it may be the code’s fault, is that the same thing happens with both servos. Does anyone see anything wrong with this code?

#include <Servo.h>
Servo myservo;
int pos = 0;
int pingPin = 7;
const int ledPin = 13;

void setup()
{
Serial.begin(9600);
pinMode (ledPin, OUTPUT);
myservo.attach(9);
}

void loop()
{
long duration, inches, cm;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// We give a short LOW pulse beforehand to ensure a clean HIGH pulse.
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);

Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print(“cm”);
Serial.println();
if (inches >= 3) {
digitalWrite (ledPin, HIGH);
pos++;
myservo.write(pos);
}
else {
digitalWrite (ledPin, LOW);
pos–;
myservo.write(pos);
}

}

long microsecondsToInches(long microseconds)
{
// According to Parallax’s datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 73.746 / 2;
}

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;
}

so your saying that there is basically a lack of response to an object closer than 3 inches to the sensor after 2 seconds of operating time?

This probably won't help with the problem at hand but it should help in general: The PING sensor I have needs a little "quiet time" between reads. When trying to take readings too quickly it occasionally returns bad results. In my case, a 4ms delay between readings seems to have solved the problem.

Edit: [timestamp=1245811517] The documentation calls for a 200us delay between readings. I only tested 4ms so a shorter delay will very likely work.

  • Brian

I dunno bout that, he has the standard "quite time" code that the ping tutorial gives, and that code worked for me back when I messed around with motion sensing

There is a problem with your code. The variable pos is unbounded. You need to clamp it to minimum and maximum values.

Good luck, Brian

I dunno bout that

The documentation for the PING clearly indicates that a small delay (200us) is necessary between readings.

he has the standard "quite time" code that the ping tutorial gives

The tutorial has a 100ms delay at the bottom of loop. While this is far more than the 200us called for, there is still a delay.

  • Brian

your right, my bad. I was referring to the delay at the top of the loop, which isn't actually a delay its the switch from HIGH to LOW.

So should I add a delay at the end of my loop?

And yes, Jezuz, thats correct, it becomes unresponsive.

How long should i make my delay?

So should I

Read Reply #4? Yes. Then add two if statements to clamp pos to a reasonable range.

add a delay at the end of my loop?

Yes.

How long should i make my delay?

delay( 4 );
  • Brian

thanks! ;D

I would suggest using a specific value for the servo based on the distance.

For example:

 if (inches >= 3) {
   digitalWrite (ledPin, HIGH);
   pos=45;
   myservo.write(pos);
 }
 else {
   digitalWrite (ledPin, LOW);
   pos=135;
   myservo.write(pos);
 }

You might also try putting in an even longer delay than the suggested 4 ms. The servo library may react badly to having the write commands come in too quickly.

great idea, thanks :)