Ping Range Finder Help

I am trying to map servo movements to my Ultrasonic Ping Range Finder. I can get the range finder demo working, but when I try to incorporate the servo, it reads data in pulses and very random, making really bad and twitchy servo movements. I am thinking it is a software issue. Is there any thing I'm doing wrong? I want the servo turn by the distance of something from the rangefinder smoothly.

// this constant won't change.  It's the pin number
// of the sensor's output:
#include <Servo.h>
const int pingPin = 7;
Servo pan;
Servo tilt;


int panPos = 90;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pan.attach(3);
  tilt.attach(12);
  tilt.write(90);
  pan.write(90);
}

void loop()
{
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration;
  int cm;
  int val; 

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // 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
  cm = microsecondsToCentimeters(duration);
  val = map(cm, 1, 15, 0, 180);
  Serial.println(val);
  delay(100);
  pan.write(val); 
}



int 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.
  int rtn = 0;
  microseconds = microseconds / 29 / 2;
  return microseconds;
}

How are you powering all this?

The servo's and Ping))) are supplied the 5V from the arduino, the arduino it self is powered by the usb cord hooked to my PC.

You can maybe power the ping from the Arduino, but not the servo.

I thought it might have to do with the servo's eating power. The Ping))) is the lags and the LED on it that show's it working will flicker and not work but like every 2 seconds or so.

Should I put the servos on transistors and feed the signal from the arduino that way? Or do you guys have a better option?

(I am not an Electrical Engineer so please bare with me.)

You don't need a transistor for the servo signal, you need a separate supply for the servo.
The signal current is minuscule, just remember to connect the grounds ( 0V) together

(I'm not an EE either)

By the grounds together, do you mean share the arduino's ground with a separate power supply such as a 5V Voltage regulator?

I tried having the servo's on a separate supply (5V Voltage regulator) and the signal pin going to the arduino, that didn't work. When powered on the servos went all the way to the left and wouldn't move. But when hooked up to the arduino they worked fine. The servos by them selves on arduino power work fine, as does the Ping))), but not together.

As a first test, replace pan.write(val); with pan.write(90); and check if the same happens. Check it a other servo positions than 90 that seem to be more jittery. The point of this test is to isolate if the problem lies with the servo or the data from the range finder without modifying the hardware or the work done.

If the servo's jittery in this test, I would look into power supply problems and others. Most likely your range finder isn't to blame.

If the servo is stable, the problem lies with the range finder (or the pulseIn()) function. I would the look into how stable the output if pulseIn is (variable duration) when focussing a fixed target. Does it jump all over the place or is it reasonably stable.

Also it's a good idea to get rid of the microsecondsToCentimeters function and the variable cm. You loose precision when going from duration to cm and blowing up any small error in the map function when going from cm to val. A small rounding error of 1 in cm results in an error of 12 degree on the servo.

Instead use map to do all calculations in one step:val = map (duration, 29 * 2 * 1, 29 * 2 * 15, 0, 180);

Korman

I will try this as soon as I get home.

Thank you guys for helping, it is for a shoulder mounted turret like the plasma caster the Predator wears in his movies. It will have a coil gun and a strobe bulb. Eventually I would like to add a webcam and run my facial recognition software.

I will let ya know if I get it working, again thanks.

Okay I narrowed down the problem. With everything sharing arduino's 5V pin and the arduino's gnd respectivly, the Ping))) doesn't work while the servo's are moving. I tried having the servo's on a separate power supply with the signal going to the arduino; this didn't work, I'm guessing because the signal needs to be on the same circuit as its power and ground. Am I right?

Connect the servo's red wire to an external 6V supply only.
Connect the external suppliy's ground to the serco's black wire AND to the Arduino's ground.
Connnect the signal wire from the Arduino to the servo's (usually white) signal wire.

It works now. I don't know what happened before, I took out the signal wire and put it back in, and it worked.

Thank you Korman for the compacted code.

You can see the project on my blog here.

I will be updating it when I get home. There will be a video also of the new progress.

As promised, here is a video:

As promised, here is a video

Have you ever thought of investing in a tripod?

To take video? I would, if I had a bigger work area and more impressive builds.