Having trouble with Ping tutorial

I have a Parallax Ping sensor and I can't get the example sketch for it to work properly. The sensor is being activated but the duration value returned by pulseIn is far too big. If I put millis() calls either side of the pulseIn() call the delay between them is about 9 milliseconds, but the duration value returned is 35568633, so the distances calculated are similarly massive. For example:

start = 3334 end = 3343 dur =35693633 ,241173in, 615407cm start = 3501 end = 3510 dur =35693633 ,241173in, 615407cm start = 3668 end = 3678 dur =35381133 ,239061in, 610019cm start = 3836 end = 3846 dur =35381133 ,239061in, 610019cm start = 4004 end = 4014 dur =35318633 ,238639in, 608941cm start = 4172 end = 4182 dur =35318633 ,238639in, 608941cm start = 4340 end = 4349 dur =35631133 ,240750in, 614329cm

My only modification to the example is adding the two millis() calls:

start = millis(); duration = pulseIn(pingPin, HIGH); end = millis();

The value I get back does get (a little) smaller as I move my hand toward the sensor. I tried a sketch at liquidware which yabb won't let me link to right now, and it too shows the value going down as I move my hand closer, so the sensor seems to be working.

I am trying this on a Diecimila from Ubuntu Intrepid with avr-gcc 4.3.0. I get the same duration value back with arduino-011, 012 and 013.

Any ideas?

If start and end are declared as ints, make them unsigned longs: unsigned long start; unsigned long end;

if they already are, then post your code.

Yeah they were already unsigned longs, thanks. The rest of the sketch is directly from the Ping example (Sketchbook/Examples/Sensors/Ping in 013). I tried changing duration, inches and cm to unsigned longs to match the pulseIn signature, but they aren't big enough to need the last bit, in this case anyway. The calculations appear to match those in the Ping datasheet; it's just the return from pulseIn that seems off to me.

int pingPin = 7;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  long duration, inches, cm;
  unsigned long start = 0;
  unsigned long end = 0;

  // 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);
  
  start = millis();
  duration = pulseIn(pingPin, HIGH);
  end = millis();

  // convert the time into a distance
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  
  Serial.print("start = ");
  Serial.print(start);
  Serial.print(" end = ");
  Serial.print(end);
  Serial.print(" dur =");
  Serial.print(duration);
  Serial.print(" ,");
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
  delay(100);
}

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

I don’t use a ping sensor but I wonder if it needs a pull-up resistor. You may want to try it with the highlighted line to see if that is the problem.

pinMode(pingPin, INPUT);
digitalWrite(pingPin, HIGH); // Turn on pullup resistor if external pullup not used

start = millis();
duration = pulseIn(pingPin, HIGH);
end = millis();

Thanks, I will try that.

I am still confused as to how the return from pulseIn could be ~35 seconds (35693633 microseconds) when only ~9ms have elapsed. Could the conversion from clock cycles to microseconds get messed up somehow?

You could also try a simple pulseIn test. With no ping sensor, see if you get meaningful results when you manually connect the input pin to ground to simulate a pulse.

Good plan. I shall try that too, since that would rule out any clock-to-microseconds foibles.

I out this sketch on my Diecimila:

const int pin = 7;

void setup()
{
  Serial.begin(9600);
  pinMode(pin, OUTPUT);
}

void delayMillis(unsigned long delay)
{
  const unsigned long start = millis();
  const unsigned long end = start + delay;
  while (millis() < end)
  {
  }
}

void loop()
{
  digitalWrite(pin, LOW);
  delayMillis(100);
  Serial.println("HIGH");
  digitalWrite(pin, HIGH);
  delayMillis(2000);
  digitalWrite(pin, LOW);
  delayMillis(100);
  Serial.println("LOW");
}

and this sketch on my Duemilanove:

int pingPin = 7;

void setup()
{
  Serial.begin(9600);
  pinMode(pingPin, INPUT);
}

void loop()
{
  unsigned long duration = 0;

  Serial.println("Start");
  duration = pulseIn(pingPin, HIGH);
  Serial.println("Stop");

  Serial.print(duration);
  Serial.println();
  
  delay(100);
}

I then hooked both pin 7s to each other with a jumper wire. The output I see from the due:

Stop

225119481

Start

Stop

225744481

Start

Stop

49184025

Start

Stop

225244481

Start

Stop

225244481

Start

Stop

224744481

Start

Stop

225431981

Start

Stop

225119481

Start

Stop

225306981

So presuming the 225119481 corresponds to my very rough 2 second delay in the deci’s sketch, I am seeing values off by a factor of 100.

What could I be doing wrong?

So I tried the original sketch using my MacBook and it works fine. I see mention of a bug in avr-gcc 4.3.0 at http://www.arduino.cc/playground/Learning/Linux and that's the version I had on my Intrepid box, so that likely explains my original problem.