Ping))) and Servo

Hello arduinolovers, I’m new in this Forum and want to say hello to all you guy’s. I’m a beginner in programming the arduino so don’t throw stones…:wink: but maybee you can help me with my project.

First, What do I try to accomplish? - I got an ultrasonic sensor (Ping))) from parallax) and a servo motor(cheap one) and I try to make them talk!

Second, where is the problem? - They don’t talk together. The idea is the following: if you’re staying closer then 1,20m in front of the ping)))sensor the servomotor should rotate otherwise not, two led’s are indicating that (red/green).

What I have had achived so far: ultrasonic ping + arduino = works!, servo + arduino = works, ping + servo + arduino = doesn’t work.

Here is my sourcecode (copy&paste style):

/* Ping))) Sensor
 
   This sketch reads a PING))) ultrasonic rangefinder and returns the
   distance to the closest object in range. To do this, it sends a pulse
   to the sensor to initiate a reading, then listens for a pulse
   to return.  The length of the returning pulse is proportional to
   the distance of the object from the sensor.
     
   The circuit:
    * +V connection of the PING))) attached to +5V
    * GND connection of the PING))) attached to ground
    * SIG connection of the PING))) attached to digital pin 7

   http://www.arduino.cc/en/Tutorial/Ping
   
   created 3 Nov 2008
   by David A. Mellis
   modified 30 Aug 2011
   by Tom Igoe
 
   This example code is in the public domain.

 */

// this constant won't change.  It's the pin number
// of the sensor's output:


#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
 
int pos = 0;    // variable to store the servo position
const int pingPin = 7; 

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pinMode(13, OUTPUT); 
  pinMode(12, OUTPUT); 
  
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  
}

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

  // 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
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
 
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
 
  delay(100);
  
    if (cm < 120) {
    // Anweisungsblock für wahr
    digitalWrite(13, HIGH);
    digitalWrite(12, LOW);
    
     for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(200);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(200);                       // waits 15ms for the servo to reach the position
  }
    
    } else {
    // Anweisungsblock für falsch
    digitalWrite(13, LOW);
    digitalWrite(12, HIGH);
    }
}

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

So maybee you guys, can help me. It’s my second arduino project.

With best regards Borner!

Looks ok. What does it do? What are your serial prints telling you? How is the servo powered?

The servo is powered by the 5v pin on the arduino board (also the ping)) I splitted the 5v on a breadboard but seems ok), the serial shows only "16cm" but is not reacting. the ping))) activity led is blinking once at start but not all the time as usually...mhh any other suggestions? thx for your reply!

May be a power issue - powering even a single servo from the arduino is usually marginal, perhaps adding the ping has pushed you over the edge. Try copying your servo code into setup so it runs unconditionally at startup just to see whether it moves. Try the same code with the ping detached. Better to get separate power for the servo - don't forget to connect the grounds.

Hi,
As others have said most likley power, check the links in my signature for an idea of whats happening, a demonstration video and how to fix it.

Duane B

rcarduino.blogspot.com

Thank you guys but it was not the power, everything is powered up right. The thing was that I had to wait the rotation of the servo after that the ping sends signals again. but not parallel as I wanted to do. so it is a programming issue here.

now there is the problem to achive that, can I call a function or just turn the servo only plus one° (startpoint is indifferent) and not the whole 180° and messure after that with the ping everytime. thx a lot for your time!!! and help!

here is the code again without all the comments:

const int pingPin = 7; 

#include <Servo.h>
 
Servo myservo;  
 
int pos = 0;   


void setup() {

  Serial.begin(9600);
  pinMode(13, OUTPUT); 
  pinMode(12, OUTPUT); 
  
  myservo.attach(9);  
  
}

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

  
  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);
  cm = microsecondsToCentimeters(duration);
 
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
 
  delay(100);
  
    if (cm < 120) {
   
    for(pos = 0; pos < 180; pos += 1) 
      {                                 
    myservo.write(pos);              
    delay(200);                      
      }
    for(pos = 180; pos>=1; pos-=1)     
    {                                
    myservo.write(pos);             
    delay(200);                      
    }
    
    digitalWrite(13, HIGH);
    digitalWrite(12, LOW);
    
     
    } else {
    // Anweisungsblock für falsch
    digitalWrite(13, LOW);
    digitalWrite(12, HIGH);
    }
}

long microsecondsToInches(long microseconds)
{ 
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

can I call a function or just turn the servo only plus one°

Of course you can.

and messure after that with the ping everytime.

I'm not sure what you mean by this. It sounds like you want to move the servo, measure a distance, move the servo, measure a distance, etc. That you can do. You just need a different for loop.

You may need to define your requirements a little better/more clearly.

I'm sorry for that, but I'm german and it's a little bit difficult to express myself, sorry. yeah exactly thats what I meant:

It sounds like you want to move the servo, measure a distance, move the servo, measure a distance, etc. That you can do. You just need a different for loop.

How must be the for loop then?

Thanks a lot you really helped me!

Move this code:

  long duration, inches, cm;

  
  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);
  cm = microsecondsToCentimeters(duration);
 
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

into a subroutine, called something like distance().

This code, then, would move the servo one degree at a time, taking a reading at each location.

void loop()
{
   for(int i=0; i<180; i++)
   {
      distance();
   }

   for(int = 180; i>0; i--)
   {
     distance();
   }
}

If you can define what you want to do, you can change the loop to do what you want. It’s not clear what you want to do with the distance reading. Are you trying to keep the sensor pointing towards the closest object? Or away from?

With a cheap servo you will get weird readings from the ping, For sure when you power from the Arduino directly.
So take a good power supply (as you have been told before) and put a cap over the servo and ping (and maybe wait a while after each move)

Best regards
Jantje

PS I know because I spend days on a unreliable distance sensor to find out it was interference with the servo.

Hello it's me again,

now I modified my servo to turn 360 degrees like in this video: Robot Builder's Guide 3 - Hacking a Servo - YouTube
and I can't stop the servo turning all the time
myservo.write(pos+1); spins it, but how can I stop the servo?

thx for your help!

and I can't stop the servo turning all the time

You should be able to stop your ex-servo by writing a value around 90 "degrees", but you'll have to determine the exact value by experiment.
zoomkat regularly posts test code for stepping a servo - that would be a good starting point.

THX a lot for my servo (futabas3003) it was 96degrees!