Go Down

Topic: Ping))) and Servo (Read 4192 times) previous topic - next topic

Borner

Apr 24, 2012, 09:59 pm Last Edit: Apr 24, 2012, 10:08 pm by Borner Reason: 1
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...;) 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):

Code: [Select]

/* 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!

wildbill

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

Borner

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!

wildbill

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.

DuaneB

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
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

Borner

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:

Code: [Select]


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

PaulS

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

Of course you can.

Quote
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.

Borner

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:
Quote
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!

PaulS

Move this code:
Code: [Select]
  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.
Code: [Select]
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?

Jantje

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.
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Borner

Hello it's me again,

now I modified my servo to turn 360 degrees like in this video: http://www.youtube.com/watch?v=CtLN8BoMIlQ
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! 

AWOL

#11
May 02, 2012, 04:10 pm Last Edit: May 02, 2012, 04:12 pm by AWOL Reason: 1
Quote
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.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Borner

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

Go Up