Servo Initial Position

I'm controlling a servo with a ping sensor and I can't get the servo to return to an initial position before it starts responding to the sensor. Below is my code, when I mean initial position I'm referring to 180 degrees. I want it to start at 180 and when something comes into contact with the ping sensor at less than 5 inches then it moves over to 0 degrees. I borrowed this code from the University of Pennsylvania so if there is a simpler way please let me know. Thanks!

#include <Servo.h> // include the servo library

Servo servoMotor; // creates an instance of the servo object to control a servo

const int pingPin = 7; // Control pin for Ping Sensor
const int servoPin = 9; // Control pin for servo motor, may only be pin 9 or 10

int moveServoLeft = 0; // variable to control the motion of the Servo Motor to the left
int moveServoRight = 0; // variable to control the motion of the Servo Motor to the right
int servoPosition = 0; // variable to control the position of the Servo Motor

void setup() {

servoMotor.attach(servoPin); // attaches the servo on pin 9 to the servo object
servoMotor.write(0); // set servo to intial position
moveServoLeft = 1; // intial motion of Servo is from 0 to 180 i.e left
servoPosition = 0;
}

void loop() {

// get Distance
long duration, inches, cm;

// to set speakerPin and servoPin mode to OUTPUT
pinMode(servoPin, OUTPUT);

// The PING Sensor 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 Sensor, 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);

delay(200);

// to enable tracking the Servo motor is rotated only if the distance of the objects are less than or equal to 5”

if(inches <= 5) {
servoMotor.attach(servoPin);
servoMotor.write(servoPosition);
delay(15);

// to move left if the motor has reached 0 degrees
if(servoPosition == 0 && moveServoRight == 1){
moveServoLeft = 1;
moveServoRight = 0;

}
//controls how quick it moves
// to move left from 0 degree to 180 degrees
if(moveServoLeft == 1 & servoPosition <= 160)
servoPosition = servoPosition + 20;
// to move right from 180 degrees to 0 degree
if(moveServoRight == 1 & servoPosition >= 0)
servoPosition = servoPosition - 20;
}

// to disable tracking the Servo motor is detached if the distance of the object is greater than 5”
else {

servoMotor.detach();

for(int duration = 0; duration < 100; duration ++){

delayMicroseconds(200);
delayMicroseconds(200);
}

}

}

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 suspect your problem is that you are attaching and detaching your servo in your main loop. There is Never (yes that is an opinion) ever a logical reason to detach a servo, it's a stupid function and used for stupid reasons. Attach the servo in your setup function (as you are) and leave it attached. Move the servo when and where you want to and change it anytime you want to in your main loop. The servo library is designed to continuously resend the last valid position command you issued and the servo will remain in that position until you write a different position command to it. That is how servos are designed to be operated. Having a servo powered up, but with no pwm command being sent to it, is a undefined state for a servo and no servo manufactures would define such a mode of operation.

I'm sure someone will try and make the case for a valid reason to detach a servo, and I'm willing to read what others have to say, but lets stick to the reality of how servos operate. This is not unlike the serial flush command another 'solution' looking for a problem.

Lets see what the official Arduino reference for servo detach has to say:

detach()

Description
Detach the Servo variable from its pin. If all Servo variables are detached, then pins 9 and 10 can be used for PWM output with analogWrite().

Oh, so we have a servo wired to pin 9 and or 10, so we detach one of them so we can then if we wished send analogWrite() commands out the pin? What will the servo do with this 400 or 900Hz PWM signal, knowing that it's designed for a 50Hz signal? No, it will barf, twitch, hopeful billow smoke and burn up to teach the programmer a lesson. ]:slight_smile:

Just say no to servo.detach

Lefty

Thanks! That definitely makes sense and it worked to zero out the servo before the initial response. Do you have a suggestion for making it continuously respond to the ping sensor? I'm wanting it to move one direction when the object is close to the sensor and then move back the other direction when the object moves away.

Thanks again