detaching a servo

Is it possible to detach and attach a servo in a program? What I mean is when you modify a servo there are some differences between servos, so 90 isn't always center, and making one servo 89 and another one 91 doesn't work either as temperature and voltage change the servos center(stop) position. So I was thinking about using a range for (stop) say, 88-92, if input is in that range it detaches the servo and no output is sent to the servo. Another option is to use a 4066 and one pin of the arduino as an enable for the controll signals to the servos.
Charley

Is it possible to detach and attach a servo in a program?

Yes, one can detach a servo in loop(), and reattach it.

So I was thinking about using a range for (stop) say, 88-92, if input is in that range it detaches the servo and no output is sent to the servo.

So, if the servo is happily spinning along at top speed, and it is told to stop, you want to just disconnect it, and let it freewheel?

PaulS:

Is it possible to detach and attach a servo in a program?

Yes, one can detach a servo in loop(), and reattach it.

How? I have been trying everything I can think of, that's why I asked:)

So I was thinking about using a range for (stop) say, 88-92, if input is in that range it detaches the servo and no output is sent to the servo.

So, if the servo is happily spinning along at top speed, and it is told to stop, you want to just disconnect it, and let it freewheel?

Yes, and when I hold the Wii Remote flat I want the robot to stop moving.

Here is the code I am using, near the bottom you will see my range expression commented out , it has the ?????????? where I want to detach the servos
Charley

#include <WiiRemote.h>
#include <Servo.h>

#define STEERING_ANGLE_MAX 160
#define STEERING_ANGLE_MIN 20
#define STEERING_ANGLE_CENTER 90
#define STEERING_ANGLE_STEP 5
Servo Left_servo; // create servo object to control a servo
Servo Right_servo;
int deg1;
int a;
WiiRemote wiiremote;

void setup()
{

wiiremote.init();
Left_servo.attach(6); // attaches the servo on pin 3 & 6 to the servo objects
Right_servo.attach(3);

}
void loop(){

wiiremote.task(&myapp);
}

void myapp(void) {
//if (wiiremote.buttonClicked(WIIREMOTE_TWO)) {
int steering_angle = getSteeringAngle();
}

int getSteeringAngle(void) {
// double rad; // y accel setup
//double deg; // y accel setup
double rad2; // X accel setup
double deg2; // X accel setup

//rad = acos((double) wiiremote.Report.Accel.Y);
// deg = rad * 180.0 / PI;

rad2 = acos((double) wiiremote.Report.Accel.X);
deg2 = rad2 * 180.0 / PI;

/* clipping */
if (deg2 > STEERING_ANGLE_MAX) { deg2 = STEERING_ANGLE_MAX; }
else if (deg2 < STEERING_ANGLE_MIN) { deg2 = STEERING_ANGLE_MIN; }

// if (deg > STEERING_ANGLE_MAX) { deg = STEERING_ANGLE_MAX; }
//if (deg < STEERING_ANGLE_MIN) { deg = STEERING_ANGLE_MIN; }

// if (deg2 >= 85 && deg2 <= 95) { ??????????????????? }

if (deg2 > 90) { a = deg2 - 90; //Inverts output to reverse right servo
deg1 = 90 - a;
}
else if (deg2 < 90) {a = 90 - deg2;
deg1 = 90 + a;
}

Left_servo.write(deg2);
Right_servo.write(deg1);

}

How? I have been trying everything I can think of, that's why I asked:)

Using the detach() method of the Servo class.

Got it , and it works perfectly, when I hold the remote flat, (and being human I wiggle,sway ,and shake) the the robot stops and when I roll it forward it moves forward proportionately to the angle I tilt the remote, and reverse works the same:) the problem was that I was putting the pin number in the detach command.

Here is the working code.

#include <WiiRemote.h>
#include <Servo.h>

#define STEERING_ANGLE_MAX 160
#define STEERING_ANGLE_MIN 20
#define STEERING_ANGLE_CENTER 90
#define STEERING_ANGLE_STEP 5
Servo Left_servo; // create servo object to control a servo
Servo Right_servo;
int deg1;
int a;
WiiRemote wiiremote;

void setup()
{

wiiremote.init();
Left_servo.attach(6); // attaches the servo on pin 3 & 6 to the servo objects
Right_servo.attach(3);

}
void loop(){
Left_servo.attach(6); // attaches the servo on pin 3 & 6 to the servo objects
Right_servo.attach(3);
wiiremote.task(&myapp);
}

void myapp(void) {
//if (wiiremote.buttonClicked(WIIREMOTE_TWO)) {
int steering_angle = getSteeringAngle();
}

int getSteeringAngle(void) {
// double rad; // y accel setup
//double deg; // y accel setup
double rad2; // X accel setup
double deg2; // X accel setup

//rad = acos((double) wiiremote.Report.Accel.Y);
// deg = rad * 180.0 / PI;

rad2 = acos((double) wiiremote.Report.Accel.X);
deg2 = rad2 * 180.0 / PI;

/* clipping */
if (deg2 > STEERING_ANGLE_MAX) { deg2 = STEERING_ANGLE_MAX; }
else if (deg2 < STEERING_ANGLE_MIN) { deg2 = STEERING_ANGLE_MIN; }

// if (deg > STEERING_ANGLE_MAX) { deg = STEERING_ANGLE_MAX; }
//if (deg < STEERING_ANGLE_MIN) { deg = STEERING_ANGLE_MIN; }

if (deg2 >= 85 && deg2 <= 95) { Left_servo.detach();
Right_servo.detach(); }

if (deg2 > 90) { a = deg2 - 90; //Inverts output to reverse right servo
deg1 = 90 - a;
}
else if (deg2 < 90) {a = 90 - deg2;
deg1 = 90 + a;
}

Left_servo.write(deg2);
Right_servo.write(deg1);

}

rameses32:
Is it possible to detach and attach a servo in a program? What I mean is when you modify a servo there are some differences between servos, so 90 isn't always center, and making one servo 89 and another one 91 doesn't work either as temperature and voltage change the servos center(stop) position. So I was thinking about using a range for (stop) say, 88-92, if input is in that range it detaches the servo and no output is sent to the servo. Another option is to use a 4066 and one pin of the arduino as an enable for the controll signals to the servos.
Charley

If you are using continous rotation servos, the writeMicroseconds approach will probably give better servo control than using the angle variant. Below is some test code that might show the difference.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

Servos are not designed to have power applied to them but without a continuous servo signal being supplied to them. It's an undefined state for the servo and there is almost no legitimate reason to ever 'detach' a servo. There are ways in your sketch to compensate for the slight differences in each servo's command range, standard R/C transmitters did this with individual 'trim' controls for each channel's stick control. That can be emulated in software.

Lefty

there is almost no legitimate reason to ever 'detach' a servo.

When "standard" servos are modified for continous rotation to drive wheels/tracks, they are often suffer from motion "creep" due to various reasons. I've never seen loss of a position control signal in itself cause erratic behavior in a servo (not to be confused with "noise" or malformed control signals). Trying to neturalize the servo creep using mechanical adjustment or on the spot software reprogramming is a real PITA.

zoomkat:

there is almost no legitimate reason to ever 'detach' a servo.

When "standard" servos are modified for continous rotation to drive wheels/tracks, they are often suffer from motion "creep" due to various reasons. I've never seen loss of a position control signal in itself cause erratic behavior in a servo (not to be confused with "noise" or malformed control signals). Trying to neturalize the servo creep using mechanical adjustment or on the spot software reprogramming is a real PITA.

I still stand by my statement/opinion. Servos were never designed to be powered up but without a continuous control signal, that is a undefined state and is sure to have variable responses by different specific servo models and manufactures.

Lefty

Some simple test code for use with the serial monitor to see if detaching a particular servo makes it exhibit unexpected behavior.

// zoomkat 9-11-12 serial servo detach test
// type servo position in serial monitor
// use writeMicroseconds >500 to control servo
// use writeMicroseconds <500 to detach servo
// for IDE 0022 and later
// Powering a servo from the arduino usually DOES NOT WORK.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-detach-test"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  // allow buffer to fill with next character
    }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();

    if (n < 500) {
      myservo.detach(); 
    }
    else {
       myservo.attach(7);
       myservo.writeMicroseconds(n); //convert readString to number for servo
    }
    readString=""; //empty for next input
  } 
}

Thanks for all the help guys. Lefty, I understand what you are talking about, but since I have no rotational feedback, and without installing rotary encoders I have to way to tell the arduino that the wheels are creeping, and going into the program and telling it servo (a) center is 91, servo (b) is 89, servo (c) is 90 etc... , does not work, I have servos that rotate one way on 90 and the opposite direction on 91, and besides that as I said earlier temperature and voltage change these values, and constantly changing the values and uploading the sketch just sucks. Also by detaching the servo in this manner it makes modifying servoes that much easier, just a couple 1% fixed value resistors and the software can now compensate for differences. You may be correct about the undefined command in the servo and manufactures not recommending this, but I dont think they recommend removing the pot, cutting out the stops, and all the other modifications we do to their products:) .

Charley

rameses32:
Thanks for all the help guys. Lefty, I understand what you are talking about, but since I have no rotational feedback, and without installing rotary encoders I have to way to tell the arduino that the wheels are creeping, and going into the program and telling it servo (a) center is 91, servo (b) is 89, servo (c) is 90 etc... , does not work, I have servos that rotate one way on 90 and the opposite direction on 91, and besides that as I said earlier temperature and voltage change these values, and constantly changing the values and uploading the sketch just sucks. Also by detaching the servo in this manner it makes modifying servoes that much easier, just a couple 1% fixed value resistors and the software can now compensate for differences. You may be correct about the undefined command in the servo and manufactures not recommending this, but I dont think they recommend removing the pot, cutting out the stops, and all the other modifications we do to their products:) .

You should be commanding the servos with the alternate microsecond commands rather the the degree commands. This should give you much better resolution for the symptom you are seeing.
Lefty

Charley

Here is a video of it working.

And here is the sketch, I know, it is really sloppy code, any improvements please let me know. I am very happy with the way it works, it does exactly what I wanted it to do when I first drew the flow chart. Thanks to everyone that helped.
Charley
P.S. I love Arduino:)

#include <WiiRemote.h>
#include <Servo.h>

#define STEERING_ANGLE_MAX 160
#define STEERING_ANGLE_MIN 20
#define STEERING_ANGLE_CENTER 90
#define STEERING_ANGLE_STEP 5
Servo Left_servo; // create servo object to control a servo
Servo Right_servo;
int deg1;
int a;
WiiRemote wiiremote;

void setup()
{

wiiremote.init();
Left_servo.attach(6); // attaches the servo on pin 3 & 6 to the servo objects
Right_servo.attach(3);

}
void loop(){
Left_servo.attach(6); // attaches the servo on pin 3 & 6 to the servo objects
Right_servo.attach(3);
wiiremote.task(&myapp);
}

void myapp(void) {

int steering_angle = getSteeringAngle();
}

int getSteeringAngle(void) {
double rad; // y accel setup
double deg; // y accel setup
double rad2; // X accel setup
double deg2; // X accel setup

rad = acos((double) wiiremote.Report.Accel.Y);
deg = rad * 180.0 / PI;

rad2 = acos((double) wiiremote.Report.Accel.X);

deg2 = rad2 * 180.0 / PI;

/* clipping */
if (deg2 > STEERING_ANGLE_MAX) { deg2 = STEERING_ANGLE_MAX; }
else if (deg2 < STEERING_ANGLE_MIN) { deg2 = STEERING_ANGLE_MIN; }

if (deg > STEERING_ANGLE_MAX) { deg = STEERING_ANGLE_MAX; }
else if (deg < STEERING_ANGLE_MIN) { deg = STEERING_ANGLE_MIN; }

if (deg2 >= 85 && deg2 <= 95) { Left_servo.detach(); //eliminates drift at servo center position
Right_servo.detach(); }

if (deg2 > 90) { a = deg2 - 90; //Inverts output to reverse right servo
deg1 = 90 - a;
}
else if (deg2 < 90) {a = 90 - deg2;
deg1 = 90 + a;
}

if (deg >= 80 && deg <= 100) {
Left_servo.write(deg2);
Right_servo.write(deg1);
}
else if (deg < 80) {
Right_servo.write(deg1);
Left_servo.write(90);
}
else if (deg > 100) {
Left_servo.write(deg2);
Right_servo.write(90);
}
}