Pages: [1]   Go Down
Author Topic: detaching a servo  (Read 2178 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it possible to detach and attach a servo in a program?
Yes, one can detach a servo in loop(), and reattach it.

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

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it possible to detach and attach a servo in a program?
Quote
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:)

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


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Quote

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

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How? I have been trying everything I can think of, that's why I asked:)
Using the detach() method of the Servo class.

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
// 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
  }
}
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
// 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
  }
}
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Logged

Pages: [1]   Go Up
Jump to: