Smooth Servo Control

Hello,

The program listed below moves my servos to the desired position, however, the movement is very jerky and happens too fast. Is their anyway to slow down/smooth out the servos motion? Once in the position the servos are fine and their is no twitching.

I looked at the examples of moving servos, however, I was not able to find one which showed smooth motion of 4 servos at the same time.

Any help would be awesome!

#include <Servo.h> 
 
Servo myservo2; 
Servo myservo3;  
Servo myservo4;
Servo myservo5;

 
void setup() 
{ 
  myservo2.attach(2);  
  myservo3.attach(3);
  myservo4.attach(4);
  myservo5.attach(5);

} 
 
 
void loop() 
{ 
  
    myservo2.write(0);             
    myservo3.write(180);     
    myservo4.write(109); 
    myservo5.write(25);  
     
delay(7000);   

  
    myservo2.write(90);    
    myservo3.write(150);     
    myservo4.write(100); 
    myservo5.write(115);  

  delay(3000);
  
}

I looked at the examples of moving servos, however, I was not able to find one which showed smooth motion of 4 servos at the same time.

You have to move servos one at a time. If you move in small enough steps, the servos will all appear, due to inertia, to be moving at one time.

What have you tried?

I tried at the "sweep" example and I loved the smooth motion however I could not figure out how to sweep all the servos at the same time. In the program I'm using now the servos all appear to start moving at the same time which is what I want. Is it possible to modify the sweep example so that all the servos move smoothly and at about the same time?

Thanks!

Which sweep example where?

The one that comes with the Arduino programing.

// Sweep
// by BARRAGAN <http://barraganstudio.com> 
// This example code is in the public domain.


#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 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
 
 
void loop() 
{ 
  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(15);                       // 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(15);                       // waits 15ms for the servo to reach the position 
  } 
}

In the servo sweep sketch where it says " myservo.write(pos); " if you add three more lines immediately following (and all before the delay()) - so you have a line for each servo - I think it should work as you want.

...R

Try:

// Sweep
// by BARRAGAN <http://barraganstudio.com> 
// This example code is in the public domain.


#include <Servo.h> 
 
Servo myservo2;  // create servo object to control servo 2
Servo myservo3;  // create servo object to control servo 3
Servo myservo4;  // create servo object to control servo 4
Servo myservo5;  // create servo object to control servo 5
                
int pos = 0;    // variable to store the servo position 
 
void setup() 
{ 
  myservo2.attach(2);  // attaches the servo on pin 2 to the servo object 
  myservo3.attach(3); // attaches the servo on pin 3 to the servo object 
  myservo4.attach(4); // attaches the servo on pin 4 to the servo object 
  myservo5.attach(5); // attaches the servo on pin 5 to the servo object 
} 
 
 
void loop() 
{ 
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo(2).write(pos);              // tell servo to go to position in variable 'pos' 
    myservo(3).write(pos);              
    myservo(4).write(pos);              
    myservo(5).write(pos);              
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo(2).write(pos);              // tell servo to go to position in variable 'pos' 
    myservo(3).write(pos);              
    myservo(4).write(pos);              
    myservo(5).write(pos);              
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
}

I need the servos to go to different positions (like in the first program i posted) but I want them to move to those positions with the smoothness of the sweep example. I also need them to arrive in their positions at about the same time. In the code you posted I think all the servos will end up in the same position.

My apologies for not being clear.

I need the servos to go to different positions

From where? The example moves the servo continuously. It doesn't just move a servo to a new position.

You can move all the servos from where they are to new positions, in a for loop, if you have 4 different position variables.

In the first code I posted (which I wrote) the servos start at a desired position wait a few seconds and move to an other position. In my code the servos move at ruffly the same time. The problem with my code is that the servos move straight to the position with no steps in-between, making the movement jerky. In the sweep example the servo moves in steps which makes the movement smooth.

I would like to modify my code so that each servo moves in steps but all the servos finish their steps at about the same time. I don't want one servo moving to position then the other. The servos should all be moving thought their steps at the same time. They will need to go to different positions wait a few seconds and then go back. For example one might go from 0 to 90 and another from 100 to 160.

You'll need to figure out some common factor in the angles that the servos are to move (90, 30, 9, and 90). Clearly, a for loop that iterates 90 times will work.

On each iteration, increment (or decrement) the position for each servo 1/90th of total range of motion for that servo (1 degree, 1/3 of a degree, 1/10 of a degree, 1 degree). Write that position to the servo. For the two smaller sweeps, the angle value will increment less than a degree, so you can see that ints won't work. The Servo library will truncate the value to an int, but that's OK. It just means that 9 out of 10 passes through the for loop, one of the servos will do nothing. On 1 of three passes, another will do nothing. On each pass, 2 of the servos will move every time.

Keep in mind that the for loop index does not HAVE to be used in the body of the for loop.

I made a program that uses steps to move the servos and it works perfect. Thanks for all the help!

Also is their anyway to shorten it?

Edit: I have found one problem. When moving to a new position the servo starts at a really low number which does not work in my design with some servos. If the arm is traveling to 180 degrees is their anyway that I can start the travel off at say 100 degrees?

#include <Servo.h> 

int pos1 = 0;
int pos1b = 0;

int pos2 = 0;
int pos2b = 0;

int pos3 = 0;
int pos3b = 0;

Servo myservo2; 
Servo myservo3;  
Servo myservo4;


void setup() 
{   myservo2.attach(2);
  myservo3.attach(3);
  myservo4.attach(4);

}

void loop() 
{
  
  delay(4000);
    myservo2.write(0);  
    myservo3.write(180);     
    myservo4.write(109);      

  delay(4000);
  smove(90,0,0);
  
}








void smove(int s1, int s2, int s3) 

{
  
  pos1 = s1 /12;
  pos2 = s2/12;
  pos3 = s3/12;
  
  
  
  
  
  pos3b= pos3;
  pos2b= pos2;
  pos1b= pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //1
  
  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //2

   pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //3

  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //4


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //5


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //6


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //7


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //8


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //9

  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //10


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //11


  pos3b = pos3b + pos3;
  pos2b = pos2b + pos2;
  pos1b = pos1b + pos1;
  myservo2.write(pos1b);
  myservo3.write(pos2b);
  myservo4.write(pos3b);
  delay(75); //12



  
  
}

[quote author=Drew Davis link=topic=170233.msg1266226#msg1266226 date=1370378671]
I made a program that uses steps to move the servos and it works perfect. Thanks for all the help!

Also is their anyway to shorten it? [/quote]

Try:

void smove(pos1, pos2, pos3) 
{
  pos1 = pos1/12;
  pos2 = pos2/12;
  pos3 = pos3/12;
   
  for (int x =1;x<13;x++){ //do the following 12 times
    pos3b+ =  pos3;  //does the same as pos3b = pos3b + pos3
    pos2b+ =  pos2;
    pos1b+ =  pos1;
    myservo2.write(pos1b);
    myservo3.write(pos2b);
    myservo4.write(pos3b);
    delay(75); 
  }
 pos3b = 0;  //reset variables for next call to function but,
     //if you need to retain where the servos are, remove these lines
 pos2b = 0;
 pos1b = 0;
}

Hey Drew,
Here is a code example of sine wave smooth servo movement from two different positions.
The code seems complex but it just uses the more detailed writemicroseconds() command spread out in a bunch of for loops to handle start pause, and alterations in beginning and ending speed.
You are basically able to pick the beginning and end range of the servo, then pick positions between that you want the servo to travel to.
The motion between will be a sine wave smooth with a selectable start and end speed.

http://forum.arduino.cc/index.php?topic=184377.0

I usually have two sets of variables in arrays (or a struct in a single array - whatever) which contains the desired and current position of each servo on the system. Then, at pre-defined intervals, either through the use of millis() or on a timer, I update the contents of that array so that the "current" variable is set to half way between its current value and that of the "target" value. Then I write that new current value to the servo. It makes for a nice fast start to the movement, but it comes to a nice gentle stop at the right position. The overall speed is set by the delay between updates.