Simultaneous but different servo sweeps with four servos

Hi I want to run a sweep command for 4 servos off of one Arduino Uno simultaneously, but each at different rates.

Currently I have figured out how to run 4 servos simultaneously but at the same rate, and how to run each at a different rate, but not simultaneously.

Here is my code, which makes all the servos rotate together 90 degrees first, then two rotate back 90 degrees at a rate of 40 ms, and then the other two rotate back after that at a rate of 15 ms.

//QUADSweep
//edited from the original code by BARRAGAN

#include "Servo.h"

Servo myservo; // create servo object to control a servo, a maximum of eight servo objects can be created
Servo mysecondservo; // servo 2
Servo mythirdservo; // servo3
Servo myfourthservo; // servo4

int pos = 0; // variable to store the servo position

void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
mysecondservo.attach(10); // attaches the servo on pin 10 to the servo object
mythirdservo.attach(8); // attaches the servo on pin 8 to the servo object
myfourthservo.attach(11); // attaches the servo on pin 11 to the servo object
}

void loop()
{
for(pos = 0; pos < 90; pos += 1) // goes from 0 degrees to 90 degrees in steps of 1 degree
{
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
mythirdservo.write(pos); // tell servo to go to position in variable 'pos'
delay(40); // waits 40ms for the servo to reach the position
}
{
mysecondservo.write(pos); // tell servo to go to position in variable 'pos'
myfourthservo.write(pos); // tell servo to go to position in variable 'pos'
delay(10);
}
}
for(pos = 90; pos>=0; pos-=1) // goes from 90 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
mythirdservo.write(pos); // tell servo to go to position in variable 'pos'
delay(40); // waits 40ms for the servo to reach the position
}
for(pos = 90; pos>=0; pos-=1) // goes from 90 degrees to 0 degrees
{
mysecondservo.write(pos); // tell servo to go to position in variable 'pos'
myfourthservo.write(pos); // tell servo to go to position in variable 'pos'
delay(10); // waits 10ms for the servo to reach the position
}
}

Any ideas or advice? Thanks

loop()
{
unsigned long start = millis();
int sweepsNotFinished;

do
    {
    unsigned long now = millis() - start;
    sweepsNotFinished = 0;
    sweepsNotFinished += sweep(now, 500, 1500, 90, 0, servo1); // 1/2 second delay then 1 second sweep from 90 to 0
    sweepsNotFinished += sweep(now, 0, 2000, 180, 75, servo2); // no delay and 2 second sweep from 180 to 75
    sweepsNotFinished += sweep(now, 250, 10000, 30, 100, servo3);  // 1/4 second delay, then 9.75 second sweep from 30 to 100
   } while (sweepsNotFinished > 0);
}

int  sweep(unsigned long currentTime, unsigned long startTime, unsigned long endTime, int startPosition, int endPosition, Servo &servo)
{
if (currentTime < startTime)
    return 1;
if (currentTime > endTime)
    return 0;
servo.write( startPosition + (endPosition-startPosition) * (currentTime-startTime) / (endTime-startTime);
  return 1;
}

ok sorry but I'm a super duper hack beginner....I'm trying to upload it but it's saying "expected `)' before ';' token" and points to the red line below. What does this mean...?

if (currentTime > endTime)
return 0;
servo.write( startPosition + (endPosition-startPosition) * (currentTime-startTime) / (endTime-startTime);
return 1;
}

it means I forgot a ')' just before the ';' character in that line.

I uploaded it but only one servo is moving...I'm just kind of lost in the code how it works

OK... So one servo is moving. If you show me the complete code I might be able to tell why the other servos are not moving.

I don't think this code will work:
mythirdservo.attach(8); // attaches the servo on pin 8 to the servo object

Hint: There is a reason why there is a special button for posting code.

//QUADSweep
//edited from the original code by BARRAGAN

#include "Servo.h"

Servo myservo;  // create servo object to control a servo, a maximum of eight servo objects can be created
Servo mysecondservo;              // servo 2
Servo mythirdservo;              // servo3
Servo myfourthservo;              // servo4

int pos = 0;    // variable to store the servo position

void setup()
{
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
 mysecondservo.attach(10); // attaches the servo on pin 10 to the servo object
 mythirdservo.attach(8); // attaches the servo on pin 8 to the servo object
 myfourthservo.attach(11); // attaches the servo on pin 11 to the servo object
}


void loop()
{
unsigned long start = millis();
int sweepsNotFinished;

do
    {
    unsigned long now = millis() - start;
    sweepsNotFinished = 0;
    sweepsNotFinished += sweep(now, 500, 1500, 90, 0, myservo); // 1/2 second delay then 1 second sweep from 90 to 0
    sweepsNotFinished += sweep(now, 0, 2000, 180, 75, mysecondservo); // no delay and 2 second sweep from 180 to 75
    sweepsNotFinished += sweep(now, 250, 10000, 30, 100, mythirdservo);  // 1/4 second delay, then 9.75 second sweep from 30 to 100
   } while (sweepsNotFinished > 0);
}

int  sweep(unsigned long currentTime, unsigned long startTime, unsigned long endTime, int startPosition, int endPosition, Servo &servo)
{
if (currentTime < startTime)
    return 1;
if (currentTime > endTime)
    return 0;
servo.write( startPosition + (endPosition-startPosition) * (currentTime-startTime) / (endTime-startTime));
  return 1;
}

I understand how the delay works (I think?) but is that set of lines supposed to only apply to one servo? With that code I just have one servo which alternates between twitching and sweeping.

The code looks fine. Which servo is moving?

Are you sure you have all the servos connected correctly? Others have found that their servos act very strangely if they accidentally swap any two of the three wires.

Are you supplying enough power to drive multiple servos? Even one servo might be too much for USB power and four is probably too much to run off the Arduino 5V power line. You should have a separate 5 or 6 volt power supply for the servos. The Arduino ground should be connected to the servo's ground pin. The Arduino data pins should connect to the servo's signal pin.

Ok I've played with the numbers and I've got it much closer to where I need it to be (thankyouthankyou!). Here is my code now:

//QUADSweep
//edited from the original code by BARRAGAN

#include "Servo.h"

Servo myservo;  // create servo object to control a servo, a maximum of eight servo objects can be created
Servo mysecondservo;              // servo 2
Servo mythirdservo;              // servo3
Servo myfourthservo;              // servo4

int pos = 0;    // variable to store the servo position

void setup()
{
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object
 mysecondservo.attach(10); // attaches the servo on pin 10 to the servo object
 mythirdservo.attach(8); // attaches the servo on pin 8 to the servo object
 myfourthservo.attach(11); // attaches the servo on pin 11 to the servo object
}


void loop()
{
unsigned long start = millis();
int sweepsNotFinished;

do
    {
    unsigned long now = millis() - start;
    sweepsNotFinished = 0;
    sweepsNotFinished += sweep(now, 250, 10000, 0, 90, myservo);  // 1/4 second delay, then 9.75 second sweep from 30 to 100
    sweepsNotFinished += sweep(now, 0, 1000, 0, 180, mysecondservo);  // 0 second delay, then 9.75 second sweep from 30 to 100
    sweepsNotFinished += sweep(now, 1000, 8000, 0, 180, mythirdservo);  // 1 second delay, then 9.75 second sweep from 30 to 100
    sweepsNotFinished += sweep(now, 500, 5000, 0, 90, myfourthservo);  // 1/2 second delay, then 9.75 second sweep from 30 to 100
   } while (sweepsNotFinished > 0);
}

int  sweep(unsigned long currentTime, unsigned long startTime, unsigned long endTime, int startPosition, int endPosition, Servo &servo)
{
if (currentTime < startTime)
    return 1;
if (currentTime > endTime)
    return 0;
servo.write( startPosition + (endPosition-startPosition) * (currentTime-startTime) / (endTime-startTime));
  return 1;
}

My question now is that right now I feel like I have good control of the second half of the sweep, but not the first (ie. what controls the speed of the first half of the sweep in the code?) Also, is there a way to make all the sweeps more continuous? Right now, all the servos wait until all other servos have completed their loops before restarting--is there a way that the servos can run continuously, irregardless to where the other servos are in their loops?

I thought you wanted the sweeps to be synchronized in some way.

What you want is each servo repeatedly sweeping back and forth between two positions, each at a different rate?

here is another way to do it; using the slow speed modification to the servo library discussed in this thread: http://arduino.cc/forum/index.php/topic,61586.0.html

// speed controlled Servo Sweep
// see: http://arduino.cc/forum/index.php/topic,61586.0.html
//
// Michael Margolis 4 August 2011

#include <VarSpeedServo.h>

const int NBR_SERVOS = 4;       // the number of servos

VarSpeedServo Servos[NBR_SERVOS];        // servo objects


int servoPins[NBR_SERVOS]        = {8,     9,  10,  11}; // servo pins
int servoSpeeds[NBR_SERVOS]      = {1,    10, 100, 255}; // sweep speed, 1 is slowest, 255 fastest)
int servoMinPosition[NBR_SERVOS] = {10,   20,  30,  40}; // the minumum servo angle
int servoMaxPosition[NBR_SERVOS] = {120, 130, 140, 150}; // the maximum servo angle

void setup()
{
   for(int i=0; i < NBR_SERVOS; i++)  
   {
     Servos[i].attach(servoPins[i]);       
     Servos[i].slowmove(servoMinPosition[i],servoSpeeds[i]) ; // start sweeping from min position
   }
}

void loop()
{
  // sweep the servos
  for(int i=0; i < NBR_SERVOS; i++)
  {    
     if( Servos[i].read() == servoMinPosition[i])
       Servos[i].slowmove(servoMaxPosition[i],servoSpeeds[i]) ;         
     else if( Servos[i].read() == servoMaxPosition[i])
       Servos[i].slowmove(servoMinPosition[i],servoSpeeds[i]) ;           
  }  
}

mem:

int servoSpeeds[NBR_SERVOS]      = {1,    10, 100, 255}; // sweep speed, 1 is slowest, 255 fastest)

A word of warning about high servo speeds setting - 255 in this case: The updating of the servo happens faster that the servo is actually able to move. So in this example, you might end up with switching between the extreme positions at each PWM cycle for the servo. The resulting movement won't be a servo wiping left and right at a fast speed, but a servo twitching randomly in some random position. You probably need to decrease the speed from 255 to some lower value until your servos has enough time to complete the sweep. In my tests with the little servos I had, speeds over 128 were usually above the hardware speed of the servo and all looked the same.

Korman

@john wasser: yes, I just want the servos to act independently of each other and just to be ongoing, completely irregardless of each other.
@mem: thank you for your input, I'll try it a little bit later today and see if that works better
@korman: thank you I'll keep that in mind

Also, I might be turning my code over to more capable hands soon...thanks for all the input!

Hello,

This is very helpfull but my question is: I want my servo's to go in the opposite direction but I have no idea how to do it...
Can someone please help me?

Thanks!

I want my servo's to go in the opposite direction but I have no idea how to do it...

Servo one;
Servo two;

int pos = someValue;

one.write(pos);
two.write(180-pos); // Assumes that the servo limit is 180