Pages: [1]   Go Down
Author Topic: Simultaneous but different servo sweeps with four servos  (Read 3160 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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(smiley-cool; // 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
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

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

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;

}
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

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

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

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 547
Posts: 45982
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

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

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

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

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

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:

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, 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?
« Last Edit: August 03, 2011, 06:39:32 pm by cloudsabio007 » Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 178
Posts: 8064
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
// 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]) ;           
  } 
}

Logged

Central Europe
Offline Offline
Edison Member
*
Karma: 6
Posts: 1220
Use the Source, Luke.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

@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!

Logged

Pages: [1]   Go Up
Jump to: