Can I control two servos simultaneously?

Hi!
I am a beginner with Arduino and code.
I am french, sorry for my english.

I would like to move 2 servos, independently but simultaneously ...?!
I must use the function just below because I would like to get slow and fluid movement. I don't know if exist a better solution, but the result is not to bad.

for(pos = 0; pos < 180; pos += 1)
{
servo.write(pos);
delay(25);
}

But I can't control another servo until the movement is done.
My question is: Someone understand anything? If yes, is there a better solution?

Thank you for your attention and sorry for mistakes.

You can control both by iterating them like so

for(pos = 0; pos < 180; pos += 1)
{
for(pos2 = 180; pos2 > 0; pos2 -=1)
{
servo.write(pos);
servo2.write(pos2);
delay(25);
}
}

Would you explain a bit more about what you want to do?

I assume you'd like to move each servo a bit at a time.

If that's the effect you want, you do NOT want to use two for loops:

for(pos = 0; pos < 180; pos += 1)
{
   for(pos2 = 180; pos2 > 0; pos2 -=1)
  { 
    servo.write(pos);
    servo2.write(pos2);
    delay(25);
  }
}

This will move servo 2 from 180 degrees to 0 after each 1 degree movement of servo, i.e. servo2 will move from 180 to 0, but 180 times for every time servo moves.

One way to think about the effect you want is to pretend you are making a "Wallace & Grommet" stop frame animation.

Each frame must contain the little bit of movement of each servo.
It may be that you want servo to get to it's final position before servo 2, so think of it as two scenes, one with both moving, and one with only servo2 moving.
I do this by planning the whole effect on a piece of paper.
To be fair, I usually convert the movements for each scene to some values in an array, and drive the whole thing from data, but let me focus on an approach.

So, if you want servo1 to move twice as fast as servo2:

#include <Servo.h> 
 
Servo servo1;  // create servo object to control a servo 
Servo servo2;  // create servo object to control a servo 
 
int pos1;      // angle of servo 1
int pos2;      // angle of servo2
 
void setup() 
{ 
  servo1.attach(9);  // attaches the servo on pin 9 to the servo object 
  servo2.attach(10);  // attaches the servo on pin 10 to the servo object 
} 
 
void loop() 
{ 
      // Scene 1: 
  for (int i=0; i<45; i += 1) {
    pos1 = 90 - i;              // servo1 from 90 to 45 degrees
    pos2 = 0 + (i*2);           // servo2 from 0 to 90 degrees
    
    servo1.write(pos1);
    servo2.write(pos2); 
    delay(15);                           // waits for the servo to get there   
  }
 
     // Scene 2 
  for (int i=0; i<60; i += 1) {
    pos1 = 45;                  // servo1 doesn't move
    pos2 = 90 + i;              // servo2 from 90 to 150 degrees
    servo1.write(pos1);
    servo2.write(pos2); 
    delay(15);                           // waits for the servo to get there 
  }
}

Add as many scenes as you need.

Once you feel comfortable with this approach, you might like to try describing each scene as the few numbers that change at each frame. Then have a look at using arrays (of struct), and see if you can make a 'player' which can perform all the scenes based on the numbers. Then you can edit the whole 'movie' by adjusting a few numbers.

HTH
GB-)

I don't know if exist a better solution, but the result is not to bad.

I think your idea of using a loop to step position from current to desired is just fine. You need however move away from using delay() (as it will block execution) and rather rely on time intervals.

The following code fragment may give you some ideas on how this can be implemented in Arduino.

#define SERVO_SPEED 25  (minimum number of milliseconds per degree)

int servo1_pos;  // desired angle for servo1
int servo2_pos;  // desired angle for servo2

void loop()
{
  static unsigned long servo_time;
  
  // check time since last servo position update 
  if ((millis()-servo_time) >= SERVO_SPEED) {
    servo_time = millis(); // save time reference for next position update
    
    // update servo1 position
    // if desired position is different from current position move one step left or right
    if (servo1_pos > servo1.read()) servo1.write(servo1.read() + 1);
    else if (servo1_pos < servo1.read()) servo1.write(servo1.read() - 1);

    // update servo2 position
    // if desired position is different from current position move one step left or right
    if (servo2_pos > servo2.read()) servo2.write(servo2.read() + 1);
    else if (servo2_pos < servo2.read()) servo2.write(servo2.read() - 1);
  }
}

You should be able to scale this to "any number" of servos and still have plenty processing capacity for other tasks.

1 Like

BenF

I agree a simple blocking solution it not nice. but a busy wait isn't great either :slight_smile:
There are several ways to solve these sorts of problem.

When Coretin gives a bit more detail, I'm confident that we can help find a good solution.

I'd add:

  1. if all Corentin wants to do is control two servo's, there isn't anything else to solve. Avoid "Premature Optimisation" :slight_smile:
    (Program optimization - Wikipedia)

  2. If the problem is elegantly represented as a data-driven 'script', it is practical to avoid blocking in the 'script player'.

  3. Your code example contains links to time intervals, or more correctly servo speed, too via the value of SERVO_SPEED. If the servos are different and move at different rates (which is quite common), the solution becomes more complex.

Anyway. I'll wait to hear from Corentin. You may have nailed it.
GB-)

BenF & gbulmer, your two posts are real eye opener for us rookies. :-?

Just one question: can Arduino possibly multitask / use threads. With threads one would be able to effectively run two pieces of code simultaneously and control two (three, four) servos at once.

Can you, please, elaborate on the question of gbulmer's delay() v BenF's mills() solutions. I would say mills() solution is better, because you can do other things with those CPU cycles, which would be blocked during gbulmer's delay().

aviva life insurance

DROBNJAK

Assuming we agree that a single core simulates multitasking/threading ...

Yes, you could use threads

There is DuinOS http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256745982/0

I believe someone has done some work with FreeRTOS, but I don't see it listed (http://www.freertos.org/)

I believe there is a threading simuation for AVR in TinyOS (http://www.tinyos.net/)

The servo library uses interrupts internally to simulate multi-threading (look for servo.cpp), and does support 12 servos/timer. It isn't limited to the number of PWM pins.

This is the sort of technique I might use to drive servo's to a 'script'.
The interrupt service routine (on a different interrupt to the servo library) would simply pick up the next thing to do (stored as data), do it, look in the script for the next action, and adjust the timer to trigger itself when it's needed.

If the need is purely an issue of driving the servo's at a slower speed than maximum, I might be tempted to extend the servo library.

I'd consider adding a servo.write(angle, duration) to make the servo move through the 'angle' and take 'duration' to do it. I like that approach because it puts the problem into a place which is waking up to adjust the servo pulse duration anyway. If I went that far, I'd probably have the servo.attach(), or some new setup-method, take a servo speed parameter to make it work well.

Otherwise, millis() is more appealing than delay(). BUT, please avoid Premature Optimisation :slight_smile:

HTH
GB-)

Hi!

I'll wait to hear from Corentin. You may have nailed it.

...Yes.

I repeat my englih is bad, I take time to decrypt your ideas and also codes. :-[
But I undustand almost all about yours greats proposals! :wink:

Few details to clarify my intention:
I am not creating an animation movie but near, animating a puppet:
I have 3 servos. I would like to begin the second movement of the servo when the first did not finish his race.
Each servo has a specific "couple speed/angle".
More precisely: I am constructing a "Jack in a box". There is a switch front to the box.
When you turn-it ON, the box box opens slowly, Jack get up and his hand move slowly, turn OFF the switch and return quickly on his initial position at the same time the box is closing. (sorry if it's not very clear)

For the end it's easy (return to initial position and closing the box: using servo.write(0) function for each servo, it's instantaneous) but for begining I have to open the box slowly and a little moment after, the puppet get up and move his hand ... simultaneously".

So gbulmer's proposal semms to be appropriate for what I want.
The construction of the code with scenes interests me because I want "cut" mouvements to have acceleration, decelaration, stop ...
So I have to try with this proposition, and I will tell you if results are conclusives.
Thank you for this help!

You need however move away from using delay() (as it will block execution) and rather rely on time intervals.

I should take a look at your proposal BenF, it semms to be a more "flexible" function but a little bit hard to use for me, for the moment! :wink:

Thank you very much gentlemen, I will try all I can with your solutions and see you soon!

So, basically, you are trying to make one of these:

:-?

just with an Arduino instead of a 555 timer chip. :-/

Is the one you want to make more elaborate than that? If not, you don't really need more than one servo. The arm on those opens the lid.

Would like to see what you have planned.

Dan

O.K.
Didn't read it all very well. :-[

You can use one servo to open the box, then use a second servo to move the puppet up and swing his arm out. Then you would not have to worry about two servos moving at the exact same time. :-?

Just a thought.

As Photo-Worx's link shows, something like this can be achieved quite simply. But if you wanted a more elaborate animation, one way to achieve that is to store the servo positions for small movement steps as data.

For example, you can store a minutes worth of action for three servos as 180 bytes of data using steps of one second (you can double this for finer steps, or reduce the size if your animation duration is shorter)

Anyway, the idea is that you store the desired servo positions for each time step in a data array and read them back to drive the servos. You can store up to a thousand steps in EEPROM on a standard Arduino board.

I'd consider adding a servo.write(angle, duration) to make the servo move through the 'angle' and take 'duration' to do it. I like that approach because it puts the problem into a place which is waking up to adjust the servo pulse duration anyway. If I went that far, I'd probably have the servo.attach(), or some new setup-method, take a servo speed parameter to make it work well.

gbulmer, if you are interested in pursuing this I would be happy to consider a speed option for the servo library. Start a new thread and put a link to here if you have some suggestions on how this could be implimented

mem

gbulmer, if you are interested in pursuing this I would be happy to consider a speed option for the servo library. Start a new thread and put a link to here if you have some suggestions on how this could be implimented

I'm busy for the next few days (it is 3am here, and still typing), but Ill try to make time next week, if that's okay.

Cheers
GB-)

its up to you. I have not seen much demand for having a speed capability in the library so its not been a high priority.

I have no idea how popular the servo library is. I wrote my own simple stuff using the 16 bit timer a while ago. Maybe it's one of those things which "isn't useful until it exists"?

My interest is stimulated by low-cost robot arms. I have one, but it is so low-cost it isn't servo's but just DC motors, so I will have to build all of the position encoding and feedback myself. We thought something more sinuous would look more intriguing.

I'll have a look
GB-)

I have no idea how popular the servo library is.

Google has over 100,000 hits for Arduino Servo and there are lots of active threads here on servo topics relating to the library. Some people do roll their own servo code or use external hardware, but I think most use the Arduino servo library.
Controlling speed of movement has been mentioned occasionally on the forum, but I get the sense that this is not considered a needed capability by most.

That's not to say that people would not find it very useful if it was available.

mem - I apologise if I caused offence. I wasn't trying to suggest that the servo library isn't used, just that I haven't used it, but do use servo's, and I/we felt a slower movement might be interesting.

More preciously, the feeling was based on some movie CGI effects where several movements are co-ordinated to simultaneously arrive at a single common goal, rather than be governed by the rate of each servo. The angle+duration thought was my simple way to get the effect. I haven't built any working examples, so I am happy to play with this off-line until we do.

I also feel 'bloating' the standard libraries, with features which very few have a need for, reduces the quality of the Arduino platform for the vast majority (especially when the code is Open Source). So I am happy to hack the code to satisfy a need, but I wasn't expecting the hacks would necessarily go into the main development line.

Okay?
GB

gbulmer, no need to apologise, no offense was taken - my reply was intended as a simple answer to the question you asked in your post.

I completely agree with your comment about avoiding feature bloat, but would be happy to help if you wanted to explore how users could add speed control to the library if this capability was required.

Lets see if these comments about servo speed control get responses from other readers.

have fun!

Hi!
Lot of reading!
Sorry if I don't quicly answer, I am student and I have no compter at home! :o
So I work on this projet and answer when I can ...
But thank you very much for help wich you bring me.

So, basically, you are trying to make one of these:
http://www.instructables.com/id/The-Most-Useless-Machine/?ALLSTEPS
Huh

just with an Arduino instead of a 555 timer chip. Undecided

Is the one you want to make more elaborate than that? If not, you don't really need more than one servo. The arm on those opens the lid.

Would like to see what you have planned.

Dan

O.K.
Didn't read it all very well

I am tying to make a box like this but more elaborate, with a better quality of movement: slowly and smoothy.
I would like to decompose movements to personify the puppet. I have already worked about.
But the challenge is to command two movements at the same time.
It can be possible with a lot of work, few patience.
Thanks to gbulmer and Benf for for the solutions you bringed me.

I hope I can take time to work harder on this project in the next days.
I inform you of news as quickly as posible!

My interest is stimulated by low-cost robot arms. I have one, but it is so low-cost it isn't servo's but just DC motors, so I will have to build all of the position encoding and feedback myself.

OWI Flex?

I've been thinking about picking one up myself for S&Gs; maybe set things up to detect limits via current monitoring. Part of me wants to hook one up to my Color Computer.

What's been stopping me (besides a ton of other projects in the queue) has been thoughts of re-creating a lightweight, low-cost version of the Armdroid arm, using foamcore or coroplast for the "body" of the arm, and adapting standard servos in some manner to allow their use at the base of the arm (so the arm doesn't have to move as much mass in the form of servos, which I think of as a step backward from the old arms of the 1980's - then again, servos are lighter and stronger, so maybe not?).

As a kid, I always wanted a robot arm for my computer; the closest I got was getting a Tomy Armatron for my birthday. Later I picked up a Popular Electronics magazine that described how to hook it up to a C=64 or Vic-20 (lots of hardware mods for that); I didn't understand anything about the electronics or hardware mods at the time, but it was a fascinating article that I kept around (and later scanned and put online - I need to put that back up on my website, now that I think about it).

By the time I had the knowledge and tools to do it, I can't bring myself to mod either of my Armatrons (I have two now; my original Tomy version, and a Radio Shack version), mainly because of fears that 10 years down the line I will find out I have "destroyed" something valuable on the collectors market (I collect Tomy robots). Even so, I may still snatch up a Radio Shack version for such crude hacking (I even have the motors used in the article; they were an item Radio Shack sold, and I bought 8 of them in two packs of four for future use).

Well, enough reminiscing...

:slight_smile:

OWI Flex?

It's this robot arm

I've been thinking about picking one up myself for S&Gs; maybe set things up to detect limits via current monitoring.

My thought too. The OpenServo folks have an ATmega friendly technique.

... adapting standard servos in some manner to allow their use at the base of the arm (so the arm doesn't have to move as much mass in the form of servos, ....

I've had a similar design idea in mind. I'd like to make a spider-like hexapod.
I'm hoping to get access to a CNC milling machine, or laser cutter to try it out (6 identical legs are a bit much for me to make)

If you get anywhere, please write about it.

GB-)