Moving multiple servos at the same time using 16ch servo dri

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
SeattleDucati
 
Posts: 3
Joined: Mon Sep 23, 2013 9:12 am

Moving multiple servos at the same time using 16ch servo dri

Post by SeattleDucati »

I am using an Arduino mega and the adafruit 16ch servo driver board to power a hexapod.

I've got my leg movements working for a single leg. But I can't figure out how to have multiple legs moving at the same time. Below is the code I use to life a single leg:

//*******Front Left Leg
for (uint16_t liftpulselen = Llifttop; liftpulselen < Lliftbottom; liftpulselen++)
{
pwm.setPWM(frontleftlift, 0, liftpulselen); //No delay within the loop, servo moves at max speed.
delay(liftspeed); //This delay within the loop controls the servo speed
}

How can I have 3 legs lift at the same time? I have broken the leg movements down into different functions, and regardless of how I go about it, everything is handled sequentially.

Any insights appreciated. Thank you.

Thank you?

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Moving multiple servos at the same time using 16ch servo

Post by adafruit_support_mike »

It requires a shift in mindset.

Instead of thinking, "what does this leg need to do over its whole motion sequence?", you need to approach the problem in terms of "what does each leg need to be doing right now?"

To get all math-theory about it, you want a function `motionForMotorAtTime( M, T )` where M identifies a specific motor and T is a specific instant in time. The goal is to be able to feed any motor/time pair into that function and get a value that describes what that motor should be doing at that instant.

Once you have that, updating the motors becomes simple.. you just ask, "what time is it?" then run through the list of motors getting motion parameters for each one at that instant.

To write such a function, it helps to start with a big pad of graph paper and start marking out descriptions for each motor along a time axis. That's usually a long and error-filled process, so just go into it with the decision to enjoy practicing your wastepaper bin hook shots. The more times you redraw the diagrams, the better you'll understand how to reduce the whole thing to a uniform description procedure.

SeattleDucati
 
Posts: 3
Joined: Mon Sep 23, 2013 9:12 am

Re: Moving multiple servos at the same time using 16ch servo

Post by SeattleDucati »

Quite a bit more involved than any controller I have used before.

So if I'm understanding you correctly, I will be feeding a constant stream of position data to a function(s) that update each individual servo. The math that determines each servos position will occur as a separate function, and will be constantly fed to a function(s) to tell the servos where they are supposed to be. Instead of issuing orders and expecting them to carried out, I'll be feeding the 'troops' real time data on where they are supposed to be.

In psuedo code, I will replace:

For (Servo position is X, move it until position is Y, variable++)
{Update one servos position}

With

void loop(){
Variable(servo position) is X
{update 3 servos}
X = X +1 (until desired final position is reached)
}

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Moving multiple servos at the same time using 16ch servo

Post by adafruit_support_mike »

You've got it.

The idea of breaking motion down into a series of instantaneous positions seems intimidating at first, it gets easier as you do it a few times. There are two good things about the technique:

First, each "where should I be at instant T?" function is independent of all the others. You can work out the description for each servo without having to know what any other servo is doing. The method also scales easily.. if running one servo is a matter of saying, "you go here", adding another is just a matter of saying, "and you go there". You don't have to get fancy until your list is so long that you can't get all the way through it before the next update cycle needs to begin. A hexapod won't bring you anywhere near that limit.

Second, the technique works nicely with what's called 'tabular programming': the easiest way to build a "where should I be at instant T?" function for a servo is to store a bunch of pulse widths in a list:

Code: Select all

/*  A servo expects to see 50 pulses every second, so here are
    explicit widths for each one.
*/
int pulseWidth[] = {
    168, 186, 204, 222, 240,
    258, 276, 294, 312, 330,
    348, 366, 384, 402, 420,
    438, 456, 474, 492, 510,
    528, 546, 564, 582, 600,
    582, 564, 546, 528, 510,
    492, 474, 456, 438, 420,
    402, 384, 366, 348, 330,
    312, 294, 276, 258, 240,
    222, 204, 186, 168, 150,
};
It's bulletproof, there's practically no processing involved, and you don't have to write new code to change the way each servo behaves.. you just put different values into the table. It uses a lot of memory though, which is a problem for microcontrollers.

You buy memory back by creating functions that would populate such a table, then calling those rather than creating actual tables. You have to do a bit more programming, and modifying the motion isn't quite as easy, but you can still adjust the servo motion profiles one at a time.

As a general tip, most walking motions break down into joints moving sinusoidally, just offset from each other in phase. That makes it pretty easy to create the motion descriptions.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”