Pages: [1]   Go Down
Author Topic: six legged walker  (Read 2400 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello

As a part of a design class at uni, we (a group of other folk and I) are making a six legged walker. We're using twelve servos to move the legs, two servos per leg, all of them controlled by an Arduino Uno. As usually happens with these things, we've run into some problems. Whenever the power is disconnected from the servos and reconnected, the legs start going mad (random angles, freezing, basically nothing like the gait programmed). Resetting the board doesn't always help. In fact, sometimes as many as 10 resets and/or reprogramming is necessary to sort it out. Anyone have any ideas as to why this might happen?

Knee servos are New Power XL-9HMB
Hip servos are Tower Pro SG-90
The board is Arduino Uno.
Programmed using Arduino 1.0 on Ubuntu 10.04.
Servos are currently powered from a K and H Products PP272 Powered Project Board (it's got 5V with a 1A fuse).
Legs are made of acrylic, are fairly light and the joints are definitely loose enough.

Any help/ideas appreciated.

EDIT: Probably worth adding the code as well.
Code:
#include <Servo.h>

//create servo objects, comments are aliases for short-hand notation
Servo hipFrontRight;     //FR
Servo hipMiddleRight;    //MR
Servo hipRearRight;      //RR
Servo hipFrontLeft;      //FL
Servo hipMiddleLeft;     //ML
Servo hipRearLeft;       //RL
Servo kneeFrontRight;    //FR
Servo kneeMiddleRight;   //MR
Servo kneeRearRight;     //RR
Servo kneeFrontLeft;     //FL
Servo kneeMiddleLeft;    //ML
Servo kneeRearLeft;      //RL

//software switch for convenience - if !1, then the loop routine is empty
int sw = 0;

//define the initial range and position of knees and hips
//polarity or ranges different for sides because of the way the servos
//are placed on the body
int hipRange = 10;
int kneeRange = 20;

int FRHipRange = 10;
int MRHipRange = 10;
int RRHipRange = 10;
int FLhipRange = 10;
int MLHipRange = 10;
int RLHipRange = 10;
int FRKneeRange = 20;
int MRKneeRange = 20;
int RRKneeRange = 20;
int FLKneeRange = 20;
int MLKneeRange = 20;
int RLKneeRange = 20;

int FRInitHip = 90;
int MRInitHip = 90;
int RRInitHip = 90;
int FLInitHip = 90;
int MLInitHip = 90;
int RLInitHip = 90;
int FRInitKnee = 90;
int MRInitKnee = 90;
int RRInitKnee = 90;
int FLInitKnee = 90;
int MLInitKnee = 90;
int RLInitKnee = 90;
 
//define speed of movement - smaller value gives higher speed
int movSpeed = 15;
 
//generic counter variable
int i = 0;

void setup()
{
  //attach servos to pins on the board
  hipFrontRight.attach(1);
  hipMiddleRight.attach(2);
  hipRearRight.attach(3);
  hipFrontLeft.attach(4);
  hipMiddleLeft.attach(5);
  hipRearLeft.attach(6);
  kneeFrontRight.attach(7);
  kneeMiddleRight.attach(8);
  kneeRearRight.attach(9);
  kneeFrontLeft.attach(10);
  kneeMiddleLeft.attach(11);
  kneeRearLeft.attach(12);
 
  //initialise servos to their initial positions
  hipFrontRight.write(FRInitHip);
  hipMiddleRight.write(MRInitHip);
  hipRearRight.write(RRInitHip);
  hipFrontLeft.write(FLInitHip);
  hipMiddleLeft.write(MLInitHip);
  hipRearLeft.write(RLInitHip);
  kneeFrontRight.write(FRInitKnee);
  kneeMiddleRight.write(MRInitKnee);
  kneeRearRight.write(RRInitKnee);
  kneeFrontLeft.write(FLInitKnee);
  kneeMiddleLeft.write(MLInitKnee);
  kneeRearLeft.write(RLInitKnee);
 
  if (sw == 0)
  {
    for (i = 0; i <= kneeRange; i++) //lift knees FR, RR, ML to initialise motion
    {
      kneeFrontRight.write(FRInitKnee - i);
      kneeRearRight.write(RRInitKnee - i);
      kneeMiddleLeft.write(MLInitKnee + i);
      delay(movSpeed);
    }
  }
}

void loop()
{
  if (sw == 1)
  {
    for (i = 0; i <= hipRange; i++) //hips FR, RR, ML go forwards, hips FL, RL, MR go backwards
    {
      hipFrontRight.write(FRInitHip + i);
      hipRearRight.write(RRInitHip + i);
      hipMiddleLeft.write(MLInitHip - i);
      hipMiddleRight.write(MRInitHip - i);
      hipRearLeft.write(RLInitHip + i);
      hipFrontLeft.write(FLInitHip + i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= kneeRange; i++) //lower knees FR, RR, ML
    {
      kneeFrontRight.write(FRInitKnee - kneeRange + i);
      kneeRearRight.write(RRInitKnee - kneeRange + i);
      kneeMiddleLeft.write(MLInitKnee + kneeRange - i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= kneeRange; i++) //lift knees MR, FL, RL
    {
      kneeMiddleRight.write(MRInitKnee - i);
      kneeFrontLeft.write(FLInitKnee + i);
      kneeRearLeft.write(RLInitKnee + i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= hipRange; i++) //all hips return to initial position
    {
      hipFrontRight.write(FRInitHip + hipRange - i);
      hipRearRight.write(RRInitHip + hipRange - i);
      hipMiddleLeft.write(MLInitHip - hipRange + i);
      hipMiddleRight.write(MRInitHip - hipRange + i);
      hipRearLeft.write(RLInitHip + hipRange - i);
      hipFrontLeft.write(FLInitHip + hipRange - i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= hipRange; i++) //hips FR, RR, ML go backwards, hips MR, FL, RL go forwards
    {
      hipMiddleRight.write(MRInitHip + i);
      hipRearLeft.write(RLInitHip - i);
      hipFrontLeft.write(FLInitHip - i);
      hipFrontRight.write(FRInitHip - i);
      hipRearRight.write(RRInitHip - i);
      hipMiddleLeft.write(MLInitHip + i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= kneeRange; i++) //lower knees FL, RL, MR
    {
      kneeMiddleRight.write(MRInitKnee - kneeRange + i);
      kneeRearLeft.write(RLInitKnee + kneeRange - i);
      kneeFrontLeft.write(FLInitKnee + kneeRange - i);
      delay(movSpeed);
    }
   
    for (i = 0; i <= kneeRange; i++) //lift knees ML, FR, RR
    {
      kneeMiddleLeft.write(MLInitKnee + i);
      kneeFrontRight.write(FRInitKnee - i);
      kneeRearRight.write(RRInitKnee - i);
      delay(movSpeed);
    }   
   
    for (i = 0; i <= hipRange; i++) //all hips return to initial position
    {
      hipMiddleRight.write(MRInitHip + hipRange - i);
      hipRearLeft.write(RLInitHip - hipRange + i);
      hipFrontLeft.write(FLInitHip - hipRange + i);
      hipFrontRight.write(FRInitHip - hipRange + i);
      hipRearRight.write(RRInitHip - hipRange + i);
      hipMiddleLeft.write(MLInitHip + hipRange - i);
      delay(movSpeed);
    }
  }
}
« Last Edit: March 13, 2012, 10:46:30 am by kbaumen » Logged

Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 39
Posts: 5551
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

5V @ 1 amp is not likely enough to power 12 servos at one time (a single standard servo can easily pull up to amp of current by itself, under load; yours are smaller servos though); what is powering the Arduino? You should first figure out a few things before delving into the code as being an issue:

1) How much current does a single servo take (and since you are using two different brands of servos - measure each) - when under load and without a load?
2) How many servos are going to running under load -at the same time-?

Multiply the maximum current from 1) with the number of servos from 2) - this will give you a rough number of the amount of current needed for the servos. Add an extra 250-300 mA or so for the Arduino (if being powered by the same supply).

I have a feeling you are trying to run the servos from the same supply as the Arduino (this is just a guess though; it isn't clear from your post); if so, likely a current sag is happening, causing the Arduino to constantly reset. Given that you can -sometimes- get it to work, I wonder if you are somehow right on the edge of what is needed current wise, and sometimes things "settle" just right (or not as many servos move at one time in a gait cycle, or the same number aren't loaded, or something), allowing it to work briefly?
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

Gosport, UK
Offline Offline
Faraday Member
**
Karma: 21
Posts: 3113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
 hipFrontRight.attach(1);

Quite possibly not the problem as you aren't doing serial comms, but it's not always wise to use the serial TX pin for anything else.
Logged

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

5V @ 1 amp is not likely enough to power 12 servos at one time (a single standard servo can easily pull up to amp of current by itself, under load; yours are smaller servos though); what is powering the Arduino? You should first figure out a few things before delving into the code as being an issue:

1) How much current does a single servo take (and since you are using two different brands of servos - measure each) - when under load and without a load?
2) How many servos are going to running under load -at the same time-?

Multiply the maximum current from 1) with the number of servos from 2) - this will give you a rough number of the amount of current needed for the servos. Add an extra 250-300 mA or so for the Arduino (if being powered by the same supply).

I have a feeling you are trying to run the servos from the same supply as the Arduino (this is just a guess though; it isn't clear from your post); if so, likely a current sag is happening, causing the Arduino to constantly reset. Given that you can -sometimes- get it to work, I wonder if you are somehow right on the edge of what is needed current wise, and sometimes things "settle" just right (or not as many servos move at one time in a gait cycle, or the same number aren't loaded, or something), allowing it to work briefly?

Thanks for the quick reply.

Currently I don't have the calculations with me but the power supply is enough for this sort of testing. Currently the robot is just sitting on the bench and legs are moving freely in the air. Besides, if they were drawing more than an amp, the fuse would've burned out on the board. Of course for it to actually walk, we will need more current.

The board has its own battery to power it (or sometimes the USB cable connected to my laptop). So there shouldn't be any current sags when starting the servos.
Logged

Phoenix, Arizona USA
Offline Offline
Faraday Member
**
Karma: 39
Posts: 5551
Where's the beer?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the quick reply.

Currently I don't have the calculations with me but the power supply is enough for this sort of testing. Currently the robot is just sitting on the bench and legs are moving freely in the air. Besides, if they were drawing more than an amp, the fuse would've burned out on the board. Of course for it to actually walk, we will need more current.

The board has its own battery to power it (or sometimes the USB cable connected to my laptop). So there shouldn't be any current sags when starting the servos.

Ok - it wasn't clear on the first post you were doing this (good idea, though!) - so, I would defer to dxw00d's suggestion (you might have to resort to using an analog input pin as a digital pin; though I would suggest going with a separate servo controller)...

smiley
Logged

I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 158
Posts: 2882
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've played with many kinds of servos. I second the idea that a 1-Amp supply isn't nearly
enough current for 12 servos, no matter that the fuse doesn't blow, or whatever else
you might think. Maybe the supply simply drops out momentarily, and the servo control
loops go bonkers.  I also doubt that your USB port can supply enough current.

I always use 5-6 NiMH rechargeable AA-cells in series to power my walking robots, and
they will easily provide enough juice for 12 standard servos [44 oz-in]. Allow about 300-mA
for each standard servo, so the supply needs to be in the 4-Amp range. You need to know
how much current your particular servos draw, for starters.

Also, many servos go totally berserk, and run over to the mechanical stops, when the +V
voltage drops too low. Also, on many types, when you first apply power, the servo horns jerk
a bunch of degrees. My GWS servos will move over 90-180 degrees if I power them on/off a few
times. I don't know about your particular type. These issues have long been a problem with
walking robots.
Logged

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

I've played with many kinds of servos. I second the idea that a 1-Amp supply isn't nearly
enough current for 12 servos, no matter that the fuse doesn't blow, or whatever else
you might think. Maybe the supply simply drops out momentarily, and the servo control
loops go bonkers.  I also doubt that your USB port can supply enough current.

I always use 5-6 NiMH rechargeable AA-cells in series to power my walking robots, and
they will easily provide enough juice for 12 standard servos [44 oz-in]. Allow about 300-mA
for each standard servo, so the supply needs to be in the 4-Amp range. You need to know
how much current your particular servos draw, for starters.

Also, many servos go totally berserk, and run over to the mechanical stops, when the +V
voltage drops too low. Also, on many types, when you first apply power, the servo horns jerk
a bunch of degrees. My GWS servos will move over 90-180 degrees if I power them on/off a few
times. I don't know about your particular type. These issues have long been a problem with
walking robots.


Cheers for the tips. We'll have a look at using a different power supply for testing and I'll post some results/issues then.
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A small servo hexapod that might be of interest. As to power search ebay for UBEC to see the better and inexpensive power converters used with servos.

http://letsmakerobots.com/node/19257
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

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

A small servo hexapod that might be of interest. As to power search ebay for UBEC to see the better and inexpensive power converters used with servos.

http://letsmakerobots.com/node/19257


Ha, that is very cool. Moves a lot like the

We tested ours with a power source that can supply up to 5 amps (when legs move freely, the servos draw at most 200 mA, thus 2.4 would've sufficed) and got exactly the same behaviour. We'll keep using it, since oric_dan(333)'s post makes sense, but it didn't solve the problem. Any other ideas?
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Whenever the power is disconnected from the servos and reconnected, the legs start going mad (random angles, freezing, basically nothing like the gait programmed).

Have you tried putting some delay between the initialization of each servo so the servos are not all initialized at the same time?
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 158
Posts: 2882
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looking at your code, I'd say several things.

First off, disconnect 11 of the servos, and write a simple routine to test just one, using
very simple movements. Just move the servo back and forth, and don't worry about trying
control the speed. Get that to work first, then, add more servos and speed control.

Secondly, increase the MoveSpeed from delay(15) to something like delay(50). The
standard servo update rate is 20-msec, which is what I suppose the Servo library uses
invisibly, and you're changing the position value faster.

Thirdly, I'm not sure you can connect a servo to pin 1, as that is used by the Arduino
serial port, ie, connected to the USB chip. 
Logged

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

Cheers for the answers guys.

I will try putting some delay between the initialization of the servos and reduce the moving speed to see what happens.

Nothing is connected to pin 1 now, the code is slightly outdated (it was up to date when I posted it).

I have tried simple routines with the servos (with one and six at a time) and never encountered such a problem. This only started happening with all 12 running at the same time. And on the first attempts it wasn't as bad but lots of things had to be mechanically adjusted and eventually it got worse.

I will see the robot again on Tuesday afternoon, so that's when I'll post an update.
Logged

Pages: [1]   Go Up
Jump to: