Go Down

Topic: six legged walker (Read 2 times) previous topic - next topic

kbaumen

Mar 13, 2012, 04:43 pm Last Edit: Mar 13, 2012, 04:46 pm by kbaumen Reason: 1
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: [Select]
#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);
    }
  }
}

cr0sh

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?
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

dxw00d

Code: [Select]
 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.

kbaumen


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.

cr0sh


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

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

Go Up