Stomper

First off, let’s get a few facts straight:

  • It walks albeit with heavy steps, which is quite obvious, considering the fact that it has ankles of metal and feet of acrylic and rubber.
  • It needs an external power bank to power the Arduino Nano R3 due to power supply fluctuations.
  • It has no sensors at all.

So what is it? Stomper is my very first attempt at making a bipedal walker. As a matter of fact, it’s my first legged robot ever! Needless to say, it received it walks rather heavily, hence the name.

Major Components:

Skeletal view of Stomper showing all six joints (i.e. 6 degrees of freedom) prior to inclusion of voltage regulation circuitry, motor driver, battery, Arduino and feet.

As you may have seen (in the video above), walking is much more difficult than kicking! Various issues presented themselves over the course of one month. The bipedal walker started out with 4 degrees of freedom (DOF). Functioning with just 4 plastic-geared servo motors sounded like a good design. However, the bot was too stable to break out of its stable static equilibrium. In a word: It was too well balanced! So between the first version and what Stomper finally turned into, there were several changes in the following:

Design

Now, I can’t quite remember who said “Walking is falling in style,” but I have much to thank this person for. Realising that the centre of gravity was too low for the walker to shift its feet, the setup was changed to include two more servo motors.

Stomper’s new design utilises 6 servo motors. The original plastic-geared servos are used as hip and knee joints while the new metal-geared servos are ankle joints.

As far as the feet were concerned, an old rubber slipper came in handy to act as a shock absorber while simultaneously providing a very sturdy grip on the floor. The aluminium servo connectors’ light weight made them the ideal choice for a small walker’s legs.

Battery

The power supply had to be modified. It started out being a 4.8V Ni-MH battery (1.2v x 4 individual dry cells), but was replaced by a 7.4v Li-ion battery pack with a 7806 IC reducing the supply voltage to almost 5v. I know that in principle, the IC’s output should have been about 6v, but factoring in a dropout voltage, you’ll understand why (unless the input is twice the rated voltage or more), there is always a loss of approximately 1v.

Circuitry & electronics

Perhaps it would also be noteworthy mentioning that I  added a 470 microfarad electrolytic capacitor to the corresponding pins given on the 16-channel servo driver board. The company says that it is only required for high-power applications to reduce power supply fluctuations, but I found it rather useful for Stomper too. The unexpected motor ‘spasms’ greatly reduced, though they didn’t stop altogether until I plugged the Arduino to an external power bank (that’s the white cable you see in the video).

Code (Written in the Arduino IDE)

For all you geeks out there, here’s the code for a decent 6 DOF bipedal walker. Or, given the heavy nature of its gait, should I say Stomper?

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  156 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  545 // this is the 'maximum' pulse length count (out of 4096)

//Code written by Raunak Hede
///////////////////////////
#define s0 95
#define s1 95
#define s2 95
#define s3 95
#define s4 90
#define s5 85
///////////////////////////
//http://raunakhede.com
void setup()
{
  Serial.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  //If frequency is changed, SERVOMIN and SERVOMAX will change! Please update them accordingly.
  standingwalker();
  delay(2000);
}
void servo(int servonum, int degrees)
{
  float pulselength = constrain(map(degrees, 0, 180, SERVOMIN, SERVOMAX), SERVOMIN, SERVOMAX);
  pwm.setPWM(servonum, 0, pulselength);
}

void standingwalker() //feet aligned
{
  servo(0, 95);  servo(1, 95);
  servo(2, 95);  servo(3, 95);
  servo(5, 85);  servo(4, 90);
        delay(1000);
}

void loop()///////////////////................................. 
{
  ltilt();
  rightfootstraighten();
  rightkneebend();
  rightlegforward();
  rightforwardbias();
  rtilt();
  leftfootstraighten();
  leftkneebend();
  leftlegforward();
  leftforwardbias();
  //standingwalker();
  //delay(10000);
}

void ltilt()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5+30);  servo(4, s4+50);
  delay(1000);
}

void rightfootstraighten()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5+40);  servo(4, s4+20);
        delay(1000);
}

void rightkneebend()
{
  servo(0, s0);  servo(1, s1+45);
  servo(2, s2);  servo(3, s3+45);
  servo(5, s5+45);  servo(4, s4+20);
        delay(1000);
}

void rightlegforward()
{
  servo(0, s0+40);  servo(1, s1+40);
  servo(2, s2+30);  servo(3, s3+30);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void rightforwardbias()
{
  servo(0, s0+10);  servo(1, s1+70);
  servo(2, s2+30);  servo(3, s3+30);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void rtilt()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5-50);  servo(4, s4-25);
        delay(1000);
}

void leftfootstraighten()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5-15);  servo(4, s4-30);
        delay(1000);
}

void leftkneebend()
{
  servo(0, s0-45);  servo(1, s1);
  servo(2, s2-45);  servo(3, s3);
  servo(5, s5-20);  servo(4, s4-30);
        delay(1000);
}

void leftlegforward()
{
  servo(0, s0-40);  servo(1, s1-40);
  servo(2, s2-35);  servo(3, s3-35);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void leftforwardbias()
{
  servo(0, s0-70);  servo(1, s1-10);
  servo(2, s2-40);  servo(3, s3-40);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

 

And here’s the special code for kicking a sponge ball, though it can also kick a weight as heavy as a tennis ball 🙂

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  156 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  545 // this is the 'maximum' pulse length count (out of 4096)

//Code written by Raunak Hede
///////////////////////////
#define s0 95
#define s1 95
#define s2 95
#define s3 95
#define s4 90
#define s5 85
///////////////////////////
//http://raunakhede.com

void setup()
{
  Serial.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  //If frequency is changed, SERVOMIN and SERVOMAX will change! Please update them accordingly.
  standingwalker();
  delay(2000);
}
void servo(int servonum, int degrees)
{
  float pulselength = constrain(map(degrees, 0, 180, SERVOMIN, SERVOMAX), SERVOMIN, SERVOMAX);
  pwm.setPWM(servonum, 0, pulselength);
}

void standingwalker() //feet aligned
{
  servo(0, 95);  servo(1, 95);
  servo(2, 95);  servo(3, 95);
  servo(5, 85);  servo(4, 90);
        delay(1000);
}

void loop()///////////////////................................. 
{
  for(int i=0; i<2; i++)
  {
    WALK();
  }
  KICK();
  delay(20000);
}

void WALK()
{
  ltilt();
  rightfootstraighten();
  rightkneebend();
  rightlegforward();
  rightforwardbias();
  rtilt();
  leftfootstraighten();
  leftkneebend();
  leftlegforward();
  leftforwardbias();
}

void KICK()
{
  standingwalker();
  ltilt();
  rightfootstraighten();
  rightkneepullback();
  rightforwardbend();
  rightkick();
  standingwalker();
  delay(10000);
}

void ltilt()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5+30);  servo(4, s4+50);
  delay(1000);
}

void rightfootstraighten()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5+40);  servo(4, s4+20);
        delay(1000);
}

void rightkneepullback()
{
  servo(0, s0-20);  servo(1, s1+40);
  servo(2, s2);  servo(3, s3+50);
  servo(5, s5+40);  servo(4, s4+20);
        delay(1000);
}

void rightforwardbend()
{
  servo(0, s0-60);  servo(1, s1+60);
  servo(2, s2);  servo(3, s3+60);
  servo(5, s5+40);  servo(4, s4+20);
        delay(1000);
}

void rightkick()
{
  servo(0, s0+30);  servo(1, s1);
  servo(2, s2);  servo(3, s3-45);
  servo(5, s5+40);  servo(4, s4+20);
        delay(1000);
}

void rightkneebend()
{
  servo(0, s0);  servo(1, s1+45);
  servo(2, s2);  servo(3, s3+45);
  servo(5, s5+45);  servo(4, s4+20);
        delay(1000);
}

void rightlegforward()
{
  servo(0, s0+40);  servo(1, s1+40);
  servo(2, s2+30);  servo(3, s3+30);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void rightforwardbias()
{
  servo(0, s0+10);  servo(1, s1+70);
  servo(2, s2+30);  servo(3, s3+30);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void rtilt()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5-50);  servo(4, s4-25);
        delay(1000);
}

void leftfootstraighten()
{
  servo(0, s0);  servo(1, s1);
  servo(2, s2);  servo(3, s3);
  servo(5, s5-15);  servo(4, s4-30);
        delay(1000);
}

void leftkneebend()
{
  servo(0, s0-45);  servo(1, s1);
  servo(2, s2-45);  servo(3, s3);
  servo(5, s5-20);  servo(4, s4-30);
        delay(1000);
}

void leftlegforward()
{
  servo(0, s0-40);  servo(1, s1-40);
  servo(2, s2-35);  servo(3, s3-35);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

void leftforwardbias()
{
  servo(0, s0-70);  servo(1, s1-10);
  servo(2, s2-40);  servo(3, s3-40);
  servo(5, s5);  servo(4, s4);
        delay(1000);
}

5 comments

Leave a Reply