hexapod master slave communication
TRANSCRIPT
Hexapod
Contents
1 Team Members
2 Mentor
3 Abstract
4 Advantages
5 Design
5.1 Material
6 Code for master slave communication
6.1 Master code
6.2 Slave Code
7 Progress so far
8 Plans ahead
9 Expenses incurred
10 Problems Faced
o 10.1 Problem 1: Heavy and Weak Bot
10.1.1 Modifications Made:
o 10.2 Problem 2: High current Requirement
10.2.1 Modifications:
Team Members
Digvijay Maheshwari
Prateek Kushwaha
Saurabh Kelkar
Mentor
Husain Manasawala
Abstract
Hexapod is a 6 legged locomotive popular among robotics hobbyists. Robot hexapods range
from simple one-motor toys to advanced platforms with 12 or more servos. Hexapod is
controlled by a micro-controller which drives the servos. Once a simple Hexapod is made it
can then be modified to detect obstacles automatically and so on.
Advantages
The robot has Legs and NOT wheels and thus it can be used in terrains that are otherwise not
easily reachable. A Hexapod has no specific direction i.e. it can move in any direction.
Design
The center of the Bot will have a hexagon made of acrylic. This part of the Bot will have the
power source and the microcontroller. To this will be attached the six legs of the Bot. Each
Leg of the Bot will have two motors- one will be attached to the body [from here on referred
to as bodymotor] and the other will be attached to the leg piece that will rest on the ground
[from here on referred to as legmotor]. Thus each leg will have two degrees of freedom. The
material that we used was 4mm acrylic sheet.
Note: If you use two different kinds of servos, use the one with the higher torque as the
legmotor as it’ll get the maximum load.
Material
Acrylic Sheets
Servo motors [# 12]
Battery
Micro controller/s
General purpose PCB(s).
We used Arduino UNO boards as our microcontrollers. Since we are using 12 servo motors
[each servo requires a PWM signal to control and one board has only 6 PWM Pins], we use
two Arduinos and using I2C communication between them. Note that a servo motor runs only
between the voltage range 4.8-6.0 Volts. If you use a higher voltage as the source you need to
step down the voltage to the above range. This we did using IC7805. Since one IC can supply
only 1 Amp current we used twelve of them. The current supply of the source needs to be
checked as the Bot will need very high current [to the tune of 5-6 Amps].
The driver circuit is as follows:
Once the Bot was ready, the next challenging task was to synchronize different legs of
different Arduinos. In the I2C method communication, we have to short the grounds of the
two Arduinos, connect the SCL and the SDI pins i.e. Pin Nos. A4 and A5, of the two
Arduinos. In this method, one of the microcontrollers becomes the Master and the other one
becomes Slave. The Slave’s clock is synced to the Master’s.
Gaits (ways to move) of Hexapod: Alternating tripod: 3 legs on the ground at a time.
Quadruped. Crawl: move just one leg at a time. We are using Quadruped method in which at
any time at least 4 legs touch the ground.
Code for master slave communication
Master code
#include <Servo.h>
#include <Wire.h>
#include<String.h>
Servo bodymotor[3];
Servo legmotor[3];
int rcvd=-1,inbyte=0,count=0;
int angle1,angle2,a1,flag=0;
byte x,y;
String input="";
void setup()
{
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
bodymotor[0].attach(3);
bodymotor[0].write(90);
bodymotor[1].attach(5);
bodymotor[1].write(90);
bodymotor[2].attach(6);
bodymotor[2].write(90);
legmotor[0].attach(9);
legmotor[0].write(180);
legmotor[1].attach(10);
legmotor[1].write(180);
legmotor[2].attach(11);
legmotor[2].write(180);
delay(2500);
Serial.begin(9600);
Wire.begin();
}
//----------------------------------------
void loop()
{
while(Serial.available()>1)
{
if(count==0)
{
input="";
count++;
}
if(count==1)
{
char c=Serial.read();
input+=c;
}
}
if(Serial.available())
{
char last=Serial.read();
input+=last;
count=0;
}
if(input=="sit")
{
sitstand();
delay(50);
}
else if(input=="twist")
{
twist();
}
else if(input=="move")
{
newmove();
}
else if(input=="turnc")
{
turn(0);
}
else if(input=="turna")
{
turn(1);
}
else
{
reset_bot(500);
}
delay(500);
}
//--------------------------------------------
void request(int c)
{
delay(c);
Wire.requestFrom(2,1);
while(Wire.available())
{
rcvd=Wire.receive();
}
}
//------------------------------------------------
void sending()
{
rcvd++;
byte x;
x=byte(rcvd);
Wire.beginTransmission(2);
Wire.send(x);
Wire.endTransmission();
}
//--------------------------------------------------
void reset_bot(int wait)
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
delay(wait);
}
//----------------------------------------------
void sitstand()
{//2050
Wire.beginTransmission(2);
x=byte(50);
Wire.send(x);
Wire.send(0);
Wire.endTransmission();
delay(50);
sending();
legmotor[0].write(135);
legmotor[1].write(135);
legmotor[2].write(135);
request(500);
sending();
legmotor[0].write(90);
legmotor[1].write(90);
legmotor[2].write(90);
delay(1000);
Wire.requestFrom(2,1);
Wire.beginTransmission(2);
x=byte(4);
Wire.send(x);
Wire.endTransmission();
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
delay(500);
rcvd=-1;
}
//----------------------------------------
void move(int a,int b)
{
Wire.beginTransmission(2);
x=byte(a);
y=byte(b);
Wire.send(a);
Wire.endTransmission();
if(b==0)
{
angle1=110;
angle2=70;
}
else if(b==1)
{
angle1=70;
angle2=110;
}
legmotor[0].write(130);
delay(500);
sending();//0
request(500);
bodymotor[0].write(angle1);
sending();//2
request(500);
legmotor[0].write(180);
sending();//4
request(500);
legmotor[2].write(130);
sending();//6
request(500);
bodymotor[2].write(angle2);
sending();//8
request(500);
legmotor[2].write(180);
sending();//10
request(500);
legmotor[1].write(130);
sending();//12
request(500);
sending();//14
bodymotor[0].write(90);
bodymotor[2].write(90);
request(1000);
sending();//16
reset_bot(500);
rcvd=-1;
}
//----------------------------------------------------------
void turn (byte sense)
{//6500
rcvd = 21;
byte z;
z=byte(20);
Wire.beginTransmission(2);
Wire.send(z);
Serial.println("a sent");
Wire.send(sense);
Serial.println("b sent");
Wire.endTransmission();
if(sense==0)
{
angle1=120;
}
else if(sense==1)
{
angle1=60;
}
delay(500);
sending();
legmotor[1].write(130);
request(750);
sending();
bodymotor[1].write(angle1);
request(750);
sending();
legmotor[1].write(180);
request(750);
sending();
legmotor[0].write(130);
legmotor[2].write(130);
request(750);
sending();
bodymotor[0].write(angle1);
bodymotor[2].write(angle1);
request(750);
sending();
legmotor[0].write(180);
legmotor[2].write(180);
request(750);
sending();
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
delay(1000);
rcvd=-1;
reset_bot(500);
}
//-------------------------------------------------------
void newmove()
{//6850
Wire.beginTransmission(2);
y=byte(40);
x=byte(0);
Wire.send(y);
Wire.endTransmission();
delay(50);
sending();
legmotor[1].write(130);
request(500);
sending();
bodymotor[1].write(60);
request(500);
sending();
legmotor[1].write(180);
request(500);
sending();
legmotor[0].write(130);
request(500);
sending();
bodymotor[0].write(85);
request(500);
sending();
legmotor[0].write(180);
delay(800);
legmotor[2].write(130);
delay(500);
bodymotor[2].write(70);
delay(500);
legmotor[2].write(180);
request(500);
sending();
request(500);
sending();
request(500);
sending();
request(500);
sending();
rcvd=-1;
reset_bot(500);
}
//-------------------------------
void twist()
{//3650
a1=90;
Wire.beginTransmission(2);
x=byte(60);
Wire.send(x);
Wire.send(0);
Wire.endTransmission();
delay(50);
while(a1<135)
{
sending();
a1=a1+5;
bodymotor[0].write(a1);
bodymotor[1].write(a1);
bodymotor[2].write(a1);
delay(100);
rcvd--;
}
while(a1>45)
{
sending();
a1=a1-5;
bodymotor[0].write(a1);
bodymotor[1].write(a1);
bodymotor[2].write(a1);
delay(100);
rcvd--;
}
while(a1<90)
{
sending();
a1=a1+5;
bodymotor[0].write(a1);
bodymotor[1].write(a1);
bodymotor[2].write(a1);
delay(100);
rcvd--;
}
rcvd=-1;
}
Slave Code
#include <Servo.h>
#include <Wire.h>
Servo bodymotor[3];
Servo legmotor[3];
int
rcvd,a=0,b=0,z=0,angle11,angle12,angle21,angle22,angle01,angle02,a1,a2=90,c
ounter=0;
byte y;
void setup()
{
Serial.begin(9600);
bodymotor[0].attach(3);
bodymotor[0].write(90);
delay(300);
bodymotor[1].attach(5);
bodymotor[1].write(90);
delay(300);
bodymotor[2].attach(6);
bodymotor[2].write(90);
delay(300);
legmotor[0].attach(9);
legmotor[0].write(180);
delay(300);
legmotor[1].attach(10);
legmotor[1].write(180);
delay(300);
legmotor[2].attach(11);
legmotor[2].write(180);
delay(500);
Wire.begin(2);
Wire.onReceive(interpret);
Wire.onRequest(whattosend);
}
void loop()
{
delay(100);
}
void reset_bot(int wait)
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
delay(wait);
}
void whattosend()
{
int x=rcvd+1;
y=byte(x);
Wire.send(y);
}
void interpret(int howMany)
{
if(z==0)
{
while(Wire.available()>0)
{
a=Wire.receive();
b=Wire.receive();
if(b==0)
{
angle11=110;
angle12=70;
angle01=110;
angle02=70;
a1=120;
}
if(b==1)
{
angle01=70;
angle02=110;
angle01=70;
angle02=110;
a1=60;
}
}
z=1;
}
else if(z==1)
{
while(Wire.available())
{
rcvd=Wire.receive();
}
if (a==0)
{
switch(rcvd)
{
case 0:
{
legmotor[0].write(130);
bodymotor[1].write(90);
legmotor[1].write(180);
break;
}
case 2:
{
bodymotor[0].write(angle01);
bodymotor[1].write(90);
legmotor[1].write(180);
break;
}
case 4:
{
legmotor[0].write(180);
bodymotor[1].write(90);
legmotor[1].write(180);
break;
}
case 6:
{
legmotor[1].write(130);
break;
}
case 8:
{
bodymotor[1].write(angle01);
break;
}
case 10:
{
legmotor[1].write(180);
break;
}
case 12:
{
legmotor[2].write(130);
break;
}
case 14:
{
bodymotor[1].write(90);
bodymotor[0].write(90);
delay(700);
break;
}
case 16:
{
reset_bot(500);
z=0;
break;
}
default:
{
Serial.println("Invalid input from Master");
break;
}
}
}
if (a==1)
{
if (rcvd==0)
{
legmotor[0].write(130);
legmotor[2].write(130);
}
else if (rcvd==2)
{
bodymotor[0].write(angle11);
bodymotor[2].write(angle12);
}
else if(rcvd==4)
{
legmotor[0].write(180);
legmotor[2].write(180);
}
else if(rcvd==6)
{
legmotor[1].write(130);
}
else if(rcvd==8)
{
bodymotor[0].write(90);
bodymotor[2].write(90);
}
}
if (a==2)
{
switch(rcvd)
{
case 0:
{
legmotor[2].write(130);
break;
}
case 2:
{
bodymotor[2].write(angle21);
break;
}
case 4:
{
legmotor[2].write(180);
break;
}
case 6:
{
legmotor[1].write(130);
break;
}
case 8:
{
bodymotor[1].write(angle22);
break;
}
case 10:
{
legmotor[1].write(180);
delay(500);
legmotor[0].write(130);
break;
}
case 12:
{
bodymotor[2].write(90);
bodymotor[1].write(90);
delay(700);
reset_bot(500);
z=0;
break;
}
default:
{
Serial.println("Invalid input from Master");
break;
}
}
}
if(a==20)
{
switch(rcvd)
{
case 22:
{
legmotor[0].write(130);
legmotor[2].write(130);
break;
}
case 24:
{
bodymotor[0].write(a1);
bodymotor[2].write(a1);
break;
}
case 26:
{
legmotor[0].write(180);
legmotor[2].write(180);
break;
}
case 28:
{
legmotor[1].write(130);
break;
}
case 30:
{
bodymotor[1].write(a1);
break;
}
case 32:
{
legmotor[1].write(180);
break;
}
case 34:
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
delay(1000);
reset_bot(500);
z=0;
break;
}
default:
{
Serial.println("Invalid receipt from master during turn");
break;
}
}
}
if(a==40);
{
switch(rcvd)
{
case 0:
{
legmotor[1].write(130);
break;
}
case 2:
{
bodymotor[1].write(120);
break;
}
case 4:
{
legmotor[1].write(180);
break;
}
case 6:
{
legmotor[0].write(130);
break;
}
case 8:
{
bodymotor[0].write(95);
break;
}
case 10:
{
legmotor[0].write(180);
break;
}
case 12:
{
legmotor[2].write(130);
break;
}
case 14:
{
bodymotor[2].write(110);
break;
}
case 16:
{
legmotor[2].write(180);
break;
}
case 18:
{
reset_bot(500);
z=0;
break;
}
}
}
if(a==50)
{
switch(rcvd)
{
case 0:
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
legmotor[0].write(135);
legmotor[1].write(135);
legmotor[2].write(135);
delay(500);
break;
}
case 2:
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
legmotor[0].write(90);
legmotor[1].write(90);
legmotor[2].write(90);
delay(750);
break;
}
case 4:
{
bodymotor[0].write(90);
bodymotor[1].write(90);
bodymotor[2].write(90);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
delay(500);
z=0;
break;
}
}
}
if(a==60)
{
switch(rcvd)
{
case 0:
{
if(counter<9)
{
a2+=5;
bodymotor[0].write(a2);
bodymotor[1].write(a2);
bodymotor[2].write(a2);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
counter++;
}
else if(counter<27 && counter>=9)
{
a2-=5;
bodymotor[0].write(a2);
bodymotor[1].write(a2);
bodymotor[2].write(a2);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
counter++;
}
else if(counter<36 && counter>=27)
{
a2+=5;
bodymotor[0].write(a2);
bodymotor[1].write(a2);
bodymotor[2].write(a2);
legmotor[0].write(180);
legmotor[1].write(180);
legmotor[2].write(180);
counter++;
}
if(counter==36)
{
counter=0;
a2=90;
z=0;
}
break;
}
}
}
}
}
Progress so far
The Hexapod is ready. It currently has the codes to Sit and stand up on its own, twist, turn
(both clockwise and anticlockwise) about its axis, and move in the forward direction. The Bot
accepts the commands from the Serial Monitor. The following are the set of commands:
sit - Sit and stand
twist - Twist
turnc - Turn clockwise
turna - Turn anticlockwise
move - Move forward
Plans ahead
We plan to make the Bot remote controlled using RF modules. There are also plans to make
the power supply on-board once we find a suitably light battery. After the above are
complete, we plan to attach proximity sensors so as to enable the Bot to move on all terrains
and adjust according to the height of the ground. After all this is done, we’ll make the robot
climb stairs. And probably make it even autonomous sometime.
Expenses incurred
Problems Faced
Problem 1: Heavy and Weak Bot
We earlier made a Bot that looked like this:
The Bot was fine as far as the functioning was concerned. But it was quite heavy and so the
motors could not take the load. Also due to too many bends and joints, it was not sturdy and
could not stand straight.
Modifications Made:
The Bot was minimized. Bodymotors were attached to the main body itself. One major
modification done was in the design of the leg piece so it could lift itself up even when down.
The current Bot looks like this:
Problem 2: High current Requirement
Since the Hexapod has 12 Servos, it draws really high current. We tried using different
regulators that could give high current. We started with LM-338 Steel Package and ended up
blowing up two of them. It did fine when checked with no load on the motors, but failed as
soon as it got load. We looked for other regulators as well but we either did not find them or
the available ones were too expensive. We also realised that we did not have a source that
could supply such high current.
Modifications:
We used 12 7805ICs for our twelve motors, i.e. one separate regulator for each Servo. Since
each can supply 1 Amp current, it works good. We currently use two BATTERY
ELIMINATORS each having maximum current limit of 5Amps.
Complete with all the connections the Hexapod looks like this:
Video
YouTube Video Link