Go Down

Topic: Me and my Quadrabot (Read 3887 times) previous topic - next topic

Dec 18, 2011, 12:21 pm Last Edit: Dec 18, 2011, 01:17 pm by CrazyEyesNZ Reason: 1
First of all, hi to all.

By way of introduction;

I had dreamed of building a robot for years and years. 18 months ago on the 9th of June 2010 I found out about Arduino and fell in love. I had not done electronics or computer programming before. The most I'd done was 3D modelling on the computer (and that's just a professional hobby). This is not the sum-total of a year's worth of dedicated work. I am 32, I have a full-time job (working swing shift), I'm dating a wonderful and understanding lady (for over a year now), I spend time with my kids and I do all the other things that people generally do in life.

Here is my robot that Im making, and started making using an Arduino Duemilanove:
http://www.youtube.com/watch?v=UHmbU5aFePY
and
http://www.youtube.com/watch?v=Xt24GM1lnHQ

I then downsized the brain to an Arduino Pro Mini (3.3V, 8 MHz) w/ ATmega328:
http://www.youtube.com/watch?v=i7LSH_QzORE
I also mounted the batteries on top.

To give you some idea of what this is, is it's a four-legged, autonomous robot.
Each leg has three servos, giving them 3 degrees of freedom.
It has one sensor, an EZ0 Ultrasonic sensor on the front for obstacle avoidance.

The programming is set up with several components:

  • Stand

  • StandtoForward

  • Forward

  • ForwardtoStand

  • RotateLeft



Because I only have one sensor, once I turn it on, it starts in Forward mode.
It then walks forward until it meets an object.
It then stands, then rotates left, approximately 90 degrees.
Then it either continues walking, or if there is an object in the way it rotates left again.

There is not much code in this robot. It's just repetitive because of the way I have set the robots movements. I have posted the main part of the code, but I haven't entered all the movements because they are just repetitions of servo.write(x), but I've included the Stand component.

Please note that I am in the process of reducing the code (currently sitting at around 500 lines). I intend on putting all the components into arrays to keep it tidy.

Code: [Select]

#include <Servo.h>
Servo myservo2;
Servo myservo3;
Servo myservo4;

Servo myservo5;
Servo myservo6;
Servo myservo7;

Servo myservo8;
Servo myservo9;
Servo myservo10;

Servo myservo11;
Servo myservo12;
Servo myservo13;

int pause = 300;
int sensorValue;
int f=0;
int rl=0;

void setup()
{
 pinMode(0, OUTPUT);

 myservo2.attach(2); //tip blue
 myservo3.attach(3);
 myservo4.attach(4);

 myservo5.attach(5);
 myservo6.attach(6);
 myservo7.attach(7); //tip red

 myservo8.attach(8); //tip green
 myservo9.attach(9);
 myservo10.attach(10);

 myservo11.attach(11);
 myservo12.attach(12);
 myservo13.attach(13); //tip yellow
}

void loop()
{  
 sensorValue = analogRead(A0);  
 Serial.print(sensorValue);
 Serial.println();

 if (sensorValue > 20) //if far from object
 {
   if (f==1){
     doForward();
   }
   else
     if (f==0){
       doStandtoForward();
       f=1;
     }
 }
 else
 {
   if(f==1) {
     doForwardtoStand();
     f=0;
   }
   else
     if (f==0)
     {
       doStand();
       delay(pause);
       doRotateLeft();  
       doRotateLeft();
     }    
 }
} //void end

void doStand()
{
 myservo2.write(77); //tip blue
 myservo3.write(57);
 myservo4.write(90);

 myservo5.write(90);
 myservo6.write(123);
 myservo7.write(103); //tip red

 myservo8.write(77); //tip green
 myservo9.write(57);
 myservo10.write(90);

 myservo11.write(90);
 myservo12.write(123);
 myservo13.write(103); //tip yellow  
}


The average person doesn't read the manual; that's what makes them average.

Just thought that I would add some more of what I've done tonight.

I am using a EZ0 UltraSonic sensor on an analog pin, but it was giving fluctuating readings

example over 20 readings on a stationary, surface mounted sensor:
79
83
78
79
79
79
79
79
79
79
79
79
79
79
79
79
79
79
78
79

The sensor is mounted on my robot, so it is subject to all sorts of shaking and other movement from itself, and any non-solid objects that might come in its way, (eg., a hand) so I wanted to determine a more accurate/stable reading.

I needed the reading at the start of each move and I wanted a fast reading so if the reading is taken between loops, of say the walking gait, that it would not appear to stop between each step.

So, like above I have taken a series of 20 readings all within a split second. I have then determined what the lowest number is and used that. (The lowest number is the most important, because if it gives a high reading and there is an object in the way, then it will continue to move).

Heres the code:
Code: [Select]
int sensorValue;
int g=20;
int average[20];

int i,j,val;

void setup()
{
  pinMode(0, OUTPUT);
}

void loop()

  sensorValue = analogRead(A0);   
  //Take g x readings and save them to sensorValue[]s
  for (i=0; i<=g-1; i++)
  {
    sensorValue = analogRead(A0); 
    average[i]=sensorValue;
  }

  //read readings and determine the lowest reading
  val=average[0];
  for (i=1; i<=g-1; i++)
  {
    if (average[i]<=average[i-1] && average[i]<=val) {
      val=average[i];
    }
  }
} //loop end
The average person doesn't read the manual; that's what makes them average.

cr0sh

Hey - nice job! Now you just need to get it running faster, and chase after the pets! :D
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.


Hey - nice job! Now you just need to get it running faster, and chase after the pets! :D


Thanks for the comment  :)
The average person doesn't read the manual; that's what makes them average.

Hahaha, just to attest to my persistence with my programming, I just spent an hour trying to find fault with my new lines of code and wondering why the servos weren't moving, when I had a look at the servos...well, they were unplugged.

Once plugged in, they worked perfectly! Good to see that at least my programming is sound; and I now have a greater confidence in my debugging ability :)
The average person doesn't read the manual; that's what makes them average.

Well today's been tiring and fruitful. I managed to re-code my program to use arrays to store the leg movements. I still have more tidy up to do though, because at the end of the code I have a lot of repetition. I have spend several hours already trying to work out how to reduce all the movement 'voids' into one void doMovement. I sure it will come to me eventually. Even so, I have reduced the code from 500 lines to 220 lines. The future slimming will reduce the code down by about 35 lines.

The only problem I am having though, is that the eleventh servo is not powering up. It works fine on the old code, but not with this code??? Could it be something wrong with 'arrays'? It's not the last servo on the array, and all the others appear to be working fine. Oh well, I guess I'll just have to try work it out.

Code: [Select]
#include <Servo.h>
Servo myservo[12];

int pause = 300;
int g=20;
int average[20];
int sensorValue;
int f=0;
int e,h,i,j,k;

int move;

//-------------------------------------------------
int standcount=1;
int stand[12][1]={
{ 77},
{ 57},
{ 90},
{ 90},
{123},
{103},
{ 77},
{ 57},
{ 90},
{ 90},
{123},
{103}
};
//-------------------------------------------------
int forwardcount=8;
int forward[12][8]={
{ 58, 51, 51, 51,109, 77, 77, 77},
{ 53, 53, 53, 0, 69, 57, 57, 57},
{ 72, 45, 45, 45,101, 90, 90, 90},
{ 79, 90, 90, 90,108,135,125,135},
{111,123,123,123,127,126,126,182},
{ 71,103,103,103,122,129,129,129},
{109, 51, 51, 51, 58, 77, 77, 77},
{ 69, 0, 53, 53, 53, 57, 57, 57},
{ 79,135,135,135,108, 90, 90, 90},
{ 72, 90, 90, 90,101, 45, 45, 45},
{127,123,123,123,111,182,126,126},
{122,103,103,103, 71,129,129,129}
};
//-------------------------------------------------
int standtoforwardcount=3;
int standtoforward[12][3]={
{ 77, 77, 77},
{ 57, 57 ,57},
{ 90, 90, 90},
{ 90, 90, 90},
{123,123,168},
{103,103,113},
{ 77, 77, 77},
{ 57, 57, 57},
{ 90, 90, 90},
{ 45, 45, 45},
{182,126,126},
{129,129,129}
};
//-------------------------------------------------
int forwardtostandcount=2;
int forwardtostand[12][2]={
{ 77, 77},
{ 57, 57},
{ 90, 90},
{ 90, 90},
{123,123},
{103,103},
{ 77, 77},
{ 57, 57},
{ 90, 90},
{ 45, 45},
{126,182},
{129,129}
};
//-------------------------------------------------
int rotateleftcount=7;
int rotateleft[12][7]={
{ 27, 88, 83, 83, 79, 79, 77},
{ 40, 61, 59, 59, 58, 58, 57},
{135,136,123,123,109,109, 90},
{ 71, 71,123,123,109,109, 90},
{122,122,153,121,122,122,123},
{100,100,140, 97,100,100,103},
{ 75, 75, 83, 83, 88, 88, 27},
{ 58, 58, 59, 59, 61, 61, 40},
{ 79, 79, 57, 57, 44, 44, 90},
{ 71, 71, 57, 57,109,109, 90},
{122,122,121,121,153,122,123},
{100,100, 91, 91,140,101,103},
};
//-------------------------------------------------
void setup()
{
pinMode(0, OUTPUT);

for (k=2; k<=13; k++)
{
myservo[k].attach(k);
}
}
//-------------------------------------------------
void loop()
{
doSensor();

if (sensorValue > 20) //if far from object
{
if (f==1){
doForward();
}
else
if (f==0){
doStandtoForward();
f=1;
}
}
else
{
if(f==1) {
doForwardtoStand();
f=0;
}
else
if (f==0)
{
doStand();
delay(pause);
doRotateLeft();
doRotateLeft();
}
}

} //loop end
//-------------------------------------------------
//Take 20 x readings and save them to sensorValue[]s
void doSensor()
{
average[0] = analogRead(A0);

for (i=1; i<9; i++)
{
sensorValue = analogRead(A0);
average[i]=sensorValue;
if (average[i]<=average[i-1] && average[i]<=sensorValue)
{
sensorValue=average[i];
}}
}
//-------------------------------------------------
void doForward()
{
for (h=0; h<forwardcount; h++)
{
for (e=0; e<12; e++)
{
move=forward[e][h];
myservo[e+2].write(move);
}
delay(pause);
}
}
//-------------------------------------------------
void doStand()
{
for (h=0; h<standcount; h++)
{
for (e=0; e<12; e++)
{
move=stand[e][h];
myservo[e+2].write(move);
}
delay(pause);
}
}
//-------------------------------------------------
void doStandtoForward()
{
for (h=0; h<standtoforwardcount; h++)
{
for (e=0; e<12; e++)
{
move=standtoforward[e][h];
myservo[e+2].write(move);
}
delay(pause);
}
}
//-------------------------------------------------
void doForwardtoStand()
{
for (h=0; h<forwardtostandcount; h++)
{
for (e=0; e<12; e++)
{
move=forwardtostand[e][h];
myservo[e+2].write(move);
}
delay(pause);
}
}
//-------------------------------------------------
void doRotateLeft()
{
for (h=0; h<rotateleftcount; h++)
{
for (e=0; e<12; e++)
{
move=rotateleft[e][h];
myservo[e+2].write(move);
}
delay(pause);
}
}
//-------------------------------------------------
The average person doesn't read the manual; that's what makes them average.

Just a side note:

I just wrote a short program (the shortest Ive ever written) so my kids can play with three buttons attached to a tri-colour LED. In fact, I could have just dispensed with the Arduino and just attached it to a 5V battery.

Code: [Select]
void setup()
{
int i;
for (i=11; i<=13; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH);
}
}

void loop()
{
}
The average person doesn't read the manual; that's what makes them average.

For all those that want to follow a little closer I have set up a Facebook page:

http://www.facebook.com/home.php#!/pages/Quadrabot/246637268735818

Feel free to stop by and leave a comment.
The average person doesn't read the manual; that's what makes them average.

PaulS

Quote
I have spend several hours already trying to work out how to reduce all the movement 'voids' into one void doMovement.

Your skill level is probably about as high as it is going to get until you learn to speak the language correctly. There are not movement 'voids'. There are movement functions.

wildbill

You're having some issues with your arrays that need addressing - you're using elements that you haven't declared, which will lead to unpredictable results. Such as, perhaps, servo eleven failing to function.

Your myservo array has twelve elements, numbered 0 to 11. Here you're using 12 and 13
Code: [Select]

for (k=2; k<=13; k++)
  {
  myservo[k].attach(k);
}


Similarly, here e varies between 0 and 11 (which is good) but myservo[e+2] hits our old friends myservo[12] and myservo[13] again.
Code: [Select]

for (e=0; e<12; e++)
  {
  move=forward[e][h];
  myservo[e+2].write(move);
  }


#10
Dec 21, 2011, 05:33 am Last Edit: Dec 21, 2011, 05:51 am by CrazyEyesNZ Reason: 1
@PaulS
Thanks for the comment. I didnt realize that knowing the model of car you drive makes you a better driver. Thanks for the increase in knowledge

@wildbill
Thanks, that information might actually help me.

Ive just changed the front legs over, so I cant test it just yet, but Ive altered the code:
Code: [Select]
 for (k=0; k<=12; k++)
 {                                  
  myservo[k].attach(k+2);
 }

and
Code: [Select]
for (h=0; h<forwardcount; h++)
 {  
   for (e=0; e<12; e++)
 {
   move=forward[e][h];
   myservo[e].write(move);
 }
 delay(pause);
 }
The average person doesn't read the manual; that's what makes them average.

wildbill

Close, but no cigar:
Code: [Select]

for (k=0; k<=12; k++)
  {                                   
   myservo[k].attach(k+2);
  }

k varies between 0 and 12. 12 is too many (thirteen is right out).

@wildbill

Thanks again,
I'm rewiring at the moment, so I still havent tried it, you saved me some time :)
The average person doesn't read the manual; that's what makes them average.

@wildbill
I changed the code and its working now as it shuold, cheers!  :D

Well, after changing the leg around; I have had to reprogram the movements. I thought I'd do a test gait with it walking on tip-toes. It seems to work alright. Next trick will be to adjust the logic so that when it comes to an object, it has a look up to see if it's a low obstruction, then if it is, lift its body up and walk on tip-toes. I'm not sure how to make it decide when to lower down again... oh well, a problem for another day.

Also, I'm not too sure yet, why my LiPo battery isn't giving sufficient power. I will have to investigate that too, but I just wanted to have a bit of a play at the moment.

http://www.youtube.com/watch?v=G7bf8rDFnUs

Oh, and the reason that it tips over at the end is because I ran out of range with the external battery wires

For all those that want to follow a little closer I have set up a Facebook page:
http://www.facebook.com/home.php#!/pages/Quadrabot/246637268735818
The average person doesn't read the manual; that's what makes them average.

Whippet

Congrats on the awesome robot, sir.  I could never have made a robot with legs, they're too hard for me to program.

Go Up