I want to make my biped robot keep walking, but it only move for twice, this biped robot project is important for my Capstone project. The code below is the code that I used
#include <Servo.h>
int HipR_Pin = 9;
int HipL_Pin = 10;
int KneeR_Pin = 5;
int KneeL_Pin = 6;
int AnkleR_Pin = 3;
int AnkleL_Pin = 11;
Servo HipR;
Servo HipL;
Servo KneeR;
Servo KneeL;
Servo AnkleR;
Servo AnkleL;
void setup() {
HipR.attach(HipR_Pin);
HipL.attach(HipL_Pin);
KneeR.attach(KneeR_Pin);
KneeL.attach(KneeL_Pin);
AnkleR.attach(KneeR_Pin);
AnkleL.attach(KneeL_Pin);
}
void loop() {
for (int i=0; i < 7; i++)
{
RightStep1;
LeftStep1;
RightStep2;
LeftStep2;
RightStep3;
LeftStep3;
RightStep4;
LeftStep4;
}
;
}
void RightStep1()
{
HipR.write(80);
HipL.write(80);
KneeR.write(100);
KneeL.write(100);
AnkleR.write(20);
AnkleL.write(20);
}
void LeftStep1()
{
HipR.write(90);
HipL.write(90);
KneeR.write(70);
KneeL.write(70);
AnkleR.write(20);
AnkleL.write(20);
}
void RightStep2()
{
HipR.write(70);
HipL.write(70);
KneeR.write(80);
KneeL.write(80);
AnkleR.write(10);
AnkleL.write(10);
}
void LeftStep2()
{
HipR.write(60);
HipL.write(60);
KneeR.write(90);
KneeL.write(90);
AnkleR.write(20);
AnkleL.write(20);
}
void RightStep3()
{
HipR.write(40);
HipL.write(40);
KneeR.write(60);
KneeL.write(60);
AnkleR.write(10);
AnkleL.write(10);
}
void LeftStep3()
{
HipR.write(50);
HipL.write(50);
KneeR.write(70);
KneeL.write(70);
AnkleR.write(20);
AnkleL.write(20);
}
void RightStep4()
{
HipR.write(60);
HipL.write(60);
KneeR.write(60);
KneeL.write(60);
AnkleR.write(10);
AnkleL.write(10);
}
void LeftStep4()
{
HipR.write(70);
HipL.write(70);
KneeR.write(50);
KneeL.write(50);
AnkleR.write(20);
AnkleL.write(20);
}
4 Answers 4
This may not be a direct answer to your question but... when I see so
much code repetition, I cannot help but suggest you try to avoid
repeating yourself. All your Step()
functions do exactly the same
actions, only with different data. You can then factor the actions
into a single function, and provide it different data as parameters.
There are many ways to achieve this in C++. I am going to show four of
them, in order from the most basic to the most esoteric.
The simplest one is to use a plain function and give it the angles as parameters. This is basically what Michel Keijzers’ answer suggests. My take on it would be
void Step(uint8_t hip, uint8_t knee, uint8_t ankle)
{
HipR.write(hip);
HipL.write(hip);
KneeR.write(knee);
KneeL.write(knee);
AnkleR.write(ankle);
AnkleL.write(ankle);
}
which you can then use in the main loop as
Step( 80, 100, 20); // right 1
Step( 90, 70, 20); // left 1
...
The next step in code modularity would be to group all the angles for a
single step into a compound data structure called a struct
, then the
function to perform a step takes a single parameter which is this data
structure:
struct Step {
uint8_t hip;
uint8_t knee;
uint8_t ankle;
};
void doStep(Step s)
{
HipR.write(s.hip);
HipL.write(s.hip);
KneeR.write(s.knee);
KneeL.write(s.knee);
AnkleR.write(s.ankle);
AnkleL.write(s.ankle);
}
These structs would be defined as
Step RightStep1 = { 80, 100, 20};
Step LeftStep1 = { 90, 70, 20};
...
and used in loop()
as
doStep(RightStep1);
doStep(LeftStep1);
...
One step further, you can embed the function within the data structure. The embedded function then becomes a "method" of the data structure which is now called an "object":
struct Step {
uint8_t hip;
uint8_t knee;
uint8_t ankle;
void perform() {
HipR.write(hip);
HipL.write(hip);
KneeR.write(knee);
KneeL.write(knee);
AnkleR.write(ankle);
AnkleL.write(ankle);
}
};
The structs can be defined just as before, and used as
RightStep1.perform();
LeftStep1.perform();
...
One last technique involves making the objects themselves behave as
functions that can be called. This kind of callable object is called a
"functor", and is kind of syntactic sugar over a method call. We just
have to rename the relevant method as operator()
:
struct Step {
uint8_t hip;
uint8_t knee;
uint8_t ankle;
void operator()() {
HipR.write(hip);
HipL.write(hip);
KneeR.write(knee);
KneeL.write(knee);
AnkleR.write(ankle);
AnkleL.write(ankle);
}
};
The structs are still defined in the same way, but now they can be used as if they were plain functions:
RightStep1();
LeftStep1();
...
I suggest you use whatever technique you feel the most comfortable with. There is a logic progression though: the more you improve your C++ skills the more comfortable you will be with the latest ones.
In addition to @Gerben's answer, you aren't giving any time for your movements to complete. .write()
doesn't wait for the movement to complete - it just sets the target angle. You should add enough delay(...)
calls to wait for your movements to finish before you start a new one.
To call a function you need to add parentheses after the function name.
void loop() {
for (int i=0; i < 7; i++)
{
RightStep1();
LeftStep1();
RightStep2();
LeftStep2();
RightStep3();
LeftStep3();
RightStep4();
LeftStep4();
}
;//<<--also remove this stray semi-colon
}
Instead of all the different step functions you can better parameterize them for example
void LeftStep4()
{
HipR.write(70);
HipL.write(70);
KneeR.write(50);
KneeL.write(50);
AnkleR.write(20);
AnkleL.write(20);
}
will be
void LeftStep4()
{
Move(70, 70, 50, 50, 20, 20);
}
and create a function
void Move(int hipR, int hipL, int kneeR, int kneeL, int ankleR, int ankleL)
HipR.write(hipR);
HipL.write(hipL);
KneeR.write(kneeR);
KneeL.write(kneeL);
AnkleR.write(ankleR);
AnkleL.write(ankleL);
}
The other functions will also be one liners like the first function LeftStep4.
Explore related questions
See similar questions with these tags.
but it only move for twice
does not describe the observed action ..... because it could mean that the robot takes two steps or it could mean that only two of the servos move or it could mean that one servo moves twice .... each of those conditions would be caused by different program bugs