Programming a quadrupedal frog to move legs asyncronously, use millis()?

Hello all, I am an arduino novice who is looking to mimic the Gait/motion of a frog for a project.
I am familiar with the delay() function, using it to time different servos motions yet I need to have multiple servos move asynchronously. I have drawn up this frog in Solidworks and had it 3D printed. I have an Arduino Uno/servo batteries/Uno battery/wiring tucked up inside the chest cavity underneath.

I am attempting to utilize a post here on this forum that has examples of using milis() to time LED's blinking and intensity.

v

v

v

https://forum.arduino.cc/index.php?topic=503368.0#bot

Just looking for some insight on timing of servo functions. I have never done this and am struggling. I'm just now starting on the coding and of course I have to present it walking by Thursday.

from what I've read on the afore mentioned post, I imagine I'll need four separate functions for leg movement, four variables for start times, four variables for periods?

Any help is appreciated guys/gals.

Thank you for your time.

-Pete

Do you already have a program to exercise each servo individually?

Paul

Our professor gave us a sample code, its a gait for a lizard.
I've ran it with the frog system and it crawls but it is obvious that it is set up for a different style of motion.

Of course the other three groups in the class are doing lizards, so my group has got to improvise.

I've revised all of the servo names and variables to fit our frog, but have yet to be able to manipulate the code to get it where I want it.

Its using a delay(), which is fine for the lizard gait, but not good for our frog.

//MAE-495, Bio-Inspired Robotics
//Group 1 (BLUE-FROG), David, Jacob, Jonathan, Nathan, Peter, Tim.
//This code serves to mimic the gait of a frog while it is crawling.
//------------------------------------------------------------------

#include<Servo.h>

Servo Rightshoulder,Rightarm,Leftshoulder,Leftarm;
Servo Righthip,Rightleg,Lefthip,Leftleg;

int Time = 20;

int Rs=90, Rh=90, Ls=90, Lh=90;
int Ra=90, La=90, Rl=90, Ll=90;

boolean step1=false, step2=false, step3=false, step4=false;

int a=0, b=0, c=0, d=0, e=0;

void setup()
{
  Serial.begin(9600);
  
  pinMode(13,OUTPUT);
  
  //links pins to servos
  Rightarm.attach(2);
  Rightshoulder.attach(3);
  Leftarm.attach(4);
  Leftshoulder.attach(5);
  Rightleg.attach(6);
  Righthip.attach(7);
  Leftleg.attach(8);
  Lefthip.attach(9);


  //set‐up first frame of gait
  Rightarm.write(Ra);
  Leftarm.write(La);
  Rightleg.write(Rl);
  Leftleg.write(Ll);
  Rightshoulder.write(Rs);
  Leftshoulder.write(Ls);
  Righthip.write(Rh);
  Lefthip.write(Lh);

  step1=true;
}


void loop()
{
  digitalWrite(13,HIGH);

  //Frame 1:Left Leg Steps
  while(step1==true)
  {
    Rs=Rs+1;
    Rh=Rh+1;
    Ls=Ls-1;
    Lh=Lh+3;
    a++;
    
    if(e<15)
    {
      Ll=Ll+4;
      e++;
    }
    
    else
    {
      Ll=Ll-4;
      e++;
    }
    
    Rightshoulder.write(Rs);
    Leftshoulder.write(Ls);
    Righthip.write(Rh);
    Lefthip.write(Lh);
    Leftleg.write(Ll);
    
    delay(Time);

    if(a<30)
    {
      step1=true;
    }

    else
    {
      step1=false;
      step2=true;
      a=0;
      e=0;
    }
  }

  //Frame2:Left Arm Steps
  while
  (step2==true)    
  {
    Rs=Rs+1;
    Rh=Rh+1;
    Ls=Ls+3;
    Lh=Lh-1;
    b++;
    
    if(e<15)    
    {
      La=La+4;
      e++;
    }
    
    else
    {
      La=La-4;
      e++;
    }
    
    Rightshoulder.write(Rs);
    Leftshoulder.write(Ls);
    Righthip.write(Rh);
    Lefthip.write(Lh);
    Leftarm.write(La);
    delay(Time);
    
    if(b<30)    
    {
      step2=true;
    }

    else
    {
      step2=false;
      step3=true;
      b=0;
      e=0;
    } 
}

  //Frame3:Right Leg Steps

  while(step3==true)
  {
    Rs=Rs+1;
    Rh=Rh-3;
    Ls=Ls-1;
    Lh=Lh-1;
    c++;
     
    if(e<15)
    {
      Rl=Rl-4;
      e++;
    }
    
    else
    {
      Rl=Rl+4;
      e++;
    }

    Rightshoulder.write(Rs);
    Leftshoulder.write(Ls);
    Righthip.write(Rh);
    Lefthip.write(Lh);
    Rightleg.write(Rl);
    delay(Time);
    
    if(c<30)
    {
      step3=true;
    }
    
    else
    {
      step3=false;
      step4=true;
      c=0;
      e=0;
    }
}

//Frame 4: Right Arm Steps
while(step4==true)
{
  Rs=Rs-3;
  Rh=Rh+1;
  Ls=Ls-1;
  Lh=Lh-1;
  d++;

  if(e<15)    
  {
    Ra=Ra-5;
    e++;
  }

  else
  {
    Ra=Ra+5;
    e++;
  }
  
  Rightshoulder.write(Rs);
  Leftshoulder.write(Ls);
  Righthip.write(Rh);
  Lefthip.write(Lh);
  Rightarm.write(Ra);
  delay(Time);

  if(d<30)
  {
    step4=true;
  }

  else
  {
    step4=false;
    step1=true;
    d=0;
    e=0;
  }
  }
}

Here's a video of it with the lizard gait running...

Looks like a problem of geometry rather than programming. Lizards have 4 legs approximately the same length, but your frog is a very different shape.
Have you analyzed the gait to see what the motion should be?

Yeah, its an entirely different beast.
I can modify this code to get closer to the gait I want but never close enough with the delay() method, I think.

Reading about the millis() method is my goal but I'm no where near the experience to formulate thoughts into code yet.

Cramming right now trying to get it in there.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique. It includes a function to move a servo.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

...R

Thank you all for the help. I really do need to learn the millis() function but had little time to work on this project.

I ended up just running through 8 arrays filled with servo positions on a loop.
It doesn't perfectly mimic the gait of a frog for the simple reason that we cant balance due to servo/sensor limitations.

//Pete's Revision, the gait is mirrored.

#include<Servo.h>
Servo //  min ,   max ,    center?            Orientation
LS,  //   830     2230     1800 = vert.       + = back
LE,  //   850     2050     1000 = straight.   + = forward
RS,  //   850     2200     1100 = vert.       + = forward
RE,  //   1100    2350     2100 = straight    + = back
LH,  //   1000    1750
RH,  //   1150    1850                        + = forward
RK,  //   1500    2000     1500 = str         + = back
LK;  //   1500    2100     2100 = straight    + = forward

int  integral_span = 20;
double time = 45;
// values for calibration:
double ls = 90, le = 90, rs = 90, re = 90, rh = 90, lh = 90,  rk = 90, lk = 90;
int a = 1, b=1;
double
LEa[]={140, 135,  160,  160, 110,   105,  104,  103,  102,  101,  100,  101,  102,  103,  104,  104,  105,  106,  107,  108,  110},
LSa[]={167, 174,  174,  138, 143,   145,  146,  148,  150,  152,  153,  155,  157,  158,  159,  160,  162,  163,  164,  165,  166},
RSa[]={48,  47,   45,   43,   42,   41,   40,   38,   37,   36,   35,   34,   33,   32,   25,   62,   55,   57,   54,   52,   50},
REa[]={103, 102,  102,  101,  101,  100,  100,  100,  100,  100,  101,  101,  100,  95,   85,  -10,   45,   70,   90,   107,  104},
LHa[]={77,  78,   80,   81,   83,   84,   85,   87,   88,   89,   90,   91,   92,   94,   95,   97,   99,   100,  102,  74,   75},
LKa[]={75,  78,   80,   83,   86,   89,   92,   94,   97,   100,  101,  104,  107,  110,  114,  117,  121,  129,  132,  69,   72},
RHa[]={64,  63,   61,   58,   55,   52,   50,   48,   46,   80,   78,   77,   75,   74,   72,   71,   70,   69,   68,   67,   66},
RKa[]={120, 116,  113,  110,  106,  99,   93,   90,   89,   148,  148,  145,  142,  140,  137,  134,  132,  131,  129,  126,  123};


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

  //  links pins  to  servos
  LS.attach(2); // Left  Shoulder 
  LE.attach(3); // Left Elbow
  RS.attach(4); // Right Shoulder
  RE.attach(5); // Right Elbow
  LH.attach(6); // Left Hip
  LK.attach(7); // Left Knee
  RH.attach(8); // Right Hip
  RK.attach(9); //  Right Knee 

  //set-up first frame of gait
  RE.write(re);
  LE.write(le);
  RK.write(rk);
  LK.write(lk);
  RS.write(rs);
  LS.write(ls);
  RH.write(rh);
  LH.write(lh);
}

void loop ()  
{
  digitalWrite(13,HIGH);

  while (a <= integral_span)
  {
    re=REa[a]+35;
    le=LEa[a]-35;
    rs=RSa[a]+25;
    ls=LSa[a]-42;
    rk=RKa[a]+30;
    lk=LKa[a]-10;
    rh=RHa[a]+15;
    lh=LHa[a]+11;
    
    RE.write(re);
    LE.write(le);
    RK.write(rk);
    LK.write(lk);
    RS.write(rs);
    LS.write(ls);
    RH.write(rh);
    LH.write(lh);

    delay(time);

    a++;
  }
  a=1;
}