I have a problem controlling multiple servos in one for loop

Hi there,

I am fairly new to programming on an Arduino so please bear with me. I am building a pair of walking legs using six servos. For now I just want the loop to start as soon as I power it up. That is working fine for three servos but as soon as I add a fourth the count does something unexpected. I basically want a for loop to simultaneously move all of these servos but when the fourth servo is added into the loop the count skips at a certain point for some reason. I have tested all of the other servos individually using the serial monitor. They count down and then count back up as expected. But as soon as I add the fourth servo into my for loop it will count down and then skip numbers. In my code you will see that I have left foot, right foot, left hip, right hip. ( I have knees but I am not using them yet because of this problem. ) In the serial monitor I am reading the right hip. It starts to count down from 180 to 150 but when it gets to 161 it drops down to 150 which creates an expected jolt in the servo. I thought that maybe I had a servo problem until I watched each of them on the serial monitor. But this appears to be a code problem instead. So I need to know: Do I have a programming problem? Am I exceeding the limitations of the Arduino? Is there a way to optimize this code so that each loop will behave as expected? Thanks in advance! Here is my code:

#include <Servo.h>

//lfootser: 80 is flat - 60 makes the plate tilt right and robot leans left. higher makes robot lean right -  100 is opposite
//rfootser: 40 is flat - 20 makes the plate tile right and robot leans left. higher makes robot lean right - 60 is opposite
//lkneeser: 70 is flat - 50 makes the knee bend in so the right leg can go forward - 90 makes the knee bend out so the right leg can go back
//rkneeser: 80 is flat - 100 makes the knee bend in so the left leg can go forward - 60 makes the knee bend out so the left leg can go back
//lhipser: 100 is flat - 130 makes left leg move forward at the hip - notice here that the servo is mounted backwards so increment accordingly in the forloop
//rhipser: 180 is flat - 150 makes the right leg move forward at the hip

Servo lfootser, rfootser, lkneeser, rkneeser, lhipser, rhipser;  // create servo objects to control servos
// twelve servo objects can be created on most boards

int lfootpos = 80, rfootpos = 40, lkneepos = 70, rkneepos = 80, lhippos = 100, rhippos = 180;    // variable to store the servo position

void setup() {
  Serial.begin(9600);
  lfootser.attach(3);  // attach the servo pins to the servo objects
  rfootser.attach(5);
  lkneeser.attach(6);
  rkneeser.attach(9);
  lhipser.attach(10);
  rhipser.attach(11);
}

void loop() {
  for (lfootpos = 80, rfootpos = 40, lhippos = 100, rhippos = 180; lfootpos > 60 && rfootpos > 20 && lhippos > 70 && rhippos > 150; lfootpos --, rfootpos --, lhippos --, rhippos --)
  {
    lfootser.write(lfootpos);
    rfootser.write(rfootpos);
    lhipser.write(lhippos);
    rhipser.write(rhippos);
    Serial.println(rhippos);
    delay(1000);
  }
  for (lfootpos = 60, rfootpos = 20, lhippos = 70, rhippos = 150; lfootpos < 80 && rfootpos < 40 && lhippos < 100 && rhippos < 180; lfootpos ++, rfootpos ++, lhippos ++, rhippos ++)
  {
    lfootser.write(lfootpos);
    rfootser.write(rfootpos);
    lhipser.write(lhippos);
    rhipser.write(rhippos);
    Serial.println(rhippos);
    delay(1000);
  }
  //This back and forth loop works fine by itself
  //  for (rhippos = 180; rhippos > 150; rhippos --)
  //  {
  //    Serial.println(rhippos);
  //    delay(1000);
  //  }
  //  for (rhippos = 150; rhippos < 180; rhippos ++)
  //  {
  //    Serial.println(rhippos);
  //    delay(1000);
  //  }
}

It is a code problem. The hips move 30 degrees, the feet only 20. So the for loop stops when the feet are done moving but then the next for loop assumes that the hips did their full thirty, they didn’t, hence the jerk.

You should see the issue on both hips.

Thank you for your quick response. I adjusted my feet to move 30 to match the other servos and now that count works on all servos. I figured there was something that I was overlooking and that makes sense since all of these are in the same loop.

Since all of your servos have to move the same amount if they share a loop, it makes the code clearer if you use a simple counter for the number of iterations:

void loop()
{
  lfootpos = 80;
  rfootpos = 40;
  lhippos = 100;
  rhippos = 180;

  for (for i = 0; i < 30; i++)
    {
      lfootser.write(lfootpos--);
      rfootser.write(rfootpos--);
      lhipser.write(lhippos--);
      rhipser.write(rhippos--);
      Serial.println(rhippos);
      delay(1000);
    }

  lfootpos = 60;
  rfootpos = 20;
  lhippos = 70;
  rhippos = 150;

  for (int i = 0; i < 30; i++)
  {
    lfootser.write(lfootpos++);
    rfootser.write(rfootpos++);
    lhipser.write(lhippos++);
    rhipser.write(rhippos++);
    Serial.println(rhippos);
    delay(1000);
  }
}

It looks like @johnwasser’s improvement and the original version will both glitch because, for example, lfootpos will have been decremented to 50, but will be jumped up to 60 before the second loop.

Where it will zoom up to 90, only to glitch again when the first loop starts it out at 80…

This scheme works and can be de-glitched by tweaking all the positions and number of steps.

Sooner or later handling things this way is going to be a real PITA, no matter how crisply expressed.

a7

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.