slowing down servo speed

Hey!

I need help to get something working smoothly.

I have: 5 servos
5 buttons

The 5 servos move together in 5 different patterns from 13 to 167 degrees. Each pattern is triggered by one of the 5 buttons.

I want to be able to easily modify the code to modulate the speed of the servos. It’s ok if a set speed affects all servos at once. (but having them independently modifiable would be crazy!)

Now, I have tried to break the motion of the servos in incrementing steps that I could slow down or speed up by modifying the delay
between each incrementation. I think this is the way to go, but this approach gives me trouble here because the servos don’t have a fixed starting point, they start where they were left at at the previous pass.
I tried working it out by making 2 different for loops, and I got lost…

Here’s the original code, quite simple, and you’ll see how complex it becomes with my non-working solution.

#include <Servo.h>

Servo myservo[5];
int buttonPin[] = {2, 3, 4, 5, 6};
int buttonState[] = {0, 0, 0, 0, 0};
int lastButtonState[] = {0, 0, 0, 0, 0};
int x = 11;
int servoRoll;
int positions[5][5] =
{  
  {13, 45, 90, 135, 167},        // button0 - servo {0, 1, 2, 3, 4}
  {45, 90, 135, 167, 13},        // button1 - servo {0, 1, 2, 3, 4}
  {90, 135, 167, 13, 45},        // button2 - servo {0, 1, 2, 3, 4}
  {135, 167, 13, 45, 90},        // button3 - servo {0, 1, 2, 3, 4}
  {167, 13, 45, 90, 135},        // button4 - servo {0, 1, 2, 3, 4}   
};




void setup() {
  for (int serv=0;serv<5;serv++){                                   //attach servos to pins
      myservo[serv].attach(x); x--;
  }

  for(int buttonPinning = 0; buttonPinning < 5; buttonPinning++){   //set buttonPins as inputs                                              
    pinMode (buttonPin[buttonPinning], INPUT);                                                                    
  }
}  
void moveButton() {                                                            
  for(int buttonRoll = 0; buttonRoll < 5; buttonRoll++){            //buttonRoll serves as reference for 'lines' of nested array                                                       
  buttonState[buttonRoll] = digitalRead(buttonPin[buttonRoll]);     //reading the buttons                                           
    
    if ((buttonState[buttonRoll] != lastButtonState[buttonRoll])&&(buttonState[buttonRoll] == 1)) {  //checking button states
    for(servoRoll = 0; servoRoll < 5; servoRoll++){                                                  //servoRoll servers as reference for 'columns' of nested array
      myservo[servoRoll].write(positions[buttonRoll][servoRoll]);                                    //tells servos to go to positions
      delay(5);
      }
    }

    else{
      delay(5);
      } 
  lastButtonState[buttonRoll] = buttonState[buttonRoll];   //sets new 'lastButtonState for the next pass                                                       
  }
}

void loop(){
  
moveButton();
}

and now the funky stuff, it still compiles though, and the servos do move slowly, but only 2 or 3 times and in a jerky way…

#include <Servo.h>

Servo myservo[5];
int buttonPin[] = {2, 3, 4, 5, 6};
int buttonState[] = {0, 0, 0, 0, 0};
int lastButtonState[] = {0, 0, 0, 0, 0};
int ServoState[] = {0, 0, 0, 0, 0};
int mover;
int servoRoll;
int buttonRoll;
int lastServoState;
int x = 11 ;

int positions[5][5] =
{
  
  {13, 45, 90, 135, 167},        // button0 - servo {0, 1, 2, 3, 4}
  {45, 90, 135, 167, 13},       // button1 - servo {0, 1, 2, 3, 4}
  {90, 135, 167, 13, 45},       // button2 - servo {0, 1, 2, 3, 4}
  {135, 167, 13, 45, 90},     // button3 - servo {0, 1, 2, 3, 4}
  {167, 13, 45, 90, 135},      // button4 - servo {0, 1, 2, 3, 4}
   
};




void setup() {
  for (int serv=0;serv<5;serv++){
      myservo[serv].attach(x); x--;
  }

  for(int buttonPinning = 0; buttonPinning < 5; buttonPinning++){                                              
    pinMode (buttonPin[buttonPinning], INPUT);                                                                    
  }
}  
void moveButton() {                                                            
  for(int buttonRoll = 0; buttonRoll < 5; buttonRoll++){                                                       
  buttonState[buttonRoll] = digitalRead(buttonPin[buttonRoll]);                                                
    
    if ((buttonState[buttonRoll] != lastButtonState[buttonRoll])&&(buttonState[buttonRoll] == 1)){  //
    for(servoRoll = 0; servoRoll < 5; servoRoll++){
        
        if(lastServoState <= (positions[buttonRoll][servoRoll])) {                                 //if, lastServoState for positions smaller than...
        for(mover = lastServoState; mover <= (positions[buttonRoll][servoRoll]); mover ++){        //I try to use 'mover' as an incrementee to get   
           myservo[servoRoll].write(mover);                                                        //myservo to increment in little steps
           delay(20);
           }
        }
        else if(lastServoState > (positions[buttonRoll][servoRoll])) {   
        for(mover = lastServoState; mover > (positions[buttonRoll][servoRoll]); mover --){         //else, lastServoState for positions bigger than... 
           myservo[servoRoll].write(mover);
           delay(20);
           }
        }
        else{
            delay(1);
            }
    };   
    }
    else{
        delay(1);
        }
  };    
  lastServoState = (positions[buttonRoll][servoRoll]);                 //gives lastServoState the value of the last position
  lastButtonState[buttonRoll] = buttonState[buttonRoll];                                                       
}

void loop() {
  moveButton();
}

any help or guidance would be greatly appreciated,

thanks

Some suggestions. For loop variables are usually given very short names, like i, j, k.

I’d suggest that you change buttonRoll to i, servoRoll to j, and mover to k, in moveButton().
In addition, put each { on a new line, indented to match the command it goes with.
Line everything in the block up.

I think that if you do this, you’ll immediately see what the problem is.

If not, take a close look at the last two lines of the moveButton() function, and think about when buttonRoll (now i) and servoRoll (now j) go out of scope.

Also consider that lastServoState is not holding a state. It’s holding a position. It’s better if names match their actual usage.

ok,

So, I cleaned the thing a little and tried to understand what’s wrong, I get a feeling it has to do with the ‘nested’ for loops and so, as you said, the following lines don’t get included in the right for loop.

 lastServoPosition[i] = (positions[i][j]);                                        
        lastButtonState[i] = buttonState[i];

here’s what I’ve done (in progress. Still not working, good practice though)

#include <Servo.h>

Servo myservo[5];
int buttonPin[] = {2, 3, 4, 5, 6};
int buttonState[] = {0, 0, 0, 0, 0};
int lastButtonState[] = {0, 0, 0, 0, 0};
int ServoState[] = {0, 0, 0, 0, 0};
int g, h, i, j, k;
int lastServoPosition[] = {0, 0, 0, 0, 0};
int x = 11 ;

int positions[5][5] =
{
  
  {13, 45, 90, 135, 167},        // button0 - servo {0, 1, 2, 3, 4}
  {45, 90, 135, 167, 13},       // button1 - servo {0, 1, 2, 3, 4}
  {90, 135, 167, 13, 45},       // button2 - servo {0, 1, 2, 3, 4}
  {135, 167, 13, 45, 90},     // button3 - servo {0, 1, 2, 3, 4}
  {167, 13, 45, 90, 135},      // button4 - servo {0, 1, 2, 3, 4}
   
};




void setup()
{
 for(g=0;g<5;g++)
  {
  myservo[g].attach(x); x--;
  }
 for(h = 0; h < 5; h++)
  {                                              
  pinMode (buttonPin[h], INPUT);                                                                    
  }
}

void moveButton()
{                                                            
 for(i = 0; i < 5; i++)
 {
  for(j = 0; j < 5; j++)
  {                                                       
   buttonState[i] = digitalRead(buttonPin[i]);                                                
   if ((buttonState[i] != lastButtonState[i])&&(buttonState[i] == 1))
   {
    if(lastServoPosition[i] <= (positions[i][j])) 
    {                                                                                 //if, lastServoState for positions smaller than...
     for(k = lastServoPosition[i]; k <= (positions[i][j]); k ++)
     {                                                                                //I try to use 'mover' as an incrementee to get   
      myservo[j].write(k);                                                            //myservo to increment in little steps
      delay(20);
     }
    }
    else if(lastServoPosition[i] > (positions[i][j]))
    {   
     for(k = lastServoPosition[i]; k > (positions[i][j]); k --)
     {                                                                                //else, lastServoState for positions bigger than... 
      myservo[j].write(k);
      delay(20);
     }
    }
   else
   {
    delay(1);
   }
   
  }   
 
  else
  {
   delay(1);
  }

 
 lastServoPosition[i] = (positions[i][j]);                                        //gives lastServoState the value of the last position
 lastButtonState[i] = buttonState[i];
  }
 }
}


void loop() 
{
  moveButton();
}

As obvious as it might seem to you, it doesn’t to me : ) I get lost in there, but I’ll get to it.

thanks for pointing the problem, you probably saved me a day or two!

    if(lastServoPosition[i] <= (positions[i][j]))
    {
    }
    else if(lastServoPosition[i] > (positions[i][j]))
    {  
    }
   else
   {
    delay(1);
   }

The lastServoPosition is either less than or equal some value, or it is greater than that value. The else clause can never be executed.

   if ((buttonState[i] != lastButtonState[i])&&(buttonState[i] == 1))
  {
  }  
  else
  {
   delay(1);
  }

Why the delay? If the button is pressed, just move on.

The “obvious” issue you fixed by moving the statements to where they belong.

There are still some things I question.

 for(i = 0; i < 5; i++)
 {
  for(j = 0; j < 5; j++)
  {
   buttonState[i] = digitalRead(buttonPin[i]); 
   if ((buttonState[i] != lastButtonState[i])&&(buttonState[i] == 1))
   {

Why is the read and if test inside the j loop?

Saving the lastServoPosition should be done when the servo is moved, not regardless of whether a change was made, it seems to me.

The comments at the ends of the code are pretty much useless. They just repeat what the code is doing.

Where comments are really useful, there are none. Why are there nested loops? Perhaps the thing to do is to create a function called MoveToPosition() that takes an argument that defines the position (the row in the array) that the servos should be moved to.

In the moveButton() function call that function with the button that is pressed. I think you’ll find that separating the logic of picking the set of positions from the logic of moving the servos to that position will make the whole thing easier.