Go Down

Topic: multiple servos speed modulation (solved) (Read 810 times) previous topic - next topic

kaporal_p

Jan 30, 2011, 06:11 am Last Edit: Feb 15, 2011, 07:09 am by kaporal_p Reason: 1
Hello,

If I had followed the guidelines better and search the forum more thoroughly, I would have found a library written by Korman that does just that, servo speed modulation.

But still, I again learned a lot from all the people who give you just enough information to give you hope...

here's my final code:

Code: [Select]

#include <VarSpeedServo.h>

VarSpeedServo myservo[5];
int ledPin[] = {14, 15, 16, 17, 18};
int buttonPin[] = {2, 3, 4, 5, 6};
int buttonState[] = {0, 0, 0, 0, 0};
int lastButtonState[] = {1, 1, 1, 1, 1};
int servospeeds[] = {10, 20, 30, 40, 50};
int positions[5][5] =


  {3, 45, 90, 135, 177},        // button0 - servo {0, 1, 2, 3, 4}
  {45, 90, 135, 177, 3},        // button1 - servo {0, 1, 2, 3, 4}
  {90, 135, 177, 3, 45},        // button2 - servo {0, 1, 2, 3, 4}
  {135, 177, 3, 45, 90},        // button3 - servo {0, 1, 2, 3, 4}
  {177, 3, 45, 90, 135},        // button4 - servo {0, 1, 2, 3, 4}   
};

void setup()
{
  int f, g, h;
  Serial.begin(9600);
  int x = 11;
  for (f=0; f<5; f++)
  {                                   
   myservo[f].attach(x); x--;
  }
  for(g = 0; g < 5; g++)
  {                                               
   pinMode (buttonPin[g], INPUT);                                                                       
  }
    for(h = 14; h < 19; h++)
  {                                               
   pinMode (ledPin[h], OUTPUT);                                                                       
  }
}

void moveServo(int pp)
{
int j, m;
for (m = 0; m < 5; m++)
{
  digitalWrite(ledPin[m], HIGH);
}
buttonState[pp] = digitalRead(buttonPin[pp]);
if ((buttonState[pp] != lastButtonState[pp])&&(buttonState[pp] == 0))
{
  digitalWrite(ledPin[pp], LOW);
  delay(50);
  for(j = 0; j < 5; j++)
  {
   myservo[j].slowmove(positions[pp][j], servospeeds[3]);
   delay(10);
  }
}
lastButtonState[pp] = buttonState[pp];
}

void loop()
{
int p;
for (p = 0; p < 5; p++)
{
  moveServo(p);
}
}



thanks again to everyone.


Below is the original post


trying to slow multiple servos with this piece of code. I increment (or decrement) the positions of the servos a step at a time. I try to make a pause between each of these steps.
 
Code: [Select]

void moveup(int pp)                                                    
{
for(pos[i] = lastPos[i]; pos[i] <= positions[pp][i]; pos[i] ++)              // pos = int variable, stores value to be given to servo and
{                                                                                            // positions = values of end of travel for servos
 myservo[i].write(pos[i]);                                                           // lastPos = position from where the servo starts
 delay(30);                                                                               // value of [i] is incremented from 0 to 4 from another function
}
}


This code is half-working, I think delay is giving me trouble, it makes servos move to 0 before each move and the servos move one after the other instead of all together, but the speed modulation does work. Then I tried to use the Millis trick

Code: [Select]

void moveup(int pp)                                                    
{
unsigned long currentMillis = millis();
for(pos[i] = lastPos[i]; pos[i] <= positions[pp][i]; pos[i] ++)
{
 if(currentMillis - previousMillis > interval)                           // interval = delay value, anywhere btwn 1 and 100 ms.
 {
  previousMillis = currentMillis;
  myservo[i].write(pos[i]);
 }
}
}


but it's not working. I think the problem is because the Millis trick works when in the void loop(). Here it just makes 1 servo go to pos = 0 and that's it.  Also, I don't think I can put this function in the void loop() because I use the void loop 'frequency' to modulate the argument 'pp'.

So, what I want is to pause between each increment of the for loop, am I on the right track?

thanks

PaulS

Where does I get a value?

The delay() call is not making the servo move to 0. Possibly, the fact that lastPos is 0 (not that I have any idea what is in lastPos) is doing it.

The delay() call says do nothing for 30 milliseconds.

The measurement you are doing with millis(), previousMillis and interval is not doing the same thing. Serial.print() the values in currentMillis and previousMillis to see why.

If you are going to use millis() in place of delay(), it will not be in a for loop.

kaporal_p

Yes lastPos starts with a value of 0, so I understand why it does that on the first run, but then, lastPos ends with a different value since it's updated at the end of the function,
Code: [Select]

lastPos[i] = pos[i];

so I don't understand why it does it at every turn.

now I will go study the millis() behavior as you suggested,

thanks

WizenedEE

I don't really understand what PaulS was talking about, but I know how to get all the servos to turn at once.

What you want to do is have two nested loops. One is the "move slowly" thing, with the delay. That would be the outer loop. The inner loop would have the code to move each servo, with no delay. This would mean the inner loop runes extremely fast and quickly sets all the servo values. Once they start turning, the outer loop waits 30 ms and then makes them all go to the next position.

PaulS

Quote
Yes lastPos starts with a value of 0, so I understand why it does that on the first run, but then, lastPos ends with a different value since it's updated at the end of the function,

The lastPos array is not updated in that snippet you posted. Perhaps you need to post more of your code. All of it would be good.

kaporal_p

#5
Jan 30, 2011, 05:49 pm Last Edit: Jan 30, 2011, 07:16 pm by kaporal_p Reason: 1
To WizenedEE

Your Idea about nested loop was my first guess, but I never got to get the program running with it, so here I am, maybe I will end up back on that track, I'll try again since my code is now much clearer than it was.

So after thinking about it, this is what I've done, but my nested loop is in a function, so I don't know if I you still name this a nested loop. I did this because depending on the servos positions, I have to move Up or to move Down, so I have a loop (a nested one) for each situation (up or down) that gets called depending on the previous position.

   
To PaulS, here's the full code. Btw, I'm not done with my study of the Millis() behavior, I don't understand it yet.


Code: [Select]
#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 servospeeds[] = {10, 20, 30, 40, 50};
int pos[] = {0, 0, 0, 0, 0};
int lastPos[] = {0, 0, 0, 0, 0};
int positions[5][5] =

{  
 {6, 6, 6, 6, 6},            // button0 - servo {0, 1, 2, 3, 4}              these values are for testing, they are now simpler than they will be
 {13, 13, 13, 13, 13},        // button1 - servo {0, 1, 2, 3, 4}
 {45, 45, 45, 45, 45},        // button2 - servo {0, 1, 2, 3, 4}
 {75, 75, 75, 75, 75},        // button3 - servo {0, 1, 2, 3, 4}
 {90, 90, 90, 90, 90},        // button4 - servo {0, 1, 2, 3, 4}  
};


int f, g, i, p;

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

void moveup(int pp)                                                     //
{
for(pos[i] = lastPos[i]; pos[i] <= positions[pp][i]; pos[i] ++)
{                                                
 myservo[i].write(pos[i]);
}
}


void movedown(int pp)
{
for(pos[i] = lastPos[i]; pos[i] >= positions[pp][i]; pos[i] --)
{                                                
 myservo[i].write(pos[i]);
}
}

 
void moveServo(int pp)
{
buttonState[pp] = digitalRead(buttonPin[pp]);
if ((buttonState[pp] != lastButtonState[pp])&&(buttonState[pp] == 0))
{
 for(i = 0; i < 5; i++)
 {
  if (pos[i] < positions[pp][i])
  {  
  moveup(p);
  delay(100);
  }
  if (pos[i] > positions[pp][i])
  {  
  movedown(p);
  delay(100);
  }
 }
}
lastPos[i] = pos[i];  
lastButtonState[pp] = buttonState[pp];
}

void loop()
{
for (p = 0; p < 5; p++)
{
moveServo(p);
}
}



PaulS

Looking at your moveServo function, the problem is fairly obvious.
Code: [Select]
void moveServo(int pp)
{
buttonState[pp] = digitalRead(buttonPin[pp]);
if ((buttonState[pp] != lastButtonState[pp])&&(buttonState[pp] == 0))
{
  for(i = 0; i < 5; i++)
  {
    // Snipped code to move servo one way or the other
  }
}
[color=orange]lastPos[i] = pos[i];  [/color]
lastButtonState[pp] = buttonState[pp];
}

Which lastPos position is being set to what value? In other words, what is the value of i when the assignment statement is executed? Hint: it's 5. That causes the 6th position in the 5 position array to be assigned the value in the 6th position of a 5 position array.

You need to move the assignment statement INSIDE the for loop.

kaporal_p

Hello,

If I had followed the guidelines better and search the forum more thoroughly, I would have found a library written by Korman that does just that, servo speed modulation.

But still, I again learned a lot from all the people who give you just enough information to give you hope...

here's my final code:

Code:
Code: [Select]

#include <VarSpeedServo.h>

VarSpeedServo myservo[5];
int ledPin[] = {14, 15, 16, 17, 18};
int buttonPin[] = {2, 3, 4, 5, 6};
int buttonState[] = {0, 0, 0, 0, 0};
int lastButtonState[] = {1, 1, 1, 1, 1};
int servospeeds[] = {10, 20, 30, 40, 50};
int positions[5][5] =


  {3, 45, 90, 135, 177},        // button0 - servo {0, 1, 2, 3, 4}
  {45, 90, 135, 177, 3},        // button1 - servo {0, 1, 2, 3, 4}
  {90, 135, 177, 3, 45},        // button2 - servo {0, 1, 2, 3, 4}
  {135, 177, 3, 45, 90},        // button3 - servo {0, 1, 2, 3, 4}
  {177, 3, 45, 90, 135},        // button4 - servo {0, 1, 2, 3, 4}   
};

void setup()
{
  int f, g, h;
  Serial.begin(9600);
  int x = 11;
  for (f=0; f<5; f++)
  {                                   
   myservo[f].attach(x); x--;
  }
  for(g = 0; g < 5; g++)
  {                                               
   pinMode (buttonPin[g], INPUT);                                                                       
  }
    for(h = 14; h < 19; h++)
  {                                               
   pinMode (ledPin[h], OUTPUT);                                                                       
  }
}

void moveServo(int pp)
{
int j, m;
for (m = 0; m < 5; m++)
{
  digitalWrite(ledPin[m], HIGH);
}
buttonState[pp] = digitalRead(buttonPin[pp]);
if ((buttonState[pp] != lastButtonState[pp])&&(buttonState[pp] == 0))
{
  digitalWrite(ledPin[pp], LOW);
  delay(50);
  for(j = 0; j < 5; j++)
  {
   myservo[j].slowmove(positions[pp][j], servospeeds[3]);
   delay(10);
  }
}
lastButtonState[pp] = buttonState[pp];
}

void loop()
{
int p;
for (p = 0; p < 5; p++)
{
  moveServo(p);
}
}


thanks again to everyone.

Go Up