Servo Angles

Hello! I am having some trouble programming 3 servos to move like a wave. So, for instance, I want my first servo to move and when it reaches a certain angle I want my second servo to move, with the first, then when it reaches a certain angle I want my third servo to move, with the first and the second. Does that make sense? I can upload a picture if that would make it better.

Thank you for your help!!

Servos can be assumed to drive instantly towards the commanded position. So you should divide your wave into small steps (maybe 5?) and then command all servos to go to the position dictated by the current step. Some milliseconds later, you move to the next step and all servos will get a new command.

That is a fair description of your goal.

What code have you written to do it?
If you have not written any code yet, start out with the servo sweep tutorial.

If you have questions about your code, make sure to use the code tags when posting your complete sketch.

Edit: do NOT attempt to power your servos from the arduino 5v pin. Many tutorials show this. It might work for one small, unloaded servo. But larger servos, or multiple servos, or servos with any load on them will quickly demand more current that the arduino voltage regulator can provide and shut down the arduino (or damage it)
Much better to use a dedicated power supply for the servos with a common ground to the arduino.

This is what I have

#include <Servo.h>

Servo left;
Servo middle;
Servo right;

// interger postion
int pos = 20;
int post = 120;
int back = 20;
int forward = 120;

// interger speed
int mid = 4;

void setup() 
{
 Serial.begin(9600);

 left.attach(2);
 middle.attach(3);
 right.attach(4);

 left.write(back);
 middle.write(back);
 right.write(back);
}

void loop() 
{
 for (pos = back; pos <= forward; pos += 1)
 {
   post = map(pos, 20, 120, 120, 20);
   left.write(pos);
   middle.write(post);
   right.write(pos);
   delay(mid);
 }
 for (pos = forward; pos >= back; pos -= 1)
 {
   post = map(pos, 20, 120, 120, 20);
   left.write(pos);
   middle.write(post);
   right.write(pos);
   delay(mid);
 }
}

What does that code do that is not what you want?

Please read the "how to use the forum" stickies to see how to format and post code.

2 things.

  1. You did not use code tags. This makes it much easier for us to read since it is in a scrolling window, and much easier to load in to the IDE to check syntax and other IDE work. You can go back and edit your reply to put in the code tags.

  2. You have now given us a good description of what you want, and given us your code. Cool! Does the code do what you want? Hint: It is best if you describe the results of your program like this by stating what you expect it to do and then stating what it actually does.

I want my first servo to move and when it reaches a certain angle I want my second servo to move, with the first, then when it reaches a certain angle I want my third servo to move, with the first and the second.

And then what?
Servos do not move continuously and those that are modified to do so have no control over the angle they are pointing at. Typically a servo would move over 180 degrees although some do more and some do less.

I would have thought for a wave you would want the motors to continuously rotate.

Can you describe your desired movement some more? Re-reading your initial post, I imagine something like the attached picture with 6 stages.

Stage 1 is the beginning position with all servos at zero degrees.
Stage 2 shows how it looks after servo 1 moved to 60 degrees. This is when servo 2 starts moving.
Stage 3 shows how it looks after servo 1 moved to 120 degrees and servo 2 moved to 60 degrees. This is when servo 3 starts moving.
Stage 4 shows how it looks after servo 1 moved to 180 degrees, servo 2 moved to 120 degrees and servo 3 moved to 60 degrees. This is where servo 1 stops moving.
Stage 5 shows how it looks after servo 2 moved to 180 degrees and servo 3 moved to 120 degrees. This is where servo 2 stops moving.
Stage 6 shows how it looks after servo 3 moved to 180 degrees. This is where servo 3 stops moving.

ServoWave.png

Ok. So my servos are set up in a line on their sides... What this code does that I don't want is that the two on the outside move together and the middle moves oppositely. So when the two on the outside are down the middle is up. What I want is for the first servo to go down, say like 45 degrees, then when it hits that point I want the second servo to start, when it hits it certain degree I want the third servo to start. Then I want it to start all over again.

left.write(pos);
   middle.write(post);
   right.write(pos);

Is the bit that you tell the left servo to move exactly the same as the right servo. You have to put another value in the right write statement if you want it to move differently.
Maybe use another map function call to generate an new value to write.

When you say start all over, you can’t unless you first move the servos backwards, then you can start over. Is that what you want.

Is this another X-Y problem ( google it )

Yes, that’s what I meant when I said to start all over, go backwards, my apologies.

Here is a photo. I’m not the best artist, but I hope it helps

So you need to move one servo all the time and the other two only when certain angles have been reached. To do this you use an if statement to look at the angles and only write to the other two servos once those angles have been exceeded.
Something like this:-

for (pos = back; pos <= forward; pos += 1)
 {

   left.write(pos);
   if( pos > firstTriggerAngle){
      post = map(pos, 20, 120, 120, 20);
      middle.write(post);
}
   if(post > secondTriggerAngle){
   post2 = map(post, ?, ?, ?, ?);  // depends on the angles you use
   right.write(post2);
  }
   delay(mid);
 }

Note their are new variables you have to define and the mapping of the third angle details to work out.

Hi,

Servo1 Servo2 Servo3
1 0 0 0
2 60 0 0
3 120 60 0
4 180 120 60
5 180 180 120
6 180 180 180

You could do it as a quick a dirty, using switch … case

https://www.arduino.cc/reference/en/language/structure/control-structure/switchcase/

You could then run it forwards and back.

Tom… :slight_smile:

I thought you couldn’t use a switch statement on a range of values? I want my servo to start at 90 go to 135 then to 180 and then go backwards.

Also the code you suggested grumpy mike doesn't work. It just moves one servo

LexiRobinson:
Also the code you suggested grumpy mike doesn't work. It just moves one servo

Then post it because if only one servo moves then you haven't done it correctly and maybe we can spot your mistake.

#include <Servo.h>

//Create servo object to control a servo
Servo left;
Servo middle;
Servo right;

//Variables to store the servo position
int pos = 0;
int post = 180;
int post2 = 180;
int back = 90;
int forward = 135;

int firstTriggerAngle = 135;
int secondTriggerAngle = 180;

//Delay
int mid = 4;

void setup() 
{
  Serial.begin(9600);

  //Attaches the servos on the pins of the arduino to the servo object
  left.attach(4);
  middle.attach(3);
  right.attach(2);

  //Starting position
  left.write(back);
  middle.write(back);
  right.write(back);
}

void loop()
{
  for (pos = back; pos <= forward; pos += 1)
  {
    left.write(pos);
    if( pos > firstTriggerAngle)
    {
      post = map(pos, 90, 180, 180, 90);
      middle.write(post);
    }
    if(post > secondTriggerAngle)
    {
      post2 = map(post, 90, 180, 180, 90);  // depends on the angles you use
      right.write(post2);
    }
    delay(mid);
 }
}

You have:-

int firstTriggerAngle = 135;
int secondTriggerAngle = 180;
int forward = 135;
int back = 90;

But in the for loop where you move the motors you have

for (pos = back; pos <= forward; pos += 1)

So the loop variable pos runs from 90 to 134, therefore you never get to move any other motor. Your for loop stops before the firstTriggerAngle is exceeded.

Wait now I’m confused. For a for loop, you need this… for (initialization; condition; increase), right? And that’s what I have. Start at 90 then check to see if it hits 135 and if it does move on. So where am I messing up?

#include <Servo.h>

//Create servo object to control a servo
Servo left;
Servo middle;
Servo right;

//Variables to store the servo position
int post = 180;
int post2 = 180;
int back = 90;
int forward = 135;

int firstTriggerAngle = 135;
int secondTriggerAngle = 180;

//Delay
int mid = 4;

void setup() 
{
  Serial.begin(9600);

  //Attaches the servos on the pins of the arduino to the servo object
  left.attach(4);
  middle.attach(3);
  right.attach(2);

  //Starting position
  left.write(back);
  middle.write(back);
  right.write(back);
}

void loop()
{
  for (int i=back; i>=forward; i+=1)
  {
    left.write(i);
    if( i > firstTriggerAngle)
    {
      post = map(i, 90, 180, 180, 90);
      middle.write(post);
    }
    if(post > secondTriggerAngle)
    {
      post2 = map(post, 90, 180, 180, 90);  // depends on the angles you use
      right.write(post2);
    }
    delay(mid);
 }

So you're expecting that i only gets to 135? And inside that for loop you're checking for i > 135.

Steve