Controlling a 180 servo speed and position with 3 push buttons

What i am trying to do is go to three different set points when a button is pushed (ex. 0 to 90 to 180 using 3 push buttons) The code for that is pretty simple. What i am have trouble with is controlling the speed. Everything I see for code to control speed is for using continuos or sweep motion. i need to be able to push a button and the servo moves to that position at a set speed then waits for next button to be pushed. any help will be greatly appreciated

With simple hobby Servo motors, there is no way (as far as I know) to control the speed of them, in fact the speed varies with the voltage applied to the Servo as much as anything else.

You can sort of get speed control by say moving 1 degree, pausing for a moment, then moving another and so on, but you wouldn't get any sort of accuracy.

What i am have trouble with is controlling the speed.

Suppose I asked you to rotate quickly from 0 to 90. How would you do that?

Suppose I asked you to rotate slowly from 0 to 90. How would you do that?

In each case, you can rotate in small steps. The difference is how long you wait between steps. Slowly means longer waits. Quickly means shorter waits. The fastest speed involves no waiting.

Exactly how to incorporate this in your code is impossible to say, seeing as how you didn't post your code, despite the sticky telling you that you needed to.

sorry very new to forum

#include <Servo.h>
int button1 = 4; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 5; //button pin, connect to ground to move servo
int press2 = 0;
int button3 = 6; //button pin, connect to ground to move servo
int press3 = 0;
Servo servo1;

void setup()
{
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
servo1.attach(7);
digitalWrite(4, HIGH); //enable pullups to make pin high
digitalWrite(5, HIGH); //enable pullups to make pin high
digitalWrite(6, HIGH); //enable pullups to make pin high}

void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
servo1.write(5);

}
press2 = digitalRead(button2);
if (press2 == LOW)
{
servo1.write(100);

}
press3 = digitalRead(button3);
if (press3 == LOW)
{
servo1.write(180);

}
}

It would be useful to use a variable to define the position to move to. That way, you could move, or not move, as needed. If the servo is at position 5, and the switch connected to pin 4 is pressed again, there is no reason to tell the servo to go where it is.

As Tom suggested, you need to use a for loop to move from where you are (which is why you need to keep track of where you are) to where you want to be, in one degree steps, not all at once. In the body of the for loop, use delay() to slow the speed of the servo down.

Look at the examples in the Servo library.

like this?
#include <Servo.h>

int button1 = 4; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 5; //button pin, connect to ground to move servo
int press2 = 0;
int button3 = 6; //button pin, connect to ground to move servo
int press3 = 0;
int pos ;
Servo servo1;

void setup()
{
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
servo1.attach(7);
digitalWrite(4, HIGH); //enable pullups to make pin high
digitalWrite(5, HIGH); //enable pullups to make pin high
digitalWrite(6, HIGH); //enable pullups to make pin high}

void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
pos.write(5);

}
press2 = digitalRead(button2);
if (press2 == LOW)
{
pos.write(100);

}
press3 = digitalRead(button3);
if (press3 == LOW)
{
pos.write(180);

}
servo1.write(pos)
{

}

my be way off here…Very new…

press1 == LOW)
{
pos = (5);

}
press2 = digitalRead(button2);
if (press2 == LOW)
{
pos = (100);

}
press3 = digitalRead(button3);
if (press3 == LOW)
{
pos = (180);

}
servo1.write(pos)

like this?

Does that even compile? I don’t think so.

How does that code address any of the issues that were pointed out? What code does not use a variable to define where to move to. It attempts, incorrectly, to invoke the write() method of an int. Here’s a clue. The int type is not a class. Therefore, it doesn’t have a write() method.

int goHere = 45;
servo1.write(goHere);

uses a variable to define where to go to.

int oldPos = 0;
int newPos = 0;

void loop()
{
  press1 = digitalRead(button1);
  if (press1 == LOW)
  {
     newPos = 5;
     if(newPos != oldPos )
     {
        servo1.write(newPos);
     }
     oldPos = newPos ;
  }
}

uses two variables to define where the servo is (oldPos) and where it needs to go (newPos). It does not move the servo if where to go is the same as where it’s at. After moving the servo, it updates the where it’s at variable.

Now, it should be obvious that you can use a for loop to move from oldPos to newPos:

for(int pos = oldPos; pos<=newPos; pos++)
{
   servo1.write(pos);
   delay(diddleTime);
}
oldPos = newPos;

The fact that newPos takes on different values depending on which switch is pressed is rather irrelevant.

You only need one block of code to move the servo from the old position to the new position, if the new position is not the same as the old position.

so do I assume that to combine the two it is as follows?

int oldPos = 0;
int newPos = 0;

void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
newPos = 5;
for(int pos = oldPos; pos<=newPos; pos++)
{
servo1.write(pos);
delay(diddleTime);
}
oldPos = newPos;

thank you for your patiences

so do I assume that to combine the two it is as follows?

That’s one way.

I was thinking more along the lines:

void loop()
{
  press1 = digitalRead(button1);
  if (press1 == LOW)
  {
     newPos = 5;
  }

  press2 = digitalRead(button2);
  if (press2 == LOW)
  {
     newPos = 100;
  }

  press3 = digitalRead(button3);
  if (press3 == LOW)
  {
     newPos = 180;
  }

  if(newPos != oldPos)
  {
    for(int pos = oldPos; pos<=newPos; pos++)
    {
       servo1.write(pos);
       delay(diddleTime);
    }
  }
  oldPos = newPos;
}

#include <Servo.h>
int button1 = 4; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 5; //button pin, connect to ground to move servo
int press2 = 0;
int oldPos = 0;
int newPos = 0;
Servo servo1;

void setup()
{
pinMode(button1, INPUT);
pinMode(button2, INPUT);
servo1.attach(7);
digitalWrite(4, HIGH); //enable pullups to make pin high
digitalWrite(5, HIGH); //enable pullups to make pin high
}

void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
newPos = 25;
if(newPos != oldPos )
{
servo1.write(newPos);
}
oldPos = newPos ;
}

press2 = digitalRead(button2);
if (press2 == LOW)
{
newPos = 180;
if(newPos != oldPos )
{
servo1.write(newPos);
}
oldPos = newPos ;
}
}

Thank you so far!!! works great!!! now looking to slow time of movement…I assume this is done adding the for statement?

#include <Servo.h>
int button1 = 4; //button pin, connect to ground to move servo
int press1 = 0;
int button2 = 5; //button pin, connect to ground to move servo
int press2 = 0;
int oldPos = 0;
int newPos = 0;
Servo servo1;

void setup()
{
pinMode(button1, INPUT);
pinMode(button2, INPUT);
servo1.attach(7);
digitalWrite(4, HIGH); //enable pullups to make pin high
digitalWrite(5, HIGH); //enable pullups to make pin high
}

void loop()
{
press1 = digitalRead(button1);
if (press1 == LOW)
{
newPos = 25;
if(newPos != oldPos )
{
servo1.write(newPos);
}
oldPos = newPos ;
}

press2 = digitalRead(button2);
if (press2 == LOW)
{
newPos = 180;

}
if(newPos != oldPos)
{
for(int pos = oldPos; pos<=newPos; pos++)
{
servo1.write(pos);
delay(100);
}
}
oldPos = newPos;
}

Ok the delay works but buttons have now effect it just keeps moving slow to a position then resets fast and starts all over again

I assume this is done adding the for statement?

Yes. You'll actually need two. One to move from oldPos to newPos in positive steps, if newPos is greater than oldPos, and one to move from oldPos to newPos in negative steps, if newPos is less than oldPos. Take care to get the middle clause correct.

if(newPos != oldPos)
{
for(int pos = oldPos; pos>=newPos; pos–)
{
servo1.write(pos);
delay(diddleTime);
}
}
oldPos = newPos;

else(newPos != oldPos)
{
for(int pos = oldPos; pos<=newPos; pos++)
{
servo1.write(pos);
delay(diddleTime);
}
}
oldPos = newPos;

am I on right track here?

am I on right track here?

Sort of.

if(newPos > oldPos)
{
   // for loop counting up
}
else if(newPos < oldPos)
{
   // for loop counting down
}

The two for loops look correct.

if(newPos > oldPos)
{
for(int pos = oldPos; pos<=newPos; pos++)
}
{
else if(newPos < oldPos)
{
for(int pos = oldPos; pos>=newPos; pos–)
}
{
servo1.write(pos);
delay(100);
}
}
oldPos = newPos;
Speed_test_1.ino: In function ‘void loop()’:
Speed_test_1:43: error: expected primary-expression before ‘}’ token
Speed_test_1:43: error: expected ;' before '}' token Speed_test_1:45: error: 'else' without a previous 'if' Speed_test_1:48: error: expected primary-expression before '}' token Speed_test_1:48: error: expected ;’ before ‘}’ token
Speed_test_1:50: error: ‘pos’ was not declared in this scope
Speed_test_1:54: error: expected `}’ at end of input

Speed_test_1.ino: In function ‘void loop()’:
Speed_test_1:43: error: expected primary-expression before ‘}’ token
Speed_test_1:43: error: expected ;' before '}' token Speed_test_1:45: error: 'else' without a previous 'if' Speed_test_1:48: error: expected primary-expression before '}' token Speed_test_1:48: error: expected ;’ before ‘}’ token
Speed_test_1:50: error: ‘pos’ was not declared in this scope
Speed_test_1:54: error: expected `}’ at end of input

press2 = digitalRead(button2);
if (press2 == LOW)
{
newPos = 180;

}
if(newPos > oldPos)
{
for(int pos = oldPos; pos<=newPos; pos++)
}
{
else if(newPos < oldPos)
{
for(int pos = oldPos; pos>=newPos; pos–)
}
{
servo1.write(pos);
delay(100);
}
}
oldPos = newPos;

}

You can't put the body of the for loop outside of the if/else statement. You must duplicate the body of the for loop.

Rather than use a for loop to move between the current position and the newly commanded position, I suggest just incrementing the servo towards the newly commanded position and making a brief delay (to control the speed) then let loop() complete. This way the switches will remain responsive if you want to select a new position before the servo has completed the previous movement.

PeterH:
Rather than use a for loop to move between the current position and the newly commanded position, I suggest just incrementing the servo towards the newly commanded position and making a brief delay (to control the speed) then let loop() complete. This way the switches will remain responsive if you want to select a new position before the servo has completed the previous movement.

One step at a time. Get the behavior of the code working, and understandable, then improve it.