Incremental Servo Movement, With Button Input

Hey guys, I am super new to programing and to be honest, I have no idea what I am doing.

So I am trying to make a servo move a set amount of degrees and stay at that position when a button is pushed, and then when that same button is pushed again, move an additional amount of degrees from the previous position and stay.

I would love to have another button that would move the servo in the opposite(negative direction) when pushed (in the same type of way).

Here is some code that i tried writing, however it is brutally wrong, and I am getting nowhere. I am seeing if someone could please help me out. It would be greatly appreciated!!

CODE:

#include <Servo.h>

Servo servo1;

int button1 = 12;
int button2 = 11;
int pos = 0;

void setup()
{
servo1.attach(9); //servo to pin 9
servo1.write(0); //servo 0 degrees
pinMode(button1,INPUT);
pinMode(button2,INPUT);
}

void loop()
{
{
if(digitalRead(button1) == HIGH); //if button is high, go to these next positions, depending on current positions
{
for(pos = 0; pos <= 45; pos += 10) //if position is 0 and button is high, go to 45 degrees, increments of 10 degrees
{
servo1.write(pos); //go to posittion
delay(15); //delay 15 ms
}
for(pos = 45; pos <= 90; pos += 10) //if position is 45 and button is high, go to 90 degrees, increments of 10 degrees
{
servo1.write(pos);
delay(15);
}
for(pos = 90; pos <= 135; pos += 10) //if position is 90 and button is high, go to 135 degrees, increments of 10 degrees
{
servo1.write(pos); //go to position
delay(15); //delay 15ms
}
}
}
{
if(digitalRead(button2) == HIGH); //if button is high, go to these next positions, depending on current positions
{
for(pos = 135; pos>=90; pos -=10); //if position is 135 and button is high, go to 90 degrees, increments of -10 degrees
{
servo1.write(pos); //go to position
delay(15); //delay 15ms
}
for(pos = 90; pos>=45; pos -=10); //if position is 135 and button is high, go to 90 degrees, increments of -10 degrees
{
servo1.write(pos); //go to position
delay(15); //delay 15ms
}
for(pos = 45;pos>=0; pos -=10); //if position is 135 and button is high, go to 90 degrees, increments of -10 degrees per second
{
servo1.write(pos); //go to position
delay(15); //delay 15ms
}
}
}
}

You need to check the button state and when it BECOMES pressed move the servo a fixed amount rather than moving it when the button IS pressed. Look at the StateChangeDetection example in the IDE and adapt it to your needs. Note that unless you want the servo to move slowly to its new position there is no need to use a for loop, just write the new position to it.

How do you expect to move the servo from 0o to 45o in 10o steps?
45/10 =4.5 steps. How do you get that half step?

UKHeliBob,
Thank you! I am currently working on the new code, I will let you know if I get it to work/need further assistance. I really appreciate it. I will upload my Code once it is more complete.

Henry_Best,

I just realized that this was a slightly older code, it was changed to steps of 5 degrees. Thank you for the observation!

Ryan

I will upload my Code once it is more complete.

Try to remember to use code tags when you do. Please read the how to use this forum sticky post.

Will do, sorry about that.

Grumpy_Mike:
Try to remember to use code tags when you do. Please read the how to use this forum sticky post.

So I have been trying to implement the button state change detection, however it just sweeps from 0 to 180. I have written another code that increments off of the last position, but it is doing some weird movement for the first 4 or so button pushes before it starts to actually increment. Now i just need to implement the button state change detection into the incremental movement, but I can not for the life of me get it to work.

Here is the working incremental code,

#include <Servo.h>
Servo servo;

const int button = 12;
int pos = 0;


void setup() 
{
  servo.write(0);
  servo.attach(9);
  pinMode(button, INPUT);
 
 
  // put your setup code here, to run once:

}

void loop() 
{
  if(digitalRead(button) == HIGH)
  {
    servo.write(pos+=10);
    delay(10);
  }
  // put your main code here, to run repeatedly:

}

Thanks again guys!! :smiley:

#include <Servo.h>
Servo servo;
const byte buttonPin = A1;
byte currentButtonState = HIGH;
byte previousButtonState = HIGH;
int servoPosition = 0;
int servoIncrement = 10;

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  servo.attach(A5);
  servo.write(0);
}

void loop()
{
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != previousButtonState && currentButtonState == LOW)
  {
    servoPosition += servoIncrement;
    servo.write(servoPosition);
  }
  previousButtonState = currentButtonState;
}

UKHeliBob, thank you so much! I can now increment the servo reliably. Here is my final code

#include <Servo.h>
Servo servo;
const byte buttonPin = 12;
byte currentButtonState = LOW;
byte previousButtonState = LOW;
int servoPosition = 0;
int servoIncrement = 18;

void setup()
{
  pinMode(buttonPin, INPUT);
  servo.attach(9);
  servo.write(0);
}

void loop()
{
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != previousButtonState && currentButtonState == HIGH)
  {
    servoPosition += servoIncrement;
    servo.write(servoPosition);
    delay(10);
  }
  previousButtonState = currentButtonState;
}

Thanks again guys! This helped me so much! :slight_smile:

I am glad that you got it working, but how about adding a check so that the servo does not try to move beyond its limits or maybe reverses when it reaches each end of its travel, or a second input to move it in the other direction ?

UKHeliBob: I am glad that you got it working, but how about adding a check so that the servo does not try to move beyond its limits or maybe reverses when it reaches each end of its travel, or a second input to move it in the other direction ?

I am working on putting a secondary button that will move it in the other direction. Once I get it working, I'll throw the code up on this thread!

Here is the new code, it has a button that increments the servo into the positive direction and another that increments in the negative direction. I do not know how to put limits onto the position, but let me know what you guys think!

#include <Servo.h>
Servo servo;
const byte buttonPin1 = 12;
const byte buttonPin2 = 11;
byte currentButtonState2 = LOW;
byte previousButtonState2 = LOW;
byte currentButtonState1 = LOW;
byte previousButtonState1 = LOW;
int servoPosition = 0;
int servoIncrement = 22.5;

void setup()
{
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  servo.attach(9);
  servo.write(0);
}

void loop()
{
  currentButtonState1 = digitalRead(buttonPin1);
  if (currentButtonState1 != previousButtonState1 && currentButtonState1 == HIGH)
  {
    servoPosition += servoIncrement;
    servo.write(servoPosition);
    delay(10);
  }
  previousButtonState1 = currentButtonState1;
  
  currentButtonState2 = digitalRead(buttonPin2);
  if (currentButtonState2 != previousButtonState2 && currentButtonState2 == HIGH)
  {
    servoPosition -= servoIncrement;
    servo.write(servoPosition);
    delay(10);
  }
  previousButtonState2 = currentButtonState2;
}

Looks OK.

As to imposing limits you would do it like this.

    servoPosition += servoIncrement;
    if (servoPosition > 180)
    {
      servoPosition = 180;
    }

It would be even better to replace the 180 with a variable with a meaningful name such as upperLimit and the same, of course, for the lower limit..

As the code for checking buttons and moving the servos is largely repeated you could consider using arrays to hold values and iterate through them using a for loop although you would need to balance the complexity of the array solution with the simplicity of of repeating the code.

Absolutely!

Yeah thats what I originally tried, however I could not get the array to work.

I just added another servo and a LCD screen to the code. Making a sort of bike shifter with the servos. Once it is a little more complete I'll put it up here.

I also incorporated the limits, however, I have not physically tested it yet. I will let you know if I get it working!

A version using arrays

#include <Servo.h>

Servo servo;
const byte buttonPins[] = {A1, A2};
byte previousButtonStates[] = {HIGH, HIGH};

int servoPosition = 0;
const int servoIncrements[] = {22, -22};

void setup()
{
  Serial.begin(115200);
  for (int p = 0; p < 2; p++)
  {
    pinMode(buttonPins[p], INPUT_PULLUP);
  }
  servo.attach(9);
  servo.write(0);
}

void loop()
{
  for (int b = 0; b < 2; b++)
  {
    boolean moved = false;
    byte currentButtonState = digitalRead(buttonPins[b]);
    if (currentButtonState != previousButtonStates[b] && currentButtonState == LOW)
    {
      servoPosition += servoIncrements[b];
      moved = true;
    }
    if (servoPosition > 180 || servoPosition < 0)
    {
      servoPosition -= servoIncrements[b];
    }
    if (moved)
    {
      servo.write(servoPosition);
      delay(10);
      Serial.println(servoPosition);
    }
    previousButtonStates[b] = currentButtonState;
  }
}

Note that the increments are ints so cannot be 22.5

Yeah thats what I originally tried, however I could not get the array to work.

Because you were doing something wrong.

If you post the code we might be able to spot what it was.

Grumpy_Mike:
Because you were doing something wrong.

If you post the code we might be able to spot what it was.

I fully understand I was doing something wrong. However it was so wrong and non-coherent that I trashed it. It would have been a waist of time for you and myself, it would have to be 100% rewritten.