Controlling servo direction using one push button

Hello,
I am trying to control a servo using only one push button. If the degree is less than 90 degrees then the degree should increment as long as the button is pushed and after reaching 90 it should decrement if the button is pressed. This is the code I am using. I am not able to get the loop to stop if the state of the button changes. Any tips?

#include <Servo.h>

Servo servo;

int pushpin = 2;  //Push button pin
int pushval = 0;  //Stores push button state

int prevpos = 0;  //To store the previous position of servo. I'm using it as a memory to know if the arm should increment or decrement after a stop.
int k = 0;

void setup() {
  servo.attach(9);
  pinMode(2, INPUT);
  Serial.begin(9600);
}

void loop() {
  pushval = digitalRead(2);

  if (prevpos <= 90)
  {
    if (pushval == HIGH)
    {
      for (int k = prevpos; k <= 90; k++)
      {
        servo.write(k);
        Serial.println(k);
        delay(100);
      }
    }
    else if (pushval == LOW)
    {
      while (0 == 0)
      {
        break;
      }
    }
    prevpos = k;
  }

  else if (prevpos =90)
  {
    if (pushval == HIGH)
    {
      for (int k = prevpos; k >= 0; k--)
      {
        servo.write(k);
        Serial.println(k);
        delay(100);
      }
    }
  }
  prevpos = k;
}

Hi, @sudhir98
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".

It will show you how to post your code in a scrolling window.
In the IDE press CTRL T, it will ident your code to make it easier to see your if statement scope.

What model Arduino are you using?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Hello, @TomGeorge
I have edited the format. Thanks.
I am using a UNO.

The contacts of every button bounce. That is why every serious sketch debounces the buttons. In your case, that might not be needed, so you can go ahead and maybe later worry about debouncing.

The Arduino can respond to multiple things if the loop() runs very fast over and over again. That means you can not stay in a for-loop with a delay.

I rather have a variable that tells to go up or go down and a variable that holds the current position. It will make the sketch easier.

int direction = 1;    // -1 or +1
int angle = 0;     // angle of servo motor, 0...180

void loop()
{
  if button pressed
  {
    angle += direction;
    servo.write( angle);

    if( angle >= 90 or angle <= 0)
      direction = -direction
  }
  
  ...

  delay( 100);     // slow down the sketch
}

Can you make a new sketch with that ?

A full description is useful, but it is very hard for beginners. Can you try to write down what the sketch should do ?
Should it stop when reaching 90 degrees while the button is still pressed ? What is the other limit ? 0 degrees ? What about a autorepeat : Press the button once for one step, only after some time it stepper motor keeps on moving as long as the button is pressed.

@Koepel ,
I will try to create a sketch with the idea you have given.

I am writing a code that will control the angle of servo using just one push button. The value will initially be 0 and should increment up to 90 and once it reaches 90 it should decrement back to 0. All this should happen only when the button is pressed.

Could it be... if( int k.... ; k<= 90; k++) ? Wouldn't that exit with a k being 91?

Then.. if ( k = 90) OOPS!

@Railroader you mean for loop? I've tried using a for loop but the problem is it doesn't exit the loop until it reaches 90. So even if I release the button mid way, say at 45, it still does not stop incrementing till it reaches 90 after which it checks and the button is low so it exits. I need a way to keep checking the state always as the value is being incremented or decremented.

Correction: It is for loop, not an if that might give k 91.

Did You pick the second remark? k = 90?

Check the button in the for loop and exit if the button is not active.

Thank you everyone. I have managed to solve the issue. I used separate increment and decrement functions and used function call. Now it is working the way I wanted it to.

Hi,
To make this thread helpful to others can you please post your working code?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Great. Thanks for telling.

OK, so you need to understand the overall concept of programming. You have a main "loop()" whose task is to "get things done" by sequentially attending to all relevant matters. This means that it absolutely cannot tarry on any one matter and most certainly cannot wait at any point for for some particular thing to happen.

This specifically means that you cannot freely use loops within your code. "While" loops are particularly inappropriate as they imply waiting for some event. "For" loops are only appropriate if it is guaranteed that they will complete immediately (which is to say within a millisecond or so) without any need to wait.

This means that whatever may have been indexed in a loop as a dependency, simply needs to be kept as a global index (or "state") variable which is tested to determine what should happen in consequence and that variable may be advanced (only) as appropriate for successive passes through the loop().

@Paul_B I used for loop with a delay to slow down the motor. I incremented the degree of servo by one each time with a delay of 100ms between each increment/decrement.