Stopping a Servo Sweep.

Hello people.

I'm working in a small project. I basically need two servos to sweep mirrored one to the other and stop via a push button. My problem is that I already got it working, and it starts the sweep when I press the button. The problem comes to stopping it, as it only does when I press the button at the moment the servos finish their sweeping cycle. If I press the button at any other moment, they wont stop.

My code is as follows, but basically is just a slightly modified version of the Sweep example Arduino comes with.

#include <Servo.h> 
 
Servo myservo;  
Servo myservo2; 
 
int pos = 0;

int switchpin = 2;
int stoppin = 3;
boolean lastbutton = LOW;
boolean currentbutton = HIGH;
boolean Servosmove = false;

void setup() 
{ 
  myservo.attach(5); 
  myservo2.attach(6);
  pinMode(switchpin, INPUT);
  myservo.write(80);
  myservo2.write(95);
} 

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchpin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchpin);
  }
  return current;
}
 
void loop()
{
  currentbutton = debounce(lastbutton);
  if (lastbutton == LOW && currentbutton == HIGH)
  {
    Servosmove = !Servosmove;
  }
  lastbutton = currentbutton;
  
  if (Servosmove == true) {
     for(pos = 90; pos>=1; pos-=1)
      {
        myservo.write(pos); 
        myservo2.write(abs(180-pos));
        delay(20); 
      }
     for(pos = 0; pos < 90; pos += 1) 
      {
        myservo.write(pos);              
        myservo2.write(abs(180-pos));
        delay(20);
      } 
} else if (Servosmove == false) {
    myservo.write(90);
    myservo2.write(90);
  }
}

Basically, I just need to know

I am sure that you realise that the problem is caused by the use of delay() within the for loops which means that for nearly 4 seconds the program is tied up and cannot read the input. The solution is not to use delay() for the timing but to use the principle shown in the BlinkWithoutDelay example. This involves starting an action, such as moving the servo then checking frequently (each time through loop()) whether it is time to do something else, such as moving the servo again. If not then do something else such as checking an input and acting on it,

The problem is your for loops. There is nothing in there that interrupts them, and they block the execution of the loop function. Your loops will keep running until they reach their end.

You need to completely restructure your code in order to simultaneously monitor the button and move the servos. I'd recommend a simple state machine (Gammon Forum : Electronics : Microprocessors : State machines) with two states: SWEEP and STOP. Use a couple of global variables to keep track of the servo position, and use BlinkWithoutDelay style coding to control the servos without blocking. Use the button press to transition between the two states.

It's stupid that so many of the Arduino examples use delay when it's a horrible way to program. It works only for the trivial examples they give, but as soon as you need to start doing something more complicated, you need to ditch the delays and work with a different paradigm.

Actually, you only delay 20 ms at a time. You just need to check the switch within the for loops and if pressed, use break to exit the for.

That being said, UKHeliBob is right... a "Blink without delay" technique is much better.

The demo several things at a time might give you some ideas.

...R

Thank you all. :slight_smile:

Following Robin's example I managed to make it switch states at any moment. It's still a little bit faulty but at least the biggest problem is gone.

Enchufe:
It's still a little bit faulty but at least the biggest problem is gone.

If you want more advice please post your latest code and describe the problems.

...R