Need help with delay

I'm currently working on a school project. I have a servo motor which start every time I press a button. That part works but I need a delay so when I press the button once I can't press the button the next 2 minutes.

I hope you guys understand my question otherwise I will be more than happy to explain it again.

Here's my code:

#include <Servo.h>
 
const int buttonPin = 2; //The number for the pushbutton in
Servo myservo;
 
int pos = 0; //variable to store the servo position
int buttonState = 0;
int lastButtonState = 0;
 
void setup(){
  pinMode(buttonPin, INPUT);
  myservo.attach(9); //attaches the servoon pin 9 to the servo object
}
 
void loop(){
  //Read the state of the pushbutton value:
 buttonState= digitalRead(buttonPin);
 if (buttonState != lastButtonState) {
   if (buttonState == HIGH){
    for (pos = 0; pos < 180; pos += 1){
      myservo.write(pos);
      delay(15);      
    }
    for (pos = 180; pos >=1; pos -=1){
      myservo.write(pos);
      delay(15);     
    }
  }
 }
 lastButtonState = buttonState;
}

That part works but I need a delay so when I press the button once I can't press the button the next 2 minutes.

So, what is the problem? What have you tried? Maybe, delay()?

I have tried the delay() function but it didn't work.

You don't need a delay. You need to make note of the time when the button is pressed by saving millis() in an unsigned long variable. Then when the button is pushed again, you need to check the difference between the current time and the saved time and see if enough time has passed to allow the button push to proceed.

-br

Hmm, thank you for your answer. Do you have an example code or something?

  • Do I have to put the whole code into a new if() statement?

The Blink Without Delay example contains an example of this sort of timing logic.

Good luck with your project.

-br

I just found that example, I will take a look at it. Thank you!

Delay sounds perfect for your stated requirements, although I suspect you'll quickly want to change to billroy's method as your sketch evolves. In what way did it not work?

Well I just need this "delay" to work and I'm done with my project. I tried to implement the milli() but now the servo motor runs the half way and stops waits the seconds I have defined and then run the whole way.

  • My problem was before that I couldn't get the delay I wanted even though I tried the delay()

Here's what it should do:

  1. I press the button
  2. The servo motor runs 180 degrees and back again.
  3. The delay should prevent me to press the button for the next ten seconds
  4. After the ten seconds I should be able to press the button again.

I hope you understand. If I can do this with a single delay please tell me where to implement it since the things I have tried didn't work.

I am sorry to inform you that you are a little further from your objective than you may have thought. This happens often in this game. You'll be finished faster if you lose the denial and get on with the work.

It is not possible to run the servo while inside your new hypothetical button lockout if the lockout is implemented as a delay. Delay blocks everything else. This is why it is necessary to use a method that keeps track of time.

You don't want a delay. You want a lockout. Think of it in those terms and you might get somewhere.

-br

Well I tried with the milli() and it does almost... work. The servo motor runs 180 degrees and then return. Now, when I press the button it runs 90 degrees and waits the ten seconds I have told it to and then runs as it should. And that's not what I want it to. I want it to follow the steps I wrote in my previous post.

And that's not what I want it to. I want it to follow the steps I wrote in my previous post.

"I changed my code. It doesn't quite do what I want, so I'm not going to show it to you. Please help me fix it, anyway."

Did I summarize that correctly?

Oh sorry here's what I have now:

#include <Servo.h>
 
const int buttonPin = 2; //The number for the pushbutton in
Servo myservo;
 
int pos = 0; //variable to store the servo position
int buttonState = 0;
int lastButtonState = 0;
long previousMillis = 0;
 
long interval = 10000;           // interval at which to blink (milliseconds)

void setup(){
  pinMode(buttonPin, INPUT);
  myservo.attach(9); //attaches the servoon pin 9 to the servo object
}
 
void loop(){
  //Read the state of the pushbutton value:
 unsigned long currentMillis = millis();

 buttonState= digitalRead(buttonPin);
 if(currentMillis - previousMillis > interval) {
   previousMillis = currentMillis;  
   if (buttonState != lastButtonState) {
     if (buttonState == HIGH){
      for (pos = 0; pos < 180; pos += 1){
        myservo.write(pos);
        delay(15);      
      }
      for (pos = 180; pos >=1; pos -=1){
        myservo.write(pos);
        delay(15);     
      }
    }
   }
   lastButtonState = buttonState;
 } 
}
long interval = 10000;           // interval at which to blink (milliseconds)

At which to blink what? 10 seconds is not two minutes.

  //Read the state of the pushbutton value:
 unsigned long currentMillis = millis();

 buttonState= digitalRead(buttonPin);
 if(currentMillis - previousMillis > interval) {

If it isn't time, why bother to read the switch state?

Putting each { on a new line, and using Tools + Auto Format will greatly improve your ability to see the structure of the code.

Think a little more about what needs to be locked out. Not the whole servo loop, just the button check, right?

-br

Whilst using millis() may be the preferred way to do this as the technique will be needed eventually in a program, the objective of locking out use of the button is easily achieved by using delay()

start of loop
  if button press detected
    sweep the servo once each way
    delay for 2 minutes (minus the time taken for the servo sweep if you want to be precise)
  end of if
end of loop

Yes, I know that the delay will block the code for 2 minutes, but if it meets the stated requirement, so what ?

I have no idea how to solve this problem at the moment. I have tried "fizzling" around with the milli() and the delay() but none of the things I tried worked out.

As to the layout of my code. I originally learned to program with K&R style and I have sticked to that since. I have never programming in this before only web dev and Python.

UKHeliBob:
Whilst using millis() may be the preferred way to do this as the technique will be needed eventually in a program, the objective of locking out use of the button is easily achieved by using delay()

start of loop

if button press detected
   sweep the servo once each way
   delay for 2 minutes (minus the time taken for the servo sweep if you want to be precise)
 end of if
end of loop



Yes, I know that the delay will block the code for 2 minutes, but if it meets the stated requirement, so what ?

I could get that to work, here's my code as it as atm.

#include <Servo.h>

const int buttonPin = 2; //The number for the pushbutton in
Servo myservo;

int pos = 0; //variable to store the servo position
int buttonState = 0;
int lastButtonState = 0;
long previousMillis = 0;

long interval = 10000;           // interval at which to blink (milliseconds)

void setup()
{
  pinMode(buttonPin, INPUT);
  myservo.attach(9); //attaches the servoon pin 9 to the servo object
}

void loop()
{
  //Read the state of the pushbutton value:

  buttonState= digitalRead(buttonPin);

  if (buttonState != lastButtonState) 
  {
      if (buttonState == HIGH){
        for (pos = 0; pos < 180; pos += 1)
        {
          myservo.write(pos);
          delay(15);      
        }
        for (pos = 180; pos >=1; pos -=1)
        {
          myservo.write(pos);
          delay(15);     
        }
      }
      delay(120000);
    }
    lastButtonState = buttonState;
  }

Pseudo code to use millis() for the timing

set unsigned long variable interval to milliseconds delay required
set boolean variable timing to false

start of loop
  if timing is false
    if button press detected
      set start time to millis()
      sweep the servo once each way
      set timing to true    
    end of if
  end of if
  
  if millis() minus start time greater than interval
    set timing to false
  end of if
  
  //because the code is non blocking you could do other stuff here whilst waiting
  //as long as it is non blocking
  
end of loop
      if (buttonState == HIGH) {

The key insight is that this test needs to test buttonState and time since last button press before deciding the button press is GO.

-br

I would like to thank you all for your help. I solved the problem with none of your suggestions here's what I did.

#include <Servo.h>

const int buttonPin = 2;
Servo myservo;

int pos = 0;
int buttonState = 0;
int lastButtonState = 0;

void setup()
{
  pinMode(buttonPin, INPUT);
  myservo.attach(9);
}

void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState)
  {
    if (buttonState == HIGH)
    {
      for (pos = 0; pos < 180; pos += 1)
      {
        myservo.write(pos);
        delay(15);
      } 
      for (pos = 180; pos >=1; pos -=1)
      {
        myservo.write(pos);
        delay(15);
      }
      for (int i = 0; i < 60; i++)
      {
        delay(1000);
      }
    }

  } 
  lastButtonState = buttonState; 
}