Stop Blocking on Button Press

Hi
Im very new to all this and green.
At the moment the delay is blocking the second button press.
I would like to be able to press both buttons at any time instead of wait.
I looked up millis() instead for delay but don't understand how to write it.
could someone help me write the code below to have the same moment and wait without blocking.
many thanks
Jason

#include <ezButton.h>
#include <Servo.h> 
ezButton buttonleft(7);
ezButton buttonright(8);  // create ezButton object that attach to pin 7;
Servo servoleft;  
Servo servoright;  
int dt=50; 
int pos = 50;  
void setup() {
    servoleft.attach(9);
    servoright.attach(10);
  Serial.begin(9600);
  servoleft.write(87);
  servoright.write(90);

}

void loop() {
  buttonleft.loop(); 
   buttonright.loop();// MUST call the loop() function first

 delay(dt);

if(buttonright.isPressed()){
   Serial.println("The button left is pressed");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!
 delay(100); 
servoleft.write(130); // Move servo to 180 degrees!
delay(1000);      // Wait 1 second
 for (pos = 130; pos >= 87; pos -= 1) {/* goes from 0 to 70
                                          degrees in steps
                                          of 1 degree */
    
   servoleft.write(pos);                  // go to position 'pos'
    
    delay(5);                         // waits 5ms
                                       

 }

}
if(buttonleft.isPressed()){
   Serial.println("The button right is pressed ");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!
 delay(100); 
servoright.write(40); // Move servo to 180 degrees!
delay(500);      // Wait 1 second
for (pos = 40; pos <= 90; pos += 1) { /* goes from 0 to 70
                                          degrees in steps
                                          of 1 degree */
    
   servoright.write(pos);                  // go to position 'pos'
    
    delay(5);                         /* waits 5ms 


}
}
}

Perhaps start by correcting the mistakes in the current sketch

  if (buttonright.isPressed())
  {
    Serial.println("The button left is pressed");
  if (buttonleft.isPressed())
  {
    Serial.println("The button right is pressed ");

:joy:
So helpful
Thanks
That was just for testing to seeing if each button was working did not matter if they matched up.
But I did say I was new lol

Try understand this example and apply to your project.

#include <Arduino.h>
#include <Bounce2.h> // https://github.com/thomasfredericks/Bounce2/archive/refs/heads/master.zip
#include <Servo.h>

Bounce2::Button button = Bounce2::Button();

const int buttonPin = 4;
const int servo1Pin = 9;
const int servo2Pin = 10;
const int ledPin =  LED_BUILTIN;

byte step = 1;
const int courseTime = 10;
const int time = (courseTime * 300) / 180;

Servo myservo1;
Servo myservo2;

void setup()
{
  Serial.begin(9600);

  button.attach(buttonPin, INPUT_PULLUP);
  button.interval(5); // interval im ms
  button.setPressedState(LOW);

  myservo1.write(0); //starts motor at 0 degress
  myservo2.write(0);
  myservo1.attach(servo1Pin);
  myservo2.attach(servo2Pin);
}

void loop()
{
  button.update();

  if (button.pressed())
  {
    if (step == 0)
    {
      step = 1;
      moveServo();
    }
    else
    {
      step = 0;
      moveServo();
    }
  }
}

void moveServo()
{
  Serial.print("step = ");
  Serial.println(step);

  switch (step)
  {
    case 0:
      for (int pos = 0; pos < 120; pos++)
      {
        myservo1.write(pos);
        myservo2.write(pos);
      }
      break;
    case 1:
      for (int pos = 120; pos > 0; pos--)
      {
        myservo1.write(pos);
        myservo2.write(pos);
      }
      break;
    default:
      break;
  }
}

Thanks for your help
I will try to get my head round it

That's the easy stuff to change but changing to non blocking timing using millis() is going to need bigger changes. All of the delay()s need to go, even assuming that they were needed in the first place

I assume that the delay()sin the servo movement for loops are to slow down the servo movement but what about the others ?

I feel that I should point out that your code as posted does not compile

Thanks
I copied and pasted bits so probably missed something.
I’m a magician and have been using it to make a sign fall in my show (left side then the right). It works but would like it to drop both together as a finale.
I think I could make it works with number of buttons presses which might be easier and then would only need 1 button I think?

Thanks again for your help

It's exactly what the code above does.

1 Like

You could certainly make it work using a single button

  • first press, one side drops
  • second press, other side drops (does the first side need to raise ?)
  • third press, both sides drop

You could then continue to use delay()s in the code, which is going to be easier than changing to millis() timing

1 Like

It’s first side drops
I put it back
Then first side drops again
This time I put it back and hold it.
Then second side drops
I put it back walk away
Then they both drop.

The buttons are link to a remote with 2 channels

But at the moment I can’t get them both to drop at the same time. Because of the delay

So will try to figure out the button number count and do it that way.

Take a look at the StateChangeDetection example in the IDE

1 Like

Look for this:

#include <Arduino.h>
#include <Servo.h>
#include <IRremote.h>

const int receiverPin = 2;
const int servoLeftPin = 9;
const int servoRightPin = 10;

byte step = 0;
bool nextStep = false;
bool commandReceived = false;

unsigned long prevMillis = 0;

#define DROP_INTERVAL 2 // Time in seconds

Servo leftSide;
Servo rightSide;

IRrecv receiver(receiverPin);

void translateIR();
void moveServo(byte move);

void setup()
{
  Serial.begin(9600);

  leftSide.write(90);
  rightSide.write(90);
  leftSide.attach(servoLeftPin);
  rightSide.attach(servoRightPin);

  receiver.enableIRIn();
}

void loop()
{
  // Checks received an IR signal
  if (receiver.decode())
  {
    translateIR();
    receiver.resume();  // Receive the next value
  }

  if (step == 4)
  {
    if ((millis() - prevMillis) >= (DROP_INTERVAL * 1000UL))
    {
      Serial.print("step = ");
      Serial.println(step);
      moveServo(4);
      step = 0;
    }
  }

  switch (step)
  {
    case 0:
      if (commandReceived == true)
      {
        if (nextStep == false)
        {
          nextStep = true;
          moveServo(0);
          prevMillis = millis();
        }
        else
        {
          if ((millis() - prevMillis) >= (DROP_INTERVAL * 1000UL))
          {
            nextStep = false;
            commandReceived = false;
            moveServo(1);
          }
        }
      }
      break;
    case 1:
      if (commandReceived == true)
      {
        if (nextStep == false)
        {
          nextStep = true;
          moveServo(2);
          prevMillis = millis();
        }
        else
        {
          if ((millis() - prevMillis) >= (DROP_INTERVAL * 1000UL))
          {
            nextStep = false;
            commandReceived = false;
            step = 4;
            moveServo(3);
            prevMillis = millis();
          }
        }
      }
      break;
    default:
      break;
  }
}

void translateIR()
{
  // Takes command based on IR code received
  switch (receiver.decodedIRData.command)
  {
    case 48:
      Serial.println("Button pressed: 1");
      step = 0;
      commandReceived = true;
      break;
    case 24:
      Serial.println("Button pressed: 2");
      commandReceived = true;
      step = 1;
      break;
    default:
      Serial.print("Other button: ");
      Serial.println(receiver.decodedIRData.command);
  }
}

void moveServo(byte move)
{
  Serial.print("move = ");
  Serial.println(move);

  switch (move)
  {
    case 0:
      leftSide.write(180);
      break;
    case 1:
      leftSide.write(90);
      break;
    case 2:
      rightSide.write(0);
      break;
    case 3:
      rightSide.write(90);
      break;
    case 4:
      leftSide.write(180);
      rightSide.write(0);
      break;
    default:
      break;
  }
}

I don't know how do you pretend to simulate put the side back in place.

Maybe you should dettach the servo at move = 0, then move the servo manually to right position, after attach the servo again to keep it in place.

Remember to always write the position before attach a servo.

Play here:

Button 1 will drop the left side and 2 the right side. Both sides will drop after DROP_INTERVAL when step = 4.

Got It all working with 1 button with EZButton thanks for the help.
Ive keeped the other button for now incase I want something else later.

Im trying to rest the count to 0 after the 4th press.
I tried countleft = 0; at the end
but does not work.
anyone know an easy way to reset it.
thanks

#include <ezButton.h>
#include <Servo.h> 
ezButton buttonleft(7);
ezButton buttonright(8);  // create ezButton object that attach to pin 7;
Servo servoleft;  
Servo servoright; 
// Tracks the button state. 
int dt=50; 
int pos = 50;

void setup() {
    servoleft.attach(9);
    servoright.attach(10);
  Serial.begin(9600);
  servoleft.write(87);
  servoright.write(77);
  buttonleft.setCountMode(COUNT_FALLING);
  buttonright.setCountMode(COUNT_FALLING);

}

void loop() {
  buttonleft.loop(); 
   buttonright.loop();// MUST call the loop() function first
   unsigned long countleft = buttonleft.getCount();
   unsigned long countright = buttonright.getCount();
   

 delay(dt);
if(buttonleft.isPressed() && countleft == 1){
   Serial.println("The button right is pressed");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!

servoright.write(40); // Move servo to 180 degrees!
delay(500);      // Wait 1 second
for (pos = 40; pos <= 77; pos += 1) { /* goes from 0 to 70
                                          degrees in steps
                                          of 1 degree */
                                       
servoright.write(pos); 
    delay(5);  
 }
 

}
if(buttonleft.isPressed() && countleft == 2){
   Serial.println("The button right is pressed");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!

servoright.write(40); // Move servo to 180 degrees!
delay(500);      // Wait 1 second
for (pos = 40; pos <= 77; pos += 1) { /* goes from 0 to 70
                                          degrees in steps
                                          of 1 degree */
                                       
servoright.write(pos); 
    delay(5);  
 }
 

}


if(buttonleft.isPressed() && countleft == 3){
   Serial.println("The button right is pressed");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!

servoleft.write(130); // Move servo to 180 degrees!
delay(500);      // Wait 1 second
 for (pos = 130; pos >= 87; pos -= 1) {/* goes from 0 to 70
                                          degrees in steps
                                          of 1 degree */
    
                 // go to position 'pos'
    
servoleft.write(pos); 
    delay(5);  
                                       

 }
 

}
if(buttonleft.isPressed() && countleft == 4){
   Serial.println("The button right is pressed");
     // Delay just means WAIT! Remember every 
                  // 100 = 0.1 second!
servoright.write(40); 
servoleft.write(130); // Move servo to 180 degrees!
delay(500);      // Wait 1 second

servoright.write(77); 
servoleft.write(87);                                    
countleft = 0;
 }
 

}

Found it
buttonleft.resetCount();

thanks again for all the help

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.