Blink without delay activate via button

Hey guys,
I want a red and green LED to blink in certain times which should be started if a button is pressed.
I am already using the millis() function, and if I just let the LEDs blink in the loop it works as it should.
Also I can turn on the LEDs with the button, so the curcuit should be fine.
When I add the 'if ' for whether the button was pressed the Red LED turns on but both don't blink how I want them to.
What do I have to change in my code to start the LEDs blinking when the button is pressed?

here is my code:

// Declare in-/outputs
const int greenLED = 10, redLED = 11;
#define BUTTON_ON_PIN 2

void setup() {
  // Initialize in-/outputs
  pinMode(redLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(BUTTON_ON_PIN, INPUT);
}

int timeRed = 7000;
int timeGreen = 4300;
int timeOff = 3000;
unsigned long previousMillis = 0;

void loop() {


  if (digitalRead(BUTTON_ON_PIN) == HIGH) {
    unsigned long currentMillis = millis();

    // Red LED
    if (currentMillis - previousMillis <= timeRed) {
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
    }
    // Green LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen) {
      digitalWrite(redLED, LOW);
      digitalWrite(greenLED, HIGH);
    }
    // Red LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);
    }
    // Off
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed + timeOff) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, LOW);
    }
    // Reset Timer
    else {
      previousMillis = currentMillis;
    }
  }
}

Welcome to the forum

What does the sketch do that is wrong ?

What is keeping the button pin LOW when the button is not pressed ?

If I only use this inside my loop, the LEDs blink:

 unsigned long currentMillis = millis();

    // Red LED
    if (currentMillis - previousMillis <= timeRed) {
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
    }
    // Green LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen) {
      digitalWrite(redLED, LOW);
      digitalWrite(greenLED, HIGH);
    }
    // Red LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);
    }
    // Off
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed + timeOff) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, LOW);
    }
    // Reset Timer
    else {
      previousMillis = currentMillis;
    }

But if I also use the if

if (digitalRead(BUTTON_ON_PIN) == HIGH)

to only let the LEDs blink when the button is pressed, the red LED gets on and doesn't blink.

So together with the if the LEDs do not blink.

if (digitalRead(BUTTON_ON_PIN) == HIGH) {
    unsigned long currentMillis = millis();

    // Red LED
    if (currentMillis - previousMillis <= timeRed) {
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
    }
    // Green LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen) {
      digitalWrite(redLED, LOW);
      digitalWrite(greenLED, HIGH);
    }
    // Red LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);
    }
    // Off
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed + timeOff) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, LOW);
    }
    // Reset Timer
    else {
      previousMillis = currentMillis;
    }
  }

Are you holding down the button when you test the sketch or do you press and release it ?

Just press and release

The code will only execute whilst you hold down the button. What happens if you hold it down ?

Ok, whilst holding down it works as it should, what do I have to change so it works when press and releasing?

  • Do you mean, you press the switch LEDs start flashing, release the switch, the LEDs continue to flash ?

You have to detect when the button becomes pressed rather than when it is pressed

See the StateChangeDetection example in the IDE

No, they only continue flashing whilst holding the button

I've done it just like in the example, but can't figure out why now when pressing the button once, the green LED is always on.
It is still working whilst pressing down the button.

int buttonState = 0;

void loop() {

  buttonState = digitalRead(BUTTON_ON_PIN);

  if (buttonState == HIGH) {
    // if (digitalRead(BUTTON_ON_PIN) == HIGH) {
    unsigned long currentMillis = millis();

    // Red LED
    if (currentMillis - previousMillis <= timeRed) {
      digitalWrite(redLED, HIGH);
      digitalWrite(greenLED, LOW);
    }
    // Green LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen) {
      digitalWrite(redLED, LOW);
      digitalWrite(greenLED, HIGH);
    }
    // Red LED
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH);
    }
    // Off
    else if (currentMillis - previousMillis <= timeRed + timeGreen + timeRed + timeOff) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, LOW);
    }
    // Reset Timer
    else {
      previousMillis = currentMillis;
    }
  }
}
  • Do you mean you want it so when you press the switch LEDs start flashing, you release the switch, you want the LEDs to continue to flash ?
//================================================^================================================
//  https://forum.arduino.cc/t/blink-without-delay-activate-via-button/1203597
//
//  
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ========================================================================
//  1.00       23/12/26    Running code
//
//
//

//================================================
#define PRESSED                    LOW    //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED                   HIGH

#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define ENABLED                    true
#define DISABLED                   false

//================================================
//Optional way of defining inputs and outputs
//#define LEDon            LOW    //+5V---[220R]---A[LED]K---PIN
//#define LEDoff           HIGH

//#define PRESSED          HIGH   //+5V---[Switch]---PIN---[10k]---GND
//#define RELEASED         LOW

//#define CLOSED           HIGH   //+5V---[Switch]---PIN---[10k]---GND
//#define OPENED           LOW

//                                            G P I O s
//================================================^================================================
const byte mySwitch                = 2;

const byte greenLED                = 10;
const byte redLED                  = 11;
const byte heartbeatLED            = 13;

//========================
//variables
bool redTIMERflag                  = DISABLED;
bool greenTIMERflag                = DISABLED;

byte lastMySwitch                  = RELEASED;

//========================
//timing stuff
unsigned long heartbeatTime;
unsigned long checkSwitchTime;
unsigned long redTime;
unsigned long greenTime;

const unsigned long  redInterval   = 7000;
const unsigned long  greenInterval = 4300;


//                                           s e t u p ( )
//================================================^================================================
void setup()
{
  Serial.begin(115200);

  pinMode(mySwitch, INPUT_PULLUP);

  digitalWrite(redLED, LEDoff);
  pinMode(redLED, OUTPUT);

  digitalWrite(greenLED, LEDoff);
  pinMode(greenLED, OUTPUT);

  pinMode(heartbeatLED, OUTPUT);

} //END of   setup()


//                                           l o o p ( )
//================================================^================================================
void loop()
{
  //========================================================================  T I M E R  heartbeatLED
  //used to see if there is code blocking happening
  //500ms, is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= 500ul)
  {
    //restart this TIMER
    heartbeatTime = millis();

    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }

  //========================================================================  T I M E R  check switches
  //50ms, is it time to scan our switches ?
  if (millis() - checkSwitchTime >= 50ul)
  {
    //restart this TIMER
    checkSwitchTime = millis();

    checkSwitches();
  }

  //========================================================================  T I M E R  red LED ON
  //7 seconds, if we are timing, is it time to turn off the red LED ?
  if (redTIMERflag == ENABLED && millis() - redTime >= redInterval)
  {
    //we are finished with this TIMER
    redTIMERflag = DISABLED;

    digitalWrite(redLED, LEDoff);
    digitalWrite(greenLED, LEDon);

    //restart the TIMER
    greenTime = millis();

    //enable the TIMER
    greenTIMERflag = ENABLED;
  }

  //========================================================================  T I M E R  green LED ON
  //4.3 seconds, if we are timing, is it time to turn off the green LED ?
  if (greenTIMERflag == ENABLED && millis() - greenTime >= greenInterval)
  {
    //we are finished with this TIMER
    greenTIMERflag = DISABLED;

    digitalWrite(greenLED, LEDoff);
  }

  //================================================
  //other non blocking code goes here
  //================================================

} //END of   loop()


//                                   c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
  byte state;

  //========================================================================  mySwitch
  state = digitalRead(mySwitch);

  //================================================
  //has this switch changed state ?
  if (lastMySwitch != state)
  {
    //update to the new state
    lastMySwitch = state;

    //========================
    //if we "are not" timing, has the switch been pressed ?
    if (redTIMERflag == DISABLED && greenTIMERflag == DISABLED && state == PRESSED)
    {
      //let's start the timing sequence
      digitalWrite(redLED, LEDon);

      //restart the TIMER
      redTime = millis();

      //enable the TIMER
      redTIMERflag = ENABLED;
    }

    //========================
    //has the switch been released (opened) ?
    else if (state == RELEASED)
    {
      //do something
    }

  } //END of this switch

  //========================================================================  nextSwitch

} //END of   checkSwitches()

1 Like

I cannot see where you are checking whether the button state has changed

What I want: If the button is pressed and released, the LEDs start flashing and do this once: red on, green on, red on, both off

In point form, describe what is supposed to happen:

    1. A switch push (closed) is detected, the switch is released (opened).
    1. The Red LED turns ON
    1. After xxx milliseconds, the Red LED goes OFF.

. . .

Hello philip101

Welcome to the world's best Arduino forum ever.

What the task of the sketch in real life?

Have a nice day and enjoy coding in C++.

you have to combine two examples:

  • Blink Without Delay
  • State Change Detection

I suggest that this should be a starting point to

  • make what's inside of loop() into a function - except the currentMillis line, leave that.
  • call that function in loop()
  • make another function just to handle the button and update a global variable when it is pressed, changes NO to YES (0 to 1) and stays YES. <aybe later something else makes in NO.
  • change the blink function to return if the button variable says NO.

When your code does not block, your functions run "parallel". You don't have to fit new things -into- existing logic structures when they run -next to- them instead. Keep indent levels down!

What you can do regarding the button and time starts with debouncing and can go to long or short pulses/pauses and sequences. Debounce is a whole topic by itself.

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