Blinking without delay latching button circuit

Hi there, I am currently trying to write a program to blink the onboard LED of an Arduino UNO at a rate of 2hz.

I am using tinkercad. I have a breadboard wired to the Arduino with a pull-down resistor switch circuit. With a press of the button, the LED should go from OFF to flashing, then with another button press, the LED should go from flashing to OFF.

My issues with my current program are that the LED starts out flashing and on the second button press the LED sticks in whatever state it was in when the button was pressed. ie if the LED is on when the button is pressed for the second time it remains on.

I am unsure how to go about correcting this, any help would be very much appreciated!

const int ledPin =  LED_BUILTIN;
const int  buttonPin = 2; 

int ledState = LOW;
int buttonPushCounter = 0;   
int buttonState = 0;         
int lastButtonState = 0; 

unsigned long previousMillis = 0;

const long interval = 250;


void setup() {
  
   
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
 
}

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

 
  if (buttonState != lastButtonState) {
    
    if (buttonState == HIGH) {
      
      buttonPushCounter++;

    } 
    
    delay(50);
  }
  
  lastButtonState = buttonState;
  
  
  if (buttonPushCounter % 2 == 0) {
    unsigned long currentMillis = millis();
  
  
  
  if (currentMillis - previousMillis >= interval) {
    
    previousMillis = currentMillis;

    
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    
    digitalWrite(ledPin, ledState);
  }
  }
}
  

You need to start your flashing when the button changes, and the check your flashing every time through loop

const int ledPin =  LED_BUILTIN;
const int  buttonPin = 2;

byte buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;

unsigned long previousMillis = 0;

const unsigned long interval = 250;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  isLedOn = false;
}

void loop() {
  unsigned long currentMillis = millis();

  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      if (buttonPushCounter % 2 == 0) {
        // turn off
        digitalWrite(ledPin, LOW);
      }
      else {
        // start flashing
        digitalWrite(ledPin, HIGH);
        previousMillis = currentMillis;
      }
    }
    delay(50);
  }

  lastButtonState = buttonState;

  if (buttonPushCounter % 2 == 1) {
    // check if time to flash
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(ledPin, !digitalRead(ledPin));
    }
  }
}
1 Like

After doing the thing from post #2, I have a few suggestions as to tweaks or adjustments.

Why delay? Mixing delay() and millis is NOT a good idea. as an FYI.

if( millis() - previousMillis >=) gives a more current millis reading then using a millis reading from the past.

Hello
Try and check out this sketch for your project.

const int ledPin =  LED_BUILTIN;
const int  buttonPin = 2;
int ledState = LOW;
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;
unsigned long previousMillis = 0;
const long interval = 250;
void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}
void loop() {
  buttonState = !digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    lastButtonState = buttonState;
    if (buttonState == HIGH) {
      buttonPushCounter++;
    }
    delay(50);
  }
  //  lastButtonState = buttonState;
  //  if (buttonPushCounter % 2 == 0) {
  unsigned long currentMillis = millis();
// ---> the millis timer is extended by a on/off control using (buttonPushCounter & 1)
  if (currentMillis - previousMillis >= interval && (buttonPushCounter & 1)) {
    previousMillis = currentMillis;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}

Thank you all for your help! I have made the adjustments that blh64 set out in post #2 and the script is now working as desired.

If I wanted to add another setting for the LED, flashing at 5 hz, after the third button press. So the sequence would be off, 2hz flashing, 5hz flashing, off. Could I still use the button counter to do that? Or would there be a better way to do that?

Have answered this for myself! Thank you again guys for your help.

const int ledPin =  LED_BUILTIN;
const int  buttonPin = 6;

int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;

unsigned long previousMillis = 0;

const unsigned long interval = 250;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  
}

void loop() {
  unsigned long currentMillis = millis();

  buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
      if (buttonPushCounter % 3 == 0) {
        
        digitalWrite(ledPin, LOW);
      }
      else {
       
        digitalWrite(ledPin, HIGH);
        previousMillis = currentMillis;
      }
    }
  
  }

  lastButtonState = buttonState;

  if (buttonPushCounter % 3 == 1) {
    
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      digitalWrite(ledPin, !digitalRead(ledPin));
    }
  }
  if (buttonPushCounter % 3 == 2) {
    
    if (currentMillis - previousMillis >= interval/2.5 ) {
      previousMillis = currentMillis;
      digitalWrite(ledPin, !digitalRead(ledPin));
    }
  }
1 Like