Using a push button to toggle between 2 LED blink intervals without using delay?

I've been trying to create what I thought would be a simple project and am having a rough go of it. I need to use a push button to toggle between two blink rates for a single LED without using any delay() commands.

I've poured over the Multi Blink and Blink Without Delay samples, but I'm having trouble making a leap forward. Any direction on where to start would be super helpful.

You also need to look at the Debounce example. This is actually a really simple kind of thing to do, all you need is the Debounce and BlinkWithoutDelay examples.

Open the Debounce example, and copy the entire loop function over to your sketch. Rename the function to something like read_button(). Also copy over the global variables the function is using, like buttonState and lastDebounceTime.

Open the BlinkWithoutDelay example, and copy its entire loop() function into your sketch, renaming the function to something helpful like blink_led(). Copy over the relevant global variables for this function do.

In the read_button() function, remove the lines that deal with flashing the LED.

ledState = !ledState;
// set the LED:
  digitalWrite(ledPin, ledState);

At the place that had ledState = !ledState;, put logic that changes the interval variable that changes the flashing rate of the LED.

In your loop function, all you need to do now is call the read_button() and blink_led() functions, and that's it! Took me less than 10 minutes, including the time it took to write the first half of this post at the same time. Here's the result:

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers
const int buttonPin = 12;    // the number of the pushbutton pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// constants won't change. Used here to set a pin number :
const int ledPin =  13;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
long interval = 500;           // interval at which to blink (milliseconds)


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

void loop() {
  blink_led();
  read_switch();
}

void read_switch() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == LOW)
      {
        if( interval == 500 )
          interval = 250;
        else
          interval = 500;
      }
    }
  }

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

void blink_led() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

I needed to change 2 extra things:

My button's hooked to pin 12, not 2 line in the debounce example.
I use the internal pullup resistors, so pinMode(12, INPUT_PULLUP)

There's one other important thing that needed to be changed after a copy+pasted it in, but I'll leave that for you to find. It'll generate a compiler error if you don't delete it, so you can't miss it.

POP QUIZ! The order of blink_led() and read_switch() does not matter. If you reverse them like this, the code will still function exactly the same.:

void loop() {
  read_switch();
  blink_led();
}

Take your time to understand why this works like that.

Wow. See, this is my main problem with amateur Arduino coding. Most things I try to tackle are simple add ons to code I'm writing, but the possibilities are so vast and I go down such deep rabbit holes in search of examples to work from that I forget what I'm trying to do is relatively simple.

Thanks so much for the guidance!