Stop Led's from blinking

EDITED

The Arduino loop() function makes the use of a while loop redundant in this case. Even worse: the way you've implemented that while loop prevents buttonState from being updated, thus getting stuck in the loop.

What you actually need is to use timers to blink the LED, and a 2-state machine driven by HIGH to LOW button transitions.

Try this instead:

#include "Timer.h"

// Pin 13 has a LED connected on most Arduino boards.
// give it a name:
const int led = 13;
const int buttonPin = 2;

// declare state variables as global
bool buttonState = LOW;
bool buttonState_prev = LOW;
bool toggleBlinking;
bool blinkState;

// declare a Timer object so blinking can be done without loosing button presses
Timer timer_b;
int blink_id;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  // initial state: toggle led each 1000 ms
  blink_id = timer_b.oscillate(led, 1000, HIGH);
  blinkState = true;
  toggleBlinking = false;
}

// the loop routine runs over and over again forever:
void loop() {
  // Update the timer (required)
  timer_b.update();

  // check if button has been pressed (HIGH to LOW),
  // then debounce it and raise toggle flag
  buttonState = digitalRead(buttonPin);
  if ((buttonState != buttonState_prev) && (buttonState_prev == HIGH)) {
    // simple button debounce (confirm press after some ms)
    delay (50);
    buttonState = digitalRead(buttonPin);
    if (buttonState != buttonState_prev) toggleBlinking = true;
  }

  // keep current LED state unless the button has been pushed
  switch (blinkState) {
    case true:
      // if button has been pushed, stop blinking and change LED state
      if (toggleBlinking == true) {
        timer_b.stop (blink_id);
        blinkState = false;
      }
      break;
    case false:
      digitalWrite(led, LOW);
      // if button has been pushed, start blinking and change LED state
      if (toggleBlinking == true) {
        blink_id = timer_b.oscillate(led, 1000, HIGH);
        blinkState = true;
      }
      break;
  }

  buttonState_prev = buttonState;
  toggleBlinking = false;
}

NOTE: You'll need to install the Timer.h library. I'VE TESTED MY CODE AND IT WORKS.


As the OP explained in a comment, what he is trying to achieve is to have a button alternate between blink and off, not having the button to be pressed to shut down the led.

This can be done in this way:

bool prevButtonState;
bool ledBlinking;

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

    if (prevButtonState && !buttonState)
    { // Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(1000);               // wait for a second
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        delay(1000);               // wait for a second
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

This, however, leads to a very long time between successive checks of the button (since there is a 2s delay between cycles). You can solve this using the millis function:

bool prevButtonState;
bool ledBlinking;
unsigned long prevMillis;

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

    if (prevButtonState && !buttonState)
    { // Pressing edge: there is a transition between high and low
        ledBlinking = !ledBlinking;

        prevMillis = millis() - 1000; // Force a check
    }
    prevButtonState = buttonState;

    if (ledBlinking)
    {
        if ((millis() - prevMillis) >= 1000)
        {
            prevMillis += 1000;
            digitalWrite(led, !digitalRead(led));
        }
    }
    else
    {
        digitalWrite(led, LOW);
    }
}

Next there is the debounce problem, but this becomes OT. Suggestion: use the Bounce2 library to manage the button if you experience bounces


It makes sense to make switch-testing fairly independent of blink-control. That's done in the following code, which turns blinking on or off each time a button is pressed. With this code, between button presses the LED either is off or it blinks at about a 2 Hz rate.

enum { LED=13, ButtonPin=2, BounceMS=50, BlinkMS=256 };
unsigned long buttonAt;
bool blinky, bouncy, buttonState;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP);
  blinky = bouncy = buttonState = false;
  buttonAt = millis();
}

void loop() {
  // Detect button changes
  if (bouncy) {
    if (millis() - buttonAt > BounceMS)
      bouncy = false;       // End of debounce period
  } else {
    if (digitalRead(ButtonPin) != buttonState) {
      buttonState = digitalRead(ButtonPin);
      buttonAt = millis();
      bouncy = true;        // Start debounce period
      if (buttonState) {    // Was button just pressed?
        blinky = !blinky;   // Toggle blink-state
      }
    }
  }
  // Control light-blinking
  if (blinky) {
    // Turn LED on for BlinkMS ms, then off for same 
    digitalWrite(LED, (millis() - buttonAt)%(2*BlinkMS) < BlinkMS);
  } else {
    digitalWrite(LED, LOW);
  }
}