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);
}
}