How to blink (or flash) a LED without delay() and detect button pushes
One of the limitations of the delay() function is that nothing else can really be done. This presents a problem when you want to flash a LED while waiting for a pushbutton to be pressed. Flashing the LED with millis() and using a flag variable to find if the LED should be flashing solves this problem. Consider this another example to my virtual millis() cookbook. This code (below) should work with both Arduino (AVR) and Energia (supported boards), but to be honest, I haven’t had a chance to test it on my MSP430 yet.The Hardware
Very simple setup. A led with current limiting resistor connect from the I/O pin to ground. The push button is connected with an external pull-up, but you could use the Arduino’s or MSP430’s internal pull-up instead. (To be honest, I just needed the image to look more interesting than JUST a button, so I used external resistors!)The Code
You can also download this code from Pastebin.
const byte button=2;
const byte LED=10;
bool blinking = false; //defines when blinking should occur
unsigned long blinkInterval = 250; // number of milliseconds for blink
unsigned long currentMillis; // variables to track millis()
unsigned long previousMillis;
void setup() {
pinMode(button, INPUT);
pinMode(LED, OUTPUT);
}
void loop() {
// this code blinks the LED
if (blinking) {
currentMillis = millis(); // better to store in variable, for less jitter
if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) { // enough time passed yet?
digitalWrite(LED, !digitalRead(LED)); // shortcut to toggle the LED
previousMillis = currentMillis; // sets the time we wait "from"
}
} else {
digitalWrite(LED, LOW); // force LED off when not blinking
}
int reading = digitalRead(button);
delay(50); // crude de-bouncing
if (reading==LOW) // buttons with pull-up are pressed when LOW
blinking=true; // start blinking
else
blinking=false; // stop blinking
}
The key to the code is line 16 where we check the value of “blinking” on each iteration of loop().
if (blinking) {
If the “blinking” flag is set to true, that code executes.
The if-statement with currentMillis() and previousMillis() is to see how long we’ve waited to change the state of the LED pin.
if ((unsigned long)(currentMillis - previousMillis) >= blinkInterval) {
That’s how to handle a millis() rollover.
The next line of magic is at line 25. Here, the button is read and then sets the flag of the blinking variable.
int reading = digitalRead(button);
delay(50); // crude de-bouncing
if (reading==LOW) // buttons with pull-up are pressed when LOW
You might notice a delay() is used for button debounce. It is possible to use millis() instead to de-bounce the button, which makes this code entirely non-blocking. However, adds a little more complexity than necessary in this example.
In other words, some times it is okay to use delay()!
So with just a couple of simple if-statements and flag variables, it is very easy to use a pushbutton to start and stop the blinking of a LED.
What is a case you wanted to remove delay() and make your code millis() compatible?
10 Comments
This makes the led blink as long as you hold the button down. How would you modify this to make it so that the led continues to blink until you press the button again?
Hey. Alot of examples of the milis function involve LEDs. I am working on some code for stepper motors and buttons to control the FF and RW of them. I am using the adafruit motor shield v2 to drive the steppers. I have some working code. But I can only use one button at a time. Was told that the milis function help me with this issue
Thanks
This is a great example, how would you add more than one LED to this program? i.e. 2 LED’s blinking at different rates only when a button or switch is pressed?
What is a case you wanted to remove delay() and make your code millis() compatible?
yes can you please post a conde with this function thanks so much
Hi James. i have a project to send ans sms when a pin is high and the next sms should only fire off after a certain no. of hours eg 6hrs . can this be done using mills?. I currently trying to change to mills but cant seem to get it right.
Regards ivan
Take a look at this example: https://www.baldengineer.com/use-millis-with-buttons-to-delay-events.html
Hello. Maybe a stupid question: why do you cast (currentMillis – previousMillis) >= blinkInterval if all operators are already unsigned long? Thanks
For clarity. Sometimes the “interval” variable will be an int or signed long.
Hi, I am new to Arduino and love the help from your site. Question: shouldn’t the resistor and plus voltage be attached to pin 2 side of the switch to keep the input from floating?
Keep up the good work!
You’re right. I rotated the pins of the pushbutton in my mind. The images have been updated.