Detecting a Button while a for loop runs


Your current design has a lot of delay without keypress detection.

If you make you own delay function calling smaller delays in a loop that takes ms at input maybe you can have the delay check the button in 10 ms loops in the delay function.

The delay function can return a boolean value if a keypress was detected in the delay and will tell your LED loop to exit when done fading out.

Some suggestions

Don’t use a for loop, let the loop() function do what it is good at, ie looping. At the worst that would mean that the interval between reading an input in loop() would be considerably shorter because you could read it between each change of LED brightness, and even shorter if you use millis() for timing instead of delay(). See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

Detect when the button becomes pressed instead of when it is pressed. Having loop() repeat quickly means that you can do this in loop() and still have responsive code. See the StateChangeDetection example in the IDE

Generally using long delays is not great as the program can do nothing else. A typical solution is instead to call the millis() function frequently and compare against a future "timestamp" and check if "time is up" for something to do.

Here is how you make a simple timer in your main program. Just call it with short delays from your main loop and it will tell you when time is up to do something. Or you can put some code inside the isTimerEvent()

Just call SetInterval() in the program init() section and whenever you want to change the pace of the timer.

unsigned long _interval=0;
unsigned long _timeStarted=0;

//Set timer interval and reset the timer
void SetInterval(long intervalMs)
	_interval = intervalMs;
	_timeStarted = millis();

//Call this from the main loop
//Returns true if timer event and prolongs the timer for next event
bool isTimerEvent()
	//Check if timer interval has elapsed
	//Rollover safe we hope
	bool retval = (millis() - _timeStarted >= _interval);
	if (retval)
		//Timer trigged - Set new start time
		_timeStarted = millis();
		//Add some function call here to fire at timer intervals
		//Code here if you like *
	return retval;

More advanced?

Another idea is to use pin change interrupt and have the Arduino input hardware detect your button. This way at least you can detect the button even in a delay.

Then your LED routine will be able to see what button status the interrupt has detected when it gets out of a delay and can fade out and exit.