I am working on a project that utilizes a button as an interrupt source to change colors displayed on some LEDs. In order for this to work (as the LED code uses delays), I set the interrupt to increment a simple counter against which the main loop() checks what LED color scheme should be running.
The problem I am having is this: During one of the more complicated schemes the LEDs rotate though various different colors. Doing this requires multiple different for loops and function calls (lasting in total a few seconds) before cutting back to the main loop() and checking what mode it should be in. This results in a user pressing the button and waiting a few seconds for the change.
My question is this: is it possible to for the return point for an interrupt to be the mail loop() function rather than the point at which the interrupt occurred? I assume that simply calling the loop() function would essentially mean that the program is always running as in interrupt which I obviously don't want.
An interrupt always returns to the instruction right after the last one executed when the interrupt occurred.
Would I be correct in guessing that the code for the LED schemes includes the delay() function? That would be the problem, those need to be done away with.
Neither is it necessary to use an interrupt for a button input. So we have two inappropriate techniques here, and they don't play well together either.
You might keep the delay 8)
However it is better to use millis() for timing, and have the led pattern in an array.
But for a quick fix, you can do this:
Use functions for the led patterns, so you only have to exit the function to get out of it.
Make a function that combines a delay of 1ms together with testing the button (or the increment of variable).
Let's call it DelayAndCheck(int delay). Make it to return a value when the button is pressed.
Replace all your delay in the led sequence with DelayAndCheck, and if that function returns something, exit the function of the led sequence.
So basicly, you are testing the button while waiting.
In this case, the delay function isn't causing the problem. Rather, I realized that because the interrupt returns to where it left off it has to finish all the loops (with included delays) before it will even check to see if it should change.
What I am going to try is setting a simple flag to for checking for interrupts and returning to the main loop if one is detected. I fully realize that the code I have written could be optimized quite a bit, but the code works well otherwise and I'd like to keep this simple.
glah:
In this case, the delay function isn't causing the problem. Rather, I realized that because the interrupt returns to where it left off it has to finish all the loops (with included delays) before it will even check to see if it should change.
Well yes it is the problem. While executing the delay() function, nothing else, like checking for a button press, can be done. See the famous BlinkWithoutDelay example which illustrates how to delay without the delay() function, so the code can do something while it's waiting for something else.
Peter_n's suggestion is clever and should work, but like he says I'd only consider it a quick fix. I'd try fixing it that way for now, then go master the BlinkWithoutDelay concept.
glah:
In this case, the delay function isn't causing the problem.
Using delay() is the root of the problem. Without it there would be no need for interrupts.
Look at the example here that shows how millis() can be used to control several things at the same time (including detecting a button press) without using delay() or interrupts.