Using an ISR to start over on a Nano

There are many ways to handle this issue.

Here's one off the wall. It uses the setjmp/longjmp mechanism to switch by pushbutton on an interrupt, between as many loop() -like functions as you have room for. Try it out, the demo switches between three loop-like functions.


Wokwi_badge setjmp/longjmp demo


// https://wokwi.com/projects/373311239978862593
// https://forum.arduino.cc/t/using-an-isr-to-start-over-on-a-nano/1158993

// also see post 30, and the thread that this came from
// https://forum.arduino.cc/t/question-that-probably-has-a-really-obvious-answer-but-im-just-too-dumb-to-find-it/887654/30


/* setjmp example */

# include <setjmp.h>

# define numLoops	3
# define myButton	3
# define theLED	LED_BUILTIN

static jmp_buf buf;

int whichLoop = 0;

unsigned char once = 0;

volatile unsigned char ignore = 0;

volatile int ignored = 0;

void myISR()
{
	if (ignore) {
		ignored++;
		return;
	}

	detachInterrupt(digitalPinToInterrupt(myButton));
	ignore = 1;
	
	/* and  yank the big lever */
	longjmp(buf, 1);
}

void setup() {

	Serial.begin(115200);
	Serial.println("hello setjmp/longjmp world!\n");

	pinMode(myButton, INPUT_PULLUP);
	pinMode(theLED, OUTPUT);
}

void loop()
{
	for (; ; ) {
		while (1) {
			if (!setjmp(buf)) {

				EIFR |= (1 << digitalPinToInterrupt(myButton));		// clear flag on button interrupt
				attachInterrupt(digitalPinToInterrupt(myButton), myISR, FALLING);
//				delay(20);
				ignore = 0;
				break;						// normal return, just start looping
			}
			else {							// big lever return, do whatever, then start mostly all over
				whichLoop++;
				if (whichLoop >= numLoops)
					whichLoop = 0;
	
				Serial.println("");
				if (ignored) { Serial.print(" ignored "); Serial.print(ignored); }
				Serial.print("switching to loop "); Serial.print(whichLoop);
				Serial.println("");
				delay(500);					// very poor man's debounce - get off that switch
			}
		}
		for (; ; )
			loopDispatch();
	}
}

void loopDispatch() {
	switch (whichLoop) {
	case 0 :
		loop0();
		break;

	case 1 :
		loop1();
		break;

	case 2 :
		loop2();
		break;
	}
}

void loop0()
{
	static unsigned char toggle;

	digitalWrite(LED_BUILTIN, ++toggle & 0x1);

	delay(333);
}

void loop1()
{
	int counter = 0;

	for (; ; ) {
		Serial.print("loop 1 : ");
		Serial.println(counter);

		counter++;

		delay(33);
	}
}

void loop2()
{
	static int counter = 0;

	Serial.print("loop 2 : ");
	Serial.println(counter);

	counter++;

	delay(33);
}

There is only the need to get off the button in less than 500 milliseconds, otherwise you'll skip ahead in the cycle of loops.

It's a bit delicate, so don't get too creative with the mechanism.

Close readers will wonder about this

void loop()
{
	for (; ; ) {

captivated loop with a infinite loop... read here:


a7