Exiting a function when a button is presseed and not when it completes

Hi, I have a main loop that counts button pushes. I have a function that get called for each button push from 1-3. If function 2 takes one minutes to complete, and at 15 seconds in I push the button, I want it to exit out of function 2 and start function 3. I don’t want to put if statements checking the button pushes in the middle of all the loops in the functions. I thought that is what an interupt is for. But the description of the interupt is that it resumes where it left off. I don’t want that. How do make an immediate stop without tesintg all over the place?

Thanks

Here is my code

/*
    Bike light buzz, 
*/

int switchPin = 2;              // switch is connected to pin 2


int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state
int patternChoice = 1;              // What mode is the light in?

int middle = 6;           // the PWM pin the middle is attached to
int left = 9;
int right = 10;
int bottom = 11;
int motorlowv = 135;    // the lowest voltage the motor can start at 117
int motorhighv = 190; //the highest voltage the motor can do 184
int idle = 70;   // hopefully keep it spinning but undetectable
int fadeAmount = 5;    // how many points to fade the LED by
int delayAmt = 100;  //delay between each voltage increase

int i;
int pins[4] = {6, 9, 10, 11};

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state
  // declare pins 6,9,10,11 to be an output:
  for (i = 0; i < 4; i++); pinMode(pins[i], OUTPUT);
}

void loop() {
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2 = digitalRead(switchPin);     // read the input again to check for bounces

  if (val == val2) {                 // make sure we got 2 consistant readings!
    if ((val != buttonState) || (firstTime == 1)) {          // the button state has changed! or 1st time through
      Serial.print("val = "); Serial.print(val); Serial.print("   val2 = "); Serial.print(val2); Serial.print("   buttonState = "); Serial.println(buttonState);
      switch (patternChoice) {
        case 1:
          Serial.print("We are at "); Serial.println(patternChoice);
          delay(300);
          pattern1();
          break;
        case 2:
          Serial.print("We are at "); Serial.println(patternChoice);
          delay(300);
          pattern2();
          break;
        case 3:
          Serial.print("We are at "); Serial.println(patternChoice);
          delay(300);
          pattern3();
          break;
        default:
          Serial.print("We are at default "); Serial.println(patternChoice);
          break;
      }   //end of switch
      if (patternChoice < 3) patternChoice ++;
      else patternChoice = 1;
    }  //  end of val != buttonstate
  }   // end of val == val2
  buttonState = val;                 // save the new state in our variable
  Serial.print("End of void.....val = "); Serial.print(val); Serial.print("   val2 = "); Serial.print(val2); Serial.print("   buttonState = "); Serial.print(buttonState); Serial.print("   Pattern = "); Serial.println(patternChoice);
}   // end of void

//  functions are under this point



void pattern1() {


  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(middle, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(middle, 0);

  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(left, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(left, 0);

  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(middle, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(middle, 0);

  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(right, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(right, 0);

  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(middle, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(middle, 0);

  for (i = motorlowv; i <= motorhighv; i = i + fadeAmount) {
    // set the brightness of pin 9:
    analogWrite(bottom, i);
    // wait for 30 milliseconds to see the dimming effect
    delay(delayAmt);
  }
  analogWrite(bottom, idle);

  // wait for 3000 milliseconds to pause between a cycle
  delay(delayAmt * 2);

}  //End of pattern1


void pattern2() {
 
  for (i = 9; i < 12; i++) {
    analogWrite(i, motorhighv);
    delay(delayAmt * 2);
    analogWrite(i, 0);
    delay(delayAmt);
  }
} //End of pattern2

void pattern3() {

  for (i = 9; i < 12; i++) {
    analogWrite(i, motorhighv);
    delay(delayAmt);
    analogWrite(i, 0);
    delay(delayAmt * 2);
  }
} //End of pattern3

You'll have to get away from all the for loops and look into using while loops.

Like you said, even if you were to use interrupts, this still won’t completely stop a delay. Maybe you could implement something along the lines of the blink without delay example where you check millis and have a couple of flags that are set/cleared depending on button presses instead of delaying code execution.

Also, in the code you shared, you don’t initialise the firstTime and it never gets changed.

The correct way is to remove all calls to delay and write the code as a state machine.

As a bit of a fudge write your own delay function that terminates when the time is up or when a button is pressed.

Have a look at how millis() is used to manage timing without blocking in several things at a time

Every function runs until it completes.

If you want a responsive program you need to design every function so it completes in a few millisecs (or less). Long running jobs should be dealt with by multiple repeats of a short function.

In general only use FOR or WHILE if their loops will complete in a number of microsecs - for example, iterating over an array to find the largest value.

You may also like to look at Planning and Implementing a Program

...R