ISR and Continuous Looping

I am really new to Arduino and programming. Just got my 1st Arduino about a month ago and I have become completely obsessed with it.
Currently I am having an issue with not knowing how to create/stop a continuous loop that would stop and go back to the main function. I have tried while() and don't have enough knowledge to setup or use an ISR.
Specifically, I would like, in the code below, to have randomLed() loop until a key is pressed and in rainbow() I would like to be able to stop it at any time during the routine.
Any help/ideas would be greatly appreciated.

#define DEBOUNCE 5
#define NUMBUTTONS sizeof(buttons)
#define LCD_CS A3 
#define LCD_CD A2 
#define LCD_WR A1
#define LCD_RD A0 
#define LCD_RESET A4

#include <SPI.h>
#include "Adafruit_GFX.h"
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
//fonts used in project
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>

// Assign human-readable names to some common 16-bit color values:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

byte buttons[] = {26, 27, 28, 29}; //button pin array
int redPin = 44;
int greenPin = 45;
int bluePin = 46;
int rVal = 0;
int gVal = 0;
int bVal = 0;

// variable for reading the pushbutton status
byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
byte previous_keystate[NUMBUTTONS], current_keystate[NUMBUTTONS];
int buttonCounter = 0;   // counter for the number of button presses
int ledColor;
bool randomColor = false;
bool rainColor = false;


void setup()
{
  byte i;
    for (i = 0; i < NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT);
    digitalWrite(buttons[i], HIGH);
  }
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  //turn off LED
  analogWrite(redPin, 255);
  analogWrite(greenPin, 255);
  analogWrite(bluePin, 255);
  //set up TFT screen and static information
  tft.begin(0X9481);
  tft.fillScreen(~BLACK);
  tft.setRotation(1);
  tft.drawRect(198, 140, 259, 26, ~WHITE); //slider area outline
  tft.drawRect(198, 181, 259, 26, ~WHITE);
  tft.drawRect(198, 222, 259, 26, ~WHITE);
  tft.drawRoundRect(298, 26, 157, 103, 5, ~WHITE);//LED color outline
  //set up area lables
  tft.setTextColor(~CYAN);
  tft.setFont(&FreeSans18pt7b);
  tft.setCursor(50, 50);
  tft.print("TFT LED");
  tft.setCursor(18, 90);
  tft.println("Color Changer");
  tft.setFont(&FreeSans12pt7b);
  tft.setCursor(50, 162);
  tft.setTextColor(~RED);
  tft.print("Red");
  tft.setCursor(99, 162);
  tft.setTextColor(~CYAN);
  tft.print("Level");
  tft.setCursor(40, 203);
  tft.setTextColor(~GREEN);
  tft.print("Green");
  tft.setCursor(111, 203);
  tft.setTextColor(~CYAN);
  tft.print("Level");
  tft.setCursor(48, 244);
  tft.setTextColor(~BLUE);
  tft.print("Blue");
  tft.setCursor(101, 244);
  tft.setTextColor(~CYAN);
  tft.print("Level");
  tft.setFont(&FreeSans9pt7b);
  tft.setCursor(300, 23);
  tft.print("Current LED Color");
  tft.setCursor(70, 300);
  tft.print("Randomizer");
  tft.setCursor(200, 300);
  tft.print("Rainbow");
}


void sendColor(int red, int green, int blue) {
  // Sends PWM signal to the pins of the led
  analogWrite(redPin, ~red);
  analogWrite(greenPin, ~green);
  analogWrite(bluePin, ~blue);
  ledColor =  tft.color565(red, green, blue);
  // Draws a rectangle with the latest color values
  tft.fillRoundRect(300, 27, 153, 100, 5, ~ledColor);
  //red slider
  tft.fillRect((red + 200), 142, (255 - red), 22, ~BLACK);
  tft.fillRect(200, 142, red, 22, ~RED);
  //green slider
  tft.fillRect((green + 200), 183, (255 - green), 22, ~BLACK);
  tft.fillRect(200, 183, green, 22, ~GREEN);
  //blue slider
  tft.fillRect((blue + 200), 224, (255 - blue), 22, ~BLACK);
  tft.fillRect(200, 224, blue, 22, ~BLUE);
}


void check_switches()
{
  static byte previousstate[NUMBUTTONS];
  static byte currentstate[NUMBUTTONS];
  static long lasttime;
  byte index;
  if (millis() < lasttime) {
     lasttime = millis();
  }
  if ((lasttime + DEBOUNCE) > millis()) {
     return;
  }
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();
  for (index = 0; index < NUMBUTTONS; index++) {
    justpressed[index] = 0;
    justreleased[index] = 0;
    currentstate[index] = digitalRead(buttons[index]); 
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
        justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
        justreleased[index] = 1; 
      }
      pressed[index] = !currentstate[index]; 
    }
    previousstate[index] = currentstate[index]; 
  }
}

byte thisSwitch_justPressed() {
  byte thisSwitch = 255;
  check_switches();  
  for (byte i = 0; i < NUMBUTTONS; i++) {
    current_keystate[i] = justpressed[i];
    if (current_keystate[i] != previous_keystate[i]) {
      if (current_keystate[i]) thisSwitch = i;
    }
    previous_keystate[i] = current_keystate[i];
  }
  return thisSwitch;
}


void setLedColor() {
  if (randomColor) {
    randomLed();
    return;
  }
  if (rainColor) {
    rainbow();
    return;
  }
  //draws the highlights for active slider or option
  if (buttonCounter == 1) {
    //contains info to draw highlights around items removed to save space
  }
  if (buttonCounter == 2) {
    //contains info to draw highlights around items removed to save space
  }
  if (buttonCounter == 3) {
    //contains info to draw highlights around items removed to save space
  }
  if (buttonCounter == 4) {
    //contains info to draw highlights around items removed to save space
  }
  if (buttonCounter == 5) {
    //contains info to draw highlights around items removed to save space
  }
  sendColor(rVal, gVal, bVal);
}


void randomLed() {
  int RrVal = random(255);
  int GrVal = random(255);
  int BrVal = random(255);
  sendColor(RrVal, GrVal, BrVal);
  randomColor = !randomColor;
}


void rainbow() {
  tft.drawRect(198, 283, 75, 25, ~RED); //rainbow highlight red to show busy
  int r;
  for (r = 0; r < 255; r = r + 5) 
  {
    sendColor(0 + r, 0, 0);
  }
  for (r = 0; r < 255; r = r + 5) 
  {
    sendColor(255, 0 + r, 0);
  }
  for (r = 0; r < 255; r = r + 5)
  {
    sendColor(255 - r, 255, 0);
  }
  for (r = 0; r < 255; r = r + 5) 
  {
    sendColor(0, 255, 0 + r);
  }
  for (r = 0; r < 255; r = r + 5)
  {
    sendColor(0, 255 - r, 255);
  }
  for (r = 0; r < 255; r = r + 5) 
  {
    sendColor(0 + r, 0, 255);
  }
  for (r = 0; r < 255; r = r + 5)
  {
    sendColor(255, 0, 255 - r);
  }
  for (r = 0; r < 255; r = r + 5) 
  {
    sendColor(255 - r, 0, 0);
  }
  for (r = 0; r < 255; r = r + 5)
  {
    sendColor(0 + r, 0 + r, 0 + r);
  }
  for (r = 0; r < 255; r = r + 5)
  {
    sendColor(255 - r, 255 - r, 255 - r);
  }
  rainColor = !rainColor;
  tft.drawRect(198, 283, 75, 25, ~YELLOW); //rainbow highlight to yellow to show ready
}


void loop() {
  byte thisSwitch = thisSwitch_justPressed();
  switch (thisSwitch)
  {

    case 0:
      if (buttonCounter >= 5) {
        buttonCounter = 0;
      }
      buttonCounter += 1;
      setLedColor();
      break;

    case 1:
      if (buttonCounter == 1) {
        if (rVal <= 0) {
          rVal = 5;
        }
        rVal = rVal - 5;
      }
      if (buttonCounter == 2) {
        if (gVal <= 0) {
          gVal = 5;
        }
        gVal = gVal - 5;
      }
      if (buttonCounter == 3) {
        if (bVal <= 0) {
          bVal = 5;
        }
        bVal = bVal - 5;
      }

      if (buttonCounter == 4) {
        randomColor = !randomColor;
      }
      if (buttonCounter == 5) {
        rainColor = !rainColor;
      }

      setLedColor();
      break;

    case 2:
      if (buttonCounter == 1) {
        if (rVal >= 255) {
          rVal = 250;
        }
        rVal = rVal + 5;
      }
      if (buttonCounter == 2) {
        if (gVal >= 255) {
          gVal = 250;
        }
        gVal = gVal + 5;
      }
      if (buttonCounter == 3) {
        if (bVal >= 255) {
          bVal = 250;
        }
        bVal = bVal + 5;
      }

      if (buttonCounter == 4) {
        randomColor = !randomColor;  //set to TRUE so random LED runs
      }
      if (buttonCounter == 5) {
        rainColor = !rainColor;  //set to TRUE so rainbow LED runs
      }

      setLedColor();
      break;

    case 3:
      if (buttonCounter <= 1) {
        buttonCounter = 6;
      }
      buttonCounter -= 1;
      setLedColor();
      break;

  }
}

There should be no need for an ISR to detect a human pressing a button.

All those FORs in the function rainbow() are going to make the program non- responsive. Why are there so many of them?

I'm guessing that each one causes a particular sequence to happen. if so you should have a variable to keep track of which sequence you are on and change your code to something like this

if (sequence == 0) {
  if (stepCount < 255) {
     sendColor(0 + stepCount, 0, 0); // pattern for sequence 0
     stepCount ++;
  }
  else {
    sequence ++
    stepCount = 0;
  }
}

And something similar for each stage of the sequence. This approach allows loop() to repeat frequently and thereby detect your button press.

Also I suspect there is a much simpler way to deal with all the sequences rather than write them all out laboriously as you have done - and which would be even more laborious with the above (necessary) code. Can you describe how each sequence differs from the previous one?

...R

PS. I think this approach would be neater

if (stepCount < 255) {
    if (sequence == 0) {
        sendColor(0 + stepCount, 0, 0); // pattern for sequence 0 ?
    }
    else if (sequence == 1) {
        sendColor(255, 0 + r, 0); // pattern for sequence 1 ?
    }
    stepCount ++;
else {
    sequence ++
    stepCount = 0;
}

Thank you for your input. I am going to try and use that code.
The task of that not of code is really a count up and count down to send info to a RGB LED.
What it does is ramp up the red, then ramp up the green, the ramp down the red and so on to get the RGB LED to go through a rainbow of colors.

Delta_G, that is exactly what I would like to do, I just am not knowledgeable enough to know how to do that.

Robin2, in the mean time I did take you advice and this is what I came up with:

for (sequence = 0; sequence < 10; sequence++) {
    for (stepCount = 0; stepCount < 255; stepCount = stepCount + 5) {
      if (sequence == 0) {
        sendColor(stepCount, 0, 0);
      }
      if (sequence == 1) {
        sendColor(255, stepCount, 0);
      }
      if (sequence == 2) {
        sendColor(255 - stepCount, 255, 0);
      }
      if (sequence == 3) {
        sendColor(0, 255, stepCount);
      }
      if (sequence == 4) {
        sendColor(0, 255 - stepCount, 255);
      }
      if (sequence == 5) {
        sendColor(stepCount, 0, 255);
      }
      if (sequence == 6) {
        sendColor(255, 0, 255 - stepCount);
      }
      if (sequence == 7) {
        sendColor(255 - stepCount, 0, 0);
      }
      if (sequence == 8) {
        sendColor(stepCount, stepCount, stepCount);
      }
      if (sequence == 9) {
        sendColor(255 - stepCount, 255 - stepCount, 255 - stepCount);
      }
    }

reb3lv:
Robin2, in the mean time I did take you advice and this is what I came up with:

The principal message I was trying to get across in Reply #1 was NOT to use FOR. I seem to have failed :slight_smile:

And you seem to be mixing up the concepts in my two examples. Just use the concept in the second example. I probably should have deleted the first one, but I thought it might act as a learning link between your original concept and my second one.

...R