Closing my code

I am fairly new to coding and am having trouble getting my code to reach the LOW button state. It is basically a six mode led light with a button state change. I want it to turn off on the 6th button push but the RGB remains on, not going to the final light mode (solid) or off.

Here is my code:

int redPin = 3;
int bluePin = 4;
int greenPin = 5;

int redIn = 0;
int greenIn = 1;
int blueIn = 2;

int redVal;
int greenVal;
int blueVal;


int switchPin = 2;              // switch is connected to pin 2
int led1Pin = 12;
int led2Pin = 11;
int led3Pin = 10;
int led4Pin = 9;
int led5Pin = 8;

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 lightMode = 0;              // What mode is the light in?
int tim = 50;

void setup()
{
  
   Serial.begin(9600);     // Set up serial communication at 9600bps
   
  buttonState = digitalRead(switchPin);   // read the initial state
   
  

  pinMode(switchPin, INPUT);    // Set the switch pin as input

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);

redVal = 255;
  greenVal = 255;
  blueVal = 255;
  update();
}

// This function updates the LED outputs.
void update()
{
  analogWrite(redPin, redVal);
  analogWrite(greenPin, greenVal);
  analogWrite(bluePin, blueVal);
}

// This function updates one of the color variables
// either getting brighter or getting dimmer.
// It also updates the outputs and delays for 10 milliseconds.
void color_morph(int* value, int get_brighter)
{
  for (int i = 0; i < 255; i++)
  {
    if (get_brighter)
      (*value)--;
    else
      (*value)++;
      
    update();
    delay(10);
  }
}

  



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) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 0) {                               // if its off
          lightMode = 1;               // turn lights on!
        } else {
          if (lightMode == 1) {        // if its all-on
            lightMode = 2;             // make it blink!
          } else {
            if (lightMode == 2) {      // if its blinking
              lightMode = 3;           // make it wave!
            } else {
	        if (lightMode == 3) {   //  if its waving, 
                  lightMode = 4;        // make it cylon
                } else { 
                   if (lightMode == 4) {    // if its cylon
                    lightMode = 5;         // make it RGB
                     } else {
                         if (lightMode == 5) { //  if its RGB 
                              lightMode = 6;   // make it solid
                              } else {
                            if (lightMode == 6) { //  if its solid
                              lightMode = 0;   // turn it off
              }
            }
                }
          }
        }
      }
    }
  }
 }
  
 buttonState = val;                 // save the new state in our variable
}
  // Now do whatever the lightMode indicates
  
   if (lightMode == 0) { // all-off
   Serial.println ("Off");
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }
  if (lightMode == 1) {
     Serial.println ("Solid");
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, HIGH);
    delay(100);
    
  }
  
  if (lightMode == 2) {
     Serial.println ("Blink");
     
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, HIGH);
    delay(100);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
    delay(100);
  }
   if (lightMode == 3){
   Serial.println ("Cylon");
    digitalWrite(led1Pin, HIGH); //turns led1 on, or HIGH
delay(tim); //wait for tim miliseconds
digitalWrite(led2Pin, HIGH);//and so on
delay(tim);
digitalWrite(led1Pin, LOW);//turns led1 off, or LOW
delay(tim);// you get the point
digitalWrite(led3Pin, HIGH);
delay(tim);
digitalWrite(led2Pin, LOW);
delay(tim);
digitalWrite(led4Pin, HIGH);
delay(tim);
digitalWrite(led3Pin, LOW);
delay(tim);
digitalWrite(led5Pin, HIGH);
delay(tim);
digitalWrite(led4Pin, LOW);
delay(tim);
digitalWrite(led4Pin, HIGH);
delay(tim);
digitalWrite(led5Pin, LOW);
delay(tim);
digitalWrite(led3Pin, HIGH);
delay(tim);
digitalWrite(led4Pin, LOW);
delay(tim);
digitalWrite(led2Pin, HIGH);
delay(tim);
digitalWrite(led3Pin, LOW);
delay(tim);
digitalWrite(led1Pin, HIGH);
delay(tim);
digitalWrite(led2Pin, LOW);
delay(tim);
  }
  
if (lightMode == 4){
  Serial.println ("Wave");
    digitalWrite(led5Pin, LOW);
    digitalWrite(led1Pin, HIGH);
    delay(50);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, HIGH);
    delay(50);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, HIGH);
    delay(50);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, HIGH);
    delay(50);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, HIGH);
    delay(50);
    digitalWrite(led5Pin, LOW);
  }

if (lightMode == 5) {
  Serial.println ("RGB");
  color_morph(&redVal,   1); // transition to red
  color_morph(&greenVal, 1); // transition to yellow
  color_morph(&redVal,   0); // transition to green
  color_morph(&blueVal,  1); // transition to aqua
  color_morph(&redVal,   1); // transition to white
  color_morph(&greenVal, 0); // transition to violet
  color_morph(&redVal,   0); // transition to blue
  color_morph(&blueVal,  0); // transition to black (all off)
}
if (lightMode == 6) { // all-on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, HIGH);

}
}

I know it is something simple but I cant see the problem myself. Any and all help is appreciated.

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

In state 5 you call the color_morph routine several times. Within that routine you call delay(10) 255 times, so it takes more than 2.5 seconds to complete. During that time no check of the button is done, the processor is just waiting, running empty loops. You loose these 2.5 seconds 8 times (=20 seconds) and then you have 10 milliseconds to push your button. If you don't match these 10 milliseconds you have to wait 20 secs again. I guess you see the problem.

BTW: your if-then-else construct for changing the state is easier done this way:

lightMode = (lightMode + 1) % 7;

Really should into the Blink-without-delay as an example of how to make the button pushes more responsive.
Basically noting the time, setting a flag, when the time has elapsed clear the flag and proceed. Can be doing other things while time passes, like reading a button and changing conditions for if-then statements.

In state 5 you call the color_morph routine several times. Within that routine you call delay(10) 255 times, so it takes more than 2.5 seconds to complete. During that time no check of the button is done, the processor is just waiting, running empty loops. You loose these 2.5 seconds 8 times (=20 seconds) and then you have 10 milliseconds to push your button. If you don't match these 10 milliseconds you have to wait 20 secs again. I guess you see the problem.

Kinda. Like I said a am new to this so I can barely understand what that means. My whole code is stuff I pieced together using tutorials to make work... until this problem.

I don't see the delays in the color_morph state which I have repeated down below. Should I repeat detect state change if statements like the one I have at the start of the void loop:

if (lightMode == 5) {
  Serial.println ("RGB");
  color_morph(&redVal,   1); // transition to red
  color_morph(&greenVal, 1); // transition to yellow
  color_morph(&redVal,   0); // transition to green
  color_morph(&blueVal,  1); // transition to aqua
  color_morph(&redVal,   1); // transition to white
  color_morph(&greenVal, 0); // transition to violet
  color_morph(&redVal,   0); // transition to blue
  color_morph(&blueVal,  0); // transition to black (all off)
 if (val == val2){                    // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 5) {                               // if its off
          lightMode = 6;

...something like that? I can't test this until later tonight so I figured I'd just ask.
Thanks for you 'alls help thus far.

No, you have to get rid of the delay() calls. Unfortunately it's not as easy as to search/replace the call with another. You have to restructure your code. Probably the easiest for you (given you don't have to include additional features into your sketch) is to replace the delay in color_morph by a function that checks the button and then delays a bit (only if there was no state change caused by the button). This functions return value has to be checked in the main code as a state change may have occurred.

If you wanna have your code extensible and maintainable I would completely restructure it to have a big main loop and change outputs based on the current state and time. Save the time of your last phase change and wait till it's time for the next. A very easy example of this is the BlinkWithoutDelay example CrossRoads already mentioned. Compare it with the standard blink example you get the idea behind the change you have to do.

Awesome. Thanks for the help guys! I have a lot of learning to do.