HELP - I need a button press to BREAK A LOOP...etc

Hi All!!

Noob here. Not a pro programmer or anything, but I have a problem that I simply CAN NOT fix!

Refer to the code below, but in a nutshell I have an RGB (common anode) LED and a pushbutton linked to pin-12.

Each time the button is pressed, the program cycles through various static modes (one color per mode). Everything works fine.

BUT, the LAST mode is a "fade" mode (Mode 6) that fades slowly through all 256 colors, and repeats the fade cycle 500 times. However, sometimes I want to press a button to break the loop and return to mode-0 (where the LED values represent an OFF mode).

I know I need some kind of listener in the WHILE loop to check for a button press, and I need some set of loops to check the state of the button in order to break out of the loop, etc.... but please believe me when I tell you that I have been working on these <10 lines of code for more than 6 hours and I CAN NOT get this to work. I have tried all sorts of loops, variables, counters, etc., etc., etc., at all parts within and around this WHILE loop. I have removed all the excess from the code below so that you can clearly see what the program is doing.

Can somebody please help me out and provide me with the code that will listen for a button press within the WHILE loop and exit me back to Mode-0?????

I would appreciate it SO much!!

-Dave

//
// Common-anode LED color chooser
//
// Provides button-actuated color modes, and a final mode that 
// cycles an RGB common-anode LED through 256 color combinations
//
// Revised by David DeProspero - 2010-2011
//

int redPin = 5;     // PWM pin for RED pin
int greenPin = 6;   // PWM pin for GREEN pin
int bluePin = 3;    // PWM pin for BLUE pin
int button = 12;    // Button connected to pin 12 (using sensor shield connected)
int val=0;           // variable for reading the button status
int state=0;           // variable to hold the last button state
int presses = 0;    // how many times the button was pressed
int mode = 0;       // what mode the color picker is in



// Fades UP an active-low or common-anode output.
//
void fadeUp(int pin, int d = 10)
{
  int i;
  for (i = 255; i >= 0; i--)
  {
    analogWrite(pin, i);
    delay(d);
  }
}



// Fades DOWN an active-low or common-anode output.
//
void fadeDown(int pin, int d = 10)
{
  int i;
  for (i = 0; i <= 255; i++)
  {
    analogWrite(pin, i);
    delay(d);
  }
}



// Set up outputs, read button inputs, select operational mode (in scaner mode, give full high values so the
// LEDs start off.  Then fade in the green LED.
//
void setup()
{
  state = digitalRead(button); //reads buttons start position
} 

void loop(){ 
val = digitalRead(button); //sets val to the state of the button press
delay(10); //debounce multiple button presses

if (val != state){ //compares button press to current state 
  if (val == LOW){ 
    if (mode == 0){ //if mode is zero and button was pressed, set mode to 1
        mode = 1; 
    } 
      else { 
            if (mode == 1) { //increment mode to 2 
                mode = 2;
            } 
               else { 
                     if (mode == 2){ 
                         mode = 3; 
                      } 
                         else { 
                                if (mode == 3){ 
                                    mode = 4; 
                                }
                                 else { 
                                        if (mode == 4){ 
                                            mode = 5; 
                                        }
                                        else { 
                                                if (mode == 5){ 
                                                    mode = 6; 
                                                   } 
                                        } 
                                 } 
                          }
               } 
      } 
   } 
state = val; 
} 




if (mode == 0){ //ALL OFF //mode 0 turns all LEDs off
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 255);
  analogWrite(greenPin,255);
  analogWrite(bluePin, 255);
}




if (mode == 1){ // RED
 pinMode(redPin, OUTPUT);
 pinMode(greenPin, OUTPUT);
 pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 255);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 255);
//count++;
}




if (mode == 2){ // GREEN
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 255);
  analogWrite(greenPin, 255);
  analogWrite(bluePin, 0);
//count++;
}




if (mode == 3){ // BLUE
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 0);
  analogWrite(greenPin, 255);
  analogWrite(bluePin, 255);
//count++;
}




if (mode == 4){ // WHITE
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 0);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 0);
//count++;
}




if (mode == 5){ // VIOLET
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 0);
  analogWrite(greenPin, 125);
  analogWrite(bluePin, 255);
//count++;
}




if (mode == 6){ // FADE
 pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  analogWrite(redPin, 255);
  analogWrite(greenPin, 255);
  analogWrite(bluePin, 255);

  fadeUp(bluePin);
  
  byte number = 0;
  
  while (number < 500){ 
// counter loop to cycle through RGB LEDs 500 times.
// The cycle of ramps will go through all of the primary
// and secondary hues in the RGB rainbow, and repeat.
//
//
//PROBLEM: I need to be able to press the button on pin-12 at any point IN this loop 
//         (if I don't want to do the full 500 cycles), and return back to MODE-0 (all OFF)
//


  fadeUp(greenPin);
  fadeDown(bluePin);
  fadeUp(redPin);
  fadeDown(greenPin);
  fadeUp(bluePin);
  fadeDown(redPin);
number++;
  }
 // count++;
}

}

First thing I notice is that huge long block to increment mode. The only case where mode != mode + 1 is when mode = 6.

The else part does not need to be in curly braces, when it consists of a single if statement.

if(mode == 0)
   mode = 1;
else if(mode == 1)
   mode = 2;

is a lot shorter, but even this is unnecessary.

mode++;
if(mode == 6)
   mode = 1;

The rest of the code consists of incompatible blocks

if(mode == 0)
{ }
if mode == 1)
{ }

Is there any value for mode that would allow more than 1 block to execute?

It is not necessary to set pinMode in each block. That should be done once, in setup().

In the while loop, you can call digitalRead() to get the state of the switch, and use break; to exit the while loop, if the switch is pressed.

You might want to test for switch presses in fadeUp and dadeDown, exit the for loop if the button is pressed, and return a boolean (true or false) from the functions. If the function returns false, break out of the while loop.

Hi PaulS - thanks for the response!

Also, thank you for providing some refined code and explanations. Like I said, I'm not a pro programmer.... this worked, so I stuck with it!
:slight_smile:

To answer your question, no, there is no mode where more than one block will execute. This should just be a simple little application, but it has turned out to be quite long (probably because of my extra code).

I had considered using a break statement in a loop, but wasn't sure how that would affect the overall application. What I need is to go from the last mode (the fader mode) back to mode 0 (all light pins off) in an infinite loop. Would break revert me back to the original mode??

If so, do you have an example of some code that I might be able to try out in there, or modify, to test its functionality??

THANKS!!

-Dave

What I need is to go from the last mode (the fader mode) back to mode 0 (all light pins off) in an infinite loop. Would break revert me back to the original mode??

The mode should change each time the button is pressed, right? That's what this code does.

mode++;
if(mode == 6)
   mode = 0;

At the top of the while loop, add:

if(digitalRead(buttonPin) == LOW)
{
   mode++;
   if(mode == 6)
      mode = 0;
   break;
}

This will test for a switch press. If the switch has been pressed, the mode will be incremented, and the while loop will end. You could add this code after each fadeUp() and fadeDown() call, to minimize the amount of time you need to wait to recognize a button press.