Help with implementing a button with an RGB LED

First, thank you all in advanced for the help.

Second, I have only had an Arduino for about a week. Although I am a complete beginner, I have had my proud moments :slight_smile:

With help I have been able to implement a FSM to go through the color wheel with a RGB LED. I would now like to learn how to switch through each case by using a button.

This is the code I am working with.

//RGB LED pins
// Mashed up from _1_RGB_Tstrorm _Test and _3LED_On_and_Off_Diff_Gotit
int ledAnalogOne[] = {9, 10, 11}; //the three pins of the first analog LED 3 = redPin, 5 = greenPin, 6 = bluePin
                                //These pins must be PWM

//Defined Colors (different RGB (red, green, blue) values for colors
//(to add your own ie. fuscia experiment and then add to the list)
const byte RED[] = {255, 0, 0}; 
const byte ORANGE[] = {83, 4, 0}; 
const byte YELLOW[] = {255, 255, 0}; 
const byte GREEN[] = {0, 255, 0}; 
const byte BLUE[] = {0, 0, 255}; 
const byte INDIGO[] = {4, 0, 19}; 
const byte VIOLET[] = {23, 0, 22}; 
const byte CYAN[] = {0, 255, 255}; 
const byte MAGENTA[] = {255, 0, 255}; 
const byte WHITE[] = {255, 255, 255}; 
const byte PINK[] = {158, 4, 79};
const byte TEST[] = {255, 255, 255 };
const byte BLACK[] = {0, 0, 0};

int led1State = 0;

long int led1time = 10UL;

unsigned long count1 = 0;

boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

void setup(){
  led1time = 1UL;
  led1State = 0; 
  
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   //Set the three LED pins as outputs
  }
  setColor(ledAnalogOne, BLACK);       //Turn off led 1
}

void loop() {
  // Act if the latter time (ms) has now passed on this particular counter,
  if (timeout(&count1, led1time )) {
    switch (led1State) {
    case 0: 
      {                              // begin the sequence
        led1State = 1;               // next step
        led1time = 2000UL;            // for half a second
        fadeToColor(ledAnalogOne, RED, ORANGE, 5); // switch it on
        break; 
      }

    case 1: 
      {
        led1State = 2;               // next step
        led1time = 2000UL;           // for however
        fadeToColor(ledAnalogOne, YELLOW, GREEN, 5);  // switch it off
        break; 
      }

    case 2: 
      {
        led1State = 3;
        led1time = 2000UL;
        fadeToColor(ledAnalogOne, BLUE, INDIGO, 5); // switch it on
        break; 
      }

    case 3: 
      {
        led1State = 4;
        led1time = 2000UL;
        fadeToColor(ledAnalogOne, VIOLET, CYAN, 5);  // switch it off
        break; 
      }
    case 4:
       {
        led1State = 5;
       led1time = 2000UL;
       fadeToColor(ledAnalogOne, MAGENTA, WHITE, 5);
       break; 
       }
    case 5:
       {
        led1State = 0;
       led1time = 2000UL;
       fadeToColor(ledAnalogOne, PINK, BLACK, 3);
       break;   
    }
      
    }}}
  
 void setColor(int* led, byte* color){
 for(int i = 0; i < 3; i++){             //iterate through each of the three pins (red green blue)
   analogWrite(led[i], 255 - color[i]);  //set the analog output value of each pin to the input value (ie led[0] (red pin) to 255- color[0] (red input color)
                                         //we use 255 - the value because our RGB LED is common anode, this means a color is full on when we output analogWrite(pin, 0)
                                         //and off when we output analogWrite(pin, 255). 
 }
}

/* A version of setColor that takes a predefined color (neccesary to allow const int pre-defined colors */
void setColor(int* led, const byte* color){
 byte tempByte[] = {color[0], color[1], color[2]};
 setColor(led, tempByte);
}

/* Fades the LED from a start color to an end color at fadeSpeed
   led - (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
   startCcolor - (byte array of three values defing the start RGB color (startColor[0] = start Red value, startColor[1] = start Green value, startColor[2] = start Red value
   endCcolor - (byte array of three values defing the finished RGB color (endColor[0] = end Red value, endColor[1] = end Green value, endColor[2] = end Red value
   fadeSpeed - this is the delay in milliseconds between steps, defines the speed of the fade
*/ 
void fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed){
  int changeRed = endColor[0] - startColor[0];                            //the difference in the two colors for the red channel
  int changeGreen = endColor[1] - startColor[1];                          //the difference in the two colors for the green channel 
  int changeBlue = endColor[2] - startColor[2];                           //the difference in the two colors for the blue channel
  int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue))); //make the number of change steps the maximum channel change
  
  for(int i = 0 ; i < steps; i++){                                        //iterate for the channel with the maximum change
   byte newRed = startColor[0] + (i * changeRed / steps);                 //the newRed intensity dependant on the start intensity and the change determined above
   byte newGreen = startColor[1] + (i * changeGreen / steps);             //the newGreen intensity
   byte newBlue = startColor[2] + (i * changeBlue / steps);               //the newBlue intensity
   byte newColor[] = {newRed, newGreen, newBlue};                         //Define an RGB color array for the new color
   setColor(led, newColor);                                               //Set the LED to the calculated value
   delay(fadeSpeed);                                                      //Delay fadeSpeed milliseconds before going on to the next color
  }
  setColor(led, endColor);                                                //The LED should be at the endColor but set to endColor to avoid rounding errors
}

/* A version of fadeToColor that takes predefined colors (neccesary to allow const int pre-defined colors */
void fadeToColor(int* led, const byte* startColor, const byte* endColor, int fadeSpeed){
  byte tempByte1[] = {startColor[0], startColor[1], startColor[2]};
   byte tempByte2[] = {endColor[0], endColor[1], endColor[2]};
   fadeToColor(led, tempByte1, tempByte2, fadeSpeed);
}

Here is about as far as I got before I got discouraged....

//RGB LED pins
// Mashed up from _1_RGB_Tstrorm _Test and _3LED_On_and_Off_Diff_Gotit
int ledAnalogOne[] = {9, 10, 11}; //the three pins of the first analog LED 3 = redPin, 5 = greenPin, 6 = bluePin
                                //These pins must be PWM

//Defined Colors (different RGB (red, green, blue) values for colors
//(to add your own ie. fuscia experiment and then add to the list)
const byte RED[] = {255, 0, 0}; 
const byte ORANGE[] = {83, 4, 0}; 
const byte YELLOW[] = {255, 255, 0}; 
const byte GREEN[] = {0, 255, 0}; 
const byte BLUE[] = {0, 0, 255}; 
const byte INDIGO[] = {4, 0, 19}; 
const byte VIOLET[] = {23, 0, 22}; 
const byte CYAN[] = {0, 255, 255}; 
const byte MAGENTA[] = {255, 0, 255}; 
const byte WHITE[] = {255, 255, 255}; 
const byte PINK[] = {158, 4, 79};
const byte TEST[] = {255, 255, 255 };
const byte BLACK[] = {0, 0, 0};

const int buttonPin = 2;

int buttonState = 0;
int led1State = 0;

}

void setup(){
  
  led1State = 0; 
  pinMode(buttonPin, INPUT);
  
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   //Set the three LED pins as outputs
  }


void loop() {
  // Act if the latter time (ms) has now passed on this particular counter,
  buttonState = fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed) 
  
  if (buttonState ==HIGH)) {
    switch (led1State) {
    case 0: 
      {                              // begin the sequence
        led1State = 1;               // next step
        led1time = 2000UL;            // for half a second
        fadeToColor(ledAnalogOne, RED, ORANGE, 5); // switch it on
        break; 
      }

    case 1: 
      {
        led1State = 2;               // next step
        led1time = 2000UL;           // for however
        fadeToColor(ledAnalogOne, YELLOW, GREEN, 5);  // switch it off
        break; 
      }

    case 2: 
      {
        led1State = 3;
        led1time = 2000UL;
        fadeToColor(ledAnalogOne, BLUE, INDIGO, 5); // switch it on
        break; 
      }

    case 3: 
      {
        led1State = 4;
        led1time = 2000UL;
        fadeToColor(ledAnalogOne, VIOLET, CYAN, 5);  // switch it off
        break; 
      }
    case 4:
       {
        led1State = 5;
       led1time = 2000UL;
       fadeToColor(ledAnalogOne, MAGENTA, WHITE, 5);
       break; 
       }
    case 5:
       {
        led1State = 0;
       led1time = 2000UL;
       fadeToColor(ledAnalogOne, PINK, BLACK, 3);
       break;   
    }
      
    }}}
  
    
 }
}



/* Fades the LED from a start color to an end color at fadeSpeed
   led - (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
   startCcolor - (byte array of three values defing the start RGB color (startColor[0] = start Red value, startColor[1] = start Green value, startColor[2] = start Red value
   endCcolor - (byte array of three values defing the finished RGB color (endColor[0] = end Red value, endColor[1] = end Green value, endColor[2] = end Red value
   fadeSpeed - this is the delay in milliseconds between steps, defines the speed of the fade
*/ 
void fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed){
  int changeRed = endColor[0] - startColor[0];                            //the difference in the two colors for the red channel
  int changeGreen = endColor[1] - startColor[1];                          //the difference in the two colors for the green channel 
  int changeBlue = endColor[2] - startColor[2];                           //the difference in the two colors for the blue channel
  int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue))); //make the number of change steps the maximum channel change
  
}
}

I know there are probably a bunch of issues. Thank you all so much for the help. I am very grateful.

It is customary to say what it does.
However looking at the code I suspect that it keeps changing when the button is held down.
You need to look for a state change, that is remember the past state of the button and only increment or do anything actually when it changes from pushed to un pushed.
This is called a state change and there is an example of this in the Arduino IDE.

Thanks for pointing me in the right direction Grumpy_Mike.

I have three cases that I want to switch through with a button.

Simple I know, but I have researched it and worked on it for the past few hours.

It goes through all the cases without waiting for the button input.

This is as far as I have gotten....

int ledAnalogOne[] = {9, 10, 11}; 
int buttonPin = 2;
int val = 0;
int sequence = 1;

const byte RED[] = {255, 0, 0}; 
const byte ORANGE[] = {83, 4, 0}; 
const byte YELLOW[] = {255, 255, 0}; 
const byte GREEN[] = {0, 255, 0}; 
const byte BLUE[] = {0, 0, 255}; 
const byte INDIGO[] = {4, 0, 19}; 
const byte VIOLET[] = {23, 0, 22}; 
const byte CYAN[] = {0, 255, 255}; 
const byte MAGENTA[] = {255, 0, 255}; 
const byte WHITE[] = {255, 255, 255}; 
const byte BLACK[] = {0, 0, 0}; 
const byte PINK[] = {158, 4, 79}; 



void setup(){
  
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   
  }
      pinMode(buttonPin, INPUT);
}


void loop(){
  

 val = digitalRead(buttonPin);
 if(val == HIGH) 
   {
    if(sequence == 3) 
     {
       sequence = 1;
         } else
           {
             sequence++; 
               }
   }

                             
  switch(sequence)
    {
       case 1:
       setColor(ledAnalogOne, CYAN);
       break;
       
       case 2:
       setColor(ledAnalogOne, BLUE);  
       break;
       
       case 3:
       setColor(ledAnalogOne, RED);
       break;
      }
 }



void setColor(int* led, byte* color){
 for(int i = 0; i < 3; i++){             //iterate through each of the three pins (red green blue)
   analogWrite(led[i], 255 - color[i]);  //set the analog output value of each pin to the input value (ie led[0] (red pin) to 255- color[0] (red input color)
                                         //we use 255 - the value because our RGB LED is common anode, this means a color is full on when we output analogWrite(pin, 0)
                                         //and off when we output analogWrite(pin, 255). 
 }
}
  
  

/* A version of setColor that takes a predefined color (neccesary to allow const int pre-defined colors */
void setColor(int* led, const byte* color){
 byte tempByte[] = {color[0], color[1], color[2]};
 setColor(led, tempByte);
}

/* Fades the LED from a start color to an end color at fadeSpeed
   led - (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
   startCcolor - (byte array of three values defing the start RGB color (startColor[0] = start Red value, startColor[1] = start Green value, startColor[2] = start Red value
   endCcolor - (byte array of three values defing the finished RGB color (endColor[0] = end Red value, endColor[1] = end Green value, endColor[2] = end Red value
   fadeSpeed - this is the delay in milliseconds between steps, defines the speed of the fade
*/ 
void fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed){
  int changeRed = endColor[0] - startColor[0];                            //the difference in the two colors for the red channel
  int changeGreen = endColor[1] - startColor[1];                          //the difference in the two colors for the green channel 
  int changeBlue = endColor[2] - startColor[2];                           //the difference in the two colors for the blue channel
  int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue))); //make the number of change steps the maximum channel change
  
  for(int i = 0 ; i < steps; i++){                                        //iterate for the channel with the maximum change
   byte newRed = startColor[0] + (i * changeRed / steps);                 //the newRed intensity dependant on the start intensity and the change determined above
   byte newGreen = startColor[1] + (i * changeGreen / steps);             //the newGreen intensity
   byte newBlue = startColor[2] + (i * changeBlue / steps);               //the newBlue intensity
   byte newColor[] = {newRed, newGreen, newBlue};                         //Define an RGB color array for the new color
   setColor(led, newColor);                                               //Set the LED to the calculated value
   delay(fadeSpeed);                                                      //Delay fadeSpeed milliseconds before going on to the next color
  }
  setColor(led, endColor);                                                //The LED should be at the endColor but set to endColor to avoid rounding errors
}

/* A version of fadeToColor that takes predefined colors (neccesary to allow const int pre-defined colors */
void fadeToColor(int* led, const byte* startColor, const byte* endColor, int fadeSpeed){
  byte tempByte1[] = {startColor[0], startColor[1], startColor[2]};
   byte tempByte2[] = {endColor[0], endColor[1], endColor[2]};
   fadeToColor(led, tempByte1, tempByte2, fadeSpeed);
}

Thanks for your help!

Yes it will. You will go through the loop hundreds of times a sceconds. When the button is pressed you only want to go through it once. So the if statemant must check if the button is pressed and if last time round the loop it was not. Therefore you have to use a variable to see what it was last time round the loop.
If you look at the state change example I directed you to you will see that.

Worked on it for a few more hours :slight_smile: and I got to work tomorrow :slight_smile:

Made a little head way.

There is a problem with my else statement, I do not know what to put there.

This is as far as I got.

int ledAnalogOne[] = {9, 10, 11}; 
int buttonPin = 2;
int buttonPushCounter =0;
int buttonState = 0;
int lastButtonState = 0;

const byte RED[] = {255, 0, 0}; 
const byte ORANGE[] = {83, 4, 0}; 
const byte YELLOW[] = {255, 255, 0}; 
const byte GREEN[] = {0, 255, 0}; 
const byte BLUE[] = {0, 0, 255}; 
const byte INDIGO[] = {4, 0, 19}; 
const byte VIOLET[] = {23, 0, 22}; 
const byte CYAN[] = {0, 255, 255}; 
const byte MAGENTA[] = {255, 0, 255}; 
const byte WHITE[] = {255, 255, 255}; 
const byte BLACK[] = {0, 0, 0}; 
const byte PINK[] = {158, 4, 79}; 



void setup(){
  
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   
  }
      pinMode(buttonPin, INPUT);
}


void loop(){
  

 buttonState = digitalRead(buttonPin);
 if (buttonState != lastButtonState){
   if (buttonState ==HIGH) {
     buttonPushCounter++;
   }
   else {
     buttonPushCounter++;
   }
lastButtonState = buttonState;
                             
  switch (buttonPushCounter)
    {
       case 0:
       setColor(ledAnalogOne, CYAN);
       buttonPushCounter++;
       break;
       
       case 1:
       setColor(ledAnalogOne, BLUE); 
       buttonPushCounter++; 
       break;
       
       case 2:
       setColor(ledAnalogOne, RED);
       buttonPushCounter= 0;
       break;
      }
 }
}


void setColor(int* led, byte* color){
 for(int i = 0; i < 3; i++){             //iterate through each of the three pins (red green blue)
   analogWrite(led[i], 255 - color[i]);  //set the analog output value of each pin to the input value (ie led[0] (red pin) to 255- color[0] (red input color)
                                         //we use 255 - the value because our RGB LED is common anode, this means a color is full on when we output analogWrite(pin, 0)
                                         //and off when we output analogWrite(pin, 255). 
 }
}
  
  

/* A version of setColor that takes a predefined color (neccesary to allow const int pre-defined colors */
void setColor(int* led, const byte* color){
 byte tempByte[] = {color[0], color[1], color[2]};
 setColor(led, tempByte);
}

/* Fades the LED from a start color to an end color at fadeSpeed
   led - (int array of three values defining the LEDs pins (led[0] = redPin, led[1] = greenPin, led[2] = bluePin))
   startCcolor - (byte array of three values defing the start RGB color (startColor[0] = start Red value, startColor[1] = start Green value, startColor[2] = start Red value
   endCcolor - (byte array of three values defing the finished RGB color (endColor[0] = end Red value, endColor[1] = end Green value, endColor[2] = end Red value
   fadeSpeed - this is the delay in milliseconds between steps, defines the speed of the fade
*/ 
void fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed){
  int changeRed = endColor[0] - startColor[0];                            //the difference in the two colors for the red channel
  int changeGreen = endColor[1] - startColor[1];                          //the difference in the two colors for the green channel 
  int changeBlue = endColor[2] - startColor[2];                           //the difference in the two colors for the blue channel
  int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue))); //make the number of change steps the maximum channel change
  
  for(int i = 0 ; i < steps; i++){                                        //iterate for the channel with the maximum change
   byte newRed = startColor[0] + (i * changeRed / steps);                 //the newRed intensity dependant on the start intensity and the change determined above
   byte newGreen = startColor[1] + (i * changeGreen / steps);             //the newGreen intensity
   byte newBlue = startColor[2] + (i * changeBlue / steps);               //the newBlue intensity
   byte newColor[] = {newRed, newGreen, newBlue};                         //Define an RGB color array for the new color
   setColor(led, newColor);                                               //Set the LED to the calculated value
   delay(fadeSpeed);                                                      //Delay fadeSpeed milliseconds before going on to the next color
  }
  setColor(led, endColor);                                                //The LED should be at the endColor but set to endColor to avoid rounding errors
}

/* A version of fadeToColor that takes predefined colors (neccesary to allow const int pre-defined colors */
void fadeToColor(int* led, const byte* startColor, const byte* endColor, int fadeSpeed){
  byte tempByte1[] = {startColor[0], startColor[1], startColor[2]};
   byte tempByte2[] = {endColor[0], endColor[1], endColor[2]};
   fadeToColor(led, tempByte1, tempByte2, fadeSpeed);
}

Thanks for your input Mike!

There is a problem with my else statement, I do not know what to put there.

There is, you don't need one at all.
Are you actually listening to what I say or are you just wasting my time?

Ended up not being able to sleep, kept thinking about it.

Got it figured out though!!!

Thanks for the direction Grump_Mike.

Change a RGB LED with a Button.

Save the trouble for anyone else...

int ledAnalogOne[] = {9, 10, 11}; 
                    
const byte RED[] = {255, 0, 0}; 
const byte ORANGE[] = {83, 4, 0}; 
const byte YELLOW[] = {255, 255, 0}; 
const byte GREEN[] = {0, 255, 0}; 
const byte BLUE[] = {0, 0, 255}; 
const byte INDIGO[] = {4, 0, 19}; 
const byte VIOLET[] = {23, 0, 22}; 
const byte CYAN[] = {0, 255, 255}; 
const byte MAGENTA[] = {255, 0, 255}; 
const byte WHITE[] = {255, 255, 255}; 
const byte PINK[] = {158, 4, 79};
const byte TEST[] = {255, 255, 255 };
const byte BLACK[] = {0, 0, 0};
const int BUTTON=2; 
boolean lastButton = LOW; 
boolean currentButton = LOW; 
int ledMode = 0; 

void setup()
{
  for(int i = 0; i < 3; i++){
   pinMode(ledAnalogOne[i], OUTPUT);   
  }
  
pinMode (BUTTON, INPUT); 
}


boolean debounce(boolean last)
{
boolean current = digitalRead(BUTTON); 
if (last != current) 
{
delay(5); 
current = digitalRead(BUTTON); 
}
return current; 
}

void setMode(int mode)
{

if (mode == 1)
{
setColor(ledAnalogOne, MAGENTA);
}

else if (mode == 2)
{
setColor(ledAnalogOne, BLUE);
}

else if (mode == 3)
{
setColor(ledAnalogOne, RED);
}

else if (mode == 4)
{
setColor(ledAnalogOne, YELLOW);
}

else if (mode == 5)
{
setColor(ledAnalogOne, ORANGE);
}

else if (mode == 6)
{
setColor(ledAnalogOne, WHITE);
}

else if (mode == 7)
{
setColor(ledAnalogOne, PINK);
}

else
{
setColor(ledAnalogOne, GREEN);
}
}
void loop()
{
currentButton = debounce(lastButton); 
if (lastButton == LOW && currentButton == HIGH) 
{
ledMode++; 
}
lastButton = currentButton; 

if (ledMode == 8) ledMode = 0;
setMode(ledMode); 
}
void setColor(int* led, byte* color){
 for(int i = 0; i < 3; i++){             
   analogWrite(led[i], 255 - color[i]);  
                                         
 }
}

void setColor(int* led, const byte* color){
 byte tempByte[] = {color[0], color[1], color[2]};
 setColor(led, tempByte);
}

void fadeToColor(int* led, byte* startColor, byte* endColor, int fadeSpeed){
  int changeRed = endColor[0] - startColor[0];                            
  int changeGreen = endColor[1] - startColor[1];                           
  int changeBlue = endColor[2] - startColor[2];                           
  int steps = max(abs(changeRed),max(abs(changeGreen), abs(changeBlue))); 
  
  for(int i = 0 ; i < steps; i++){                                        
   byte newRed = startColor[0] + (i * changeRed / steps);                 
   byte newGreen = startColor[1] + (i * changeGreen / steps);             
   byte newBlue = startColor[2] + (i * changeBlue / steps);               
   byte newColor[] = {newRed, newGreen, newBlue};                         
   setColor(led, newColor);                                               
   delay(fadeSpeed);                                                      
  }
  setColor(led, endColor);                                                
}


void fadeToColor(int* led, const byte* startColor, const byte* endColor, int fadeSpeed){
  byte tempByte1[] = {startColor[0], startColor[1], startColor[2]};
   byte tempByte2[] = {endColor[0], endColor[1], endColor[2]};
   fadeToColor(led, tempByte1, tempByte2, fadeSpeed);
}