help with specific rgb color, fade and random pick

I’m helping a friend with a project and want to use the arduino to accomplish it. What I want to do is have 7 specific colors displayed from a RGB LED. On the activation of a switch, it would display color 1 for about 2 seconds, fade to color 2 (maybe a 1-2 second fade time), display for 2 seconds, fade to color 3…and so on. At the end of the 7th color, pause for a period of maybe 3 seconds, then choose one of those 7 colors at random and display that color until the switch is released or after maybe a 15 second timeout. Any and all help would be greatly appreciated.

Do you have any underlying code or hardware to share?

I will draw up some code samples ;)

/me

OK, it's 12:45 in England and I'm too tired to work out the fading code.

But I'll get back to it tomorrow!

/me

Unfortunately, no coding....i'm completely new to this. I've uploaded sketches and changed minor things in code, but never wrote my own. Hardware wise, would be really simple. Probably just get a premade Arduino RBBB board or similar, a RGB LED, momentary push switch and that should be pretty much all I need for this project. Thanks for any input ;)

Hope this explains a little bit (my first attempt…be gentle)

int val=0;                             
int inPin=2;                           // switch connected to pin 2
int rpin=3;
int gpin=5;
int bpin=6;

void setup() 
{ 
  pinMode (inPin, INPUT);                // declare pushbutton as input 
} 
 
void loop()
{
  val =digitalRead (inPin);            // read input value
  if (val == HIGH) {                    // check if input is high
    analogWrite (rpin, 0);
    analogWrite (gpin, 0);
    analogWrite (bpin, 0);
  }
    else
    {
       analogWrite(rpin, 255);        // LED color white
       analogWrite(gpin, 255);
       analogWrite(bpin, 255);  
       delay(1000);
   
       analogWrite(rpin, 255);        // LED color purple
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(1000);
   
       analogWrite(rpin, 0);          // LED color blue
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(1000);
       
       analogWrite(rpin, 0);          // LED color green
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(1000);
       
       analogWrite(rpin, 255);        // LED color yellow
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(1000);
       
       analogWrite(rpin, 255);        // LED color orange
       analogWrite(gpin, 153);
       analogWrite(bpin, 0);
       delay(1000);
       
       analogWrite(rpin, 255);        // LED color red
       analogWrite(gpin, 0);
       analogWrite(bpin, 0);
       delay(1000);
    }
}

Not sure how to incorporate the fading from one to the next or to select one of the 7 at random…will keep searching :wink:

Fading example:

for (int x=0; x<256; x++) {
analogWrite(rpin, x);
delay(10);
}

for (int x=255; x>0; x–) {
analogWrite(rpin, x);
delay(10);
}

This isn’t the best way to do the fading if you want to change up the colors, but it gives you an idea of what to do. for now, you could just write a for loop for each color.

Thanks CMiYC, works great! Plus I understood the actual way it was functioning, so made it that much easier to implement :wink:
So, my code is now as follows:

int val=0;                             
int inPin=4;                           // switch connected to pin 4
int rpin=3;
int gpin=5;
int bpin=6;

void setup() 
{ 
  pinMode (inPin, INPUT);                // declare pushbutton as input 
} 
 
void loop()
{
  val =digitalRead (inPin);            // read input value
  if (val == LOW) {                    // check if input is high
       
       analogWrite(rpin, 255);        // LED color white
       analogWrite(gpin, 255);
       analogWrite(bpin, 255);  
       delay(3000);
           for (int x=255; x>0; x--) {
           analogWrite(gpin, x);
           delay(10);
            }
   
       analogWrite(rpin, 255);        // LED color purple
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(3000);
          for (int x=255; x>0; x--) {
          analogWrite(rpin, x);
          delay(10);
          }

       analogWrite(rpin, 0);          // LED color blue
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(3000);
         for (int x=0; x<256; x++) {
         analogWrite(gpin, x);
         delay(10);
          }
         for (int x=255; x>0; x--) {
         analogWrite(bpin, x);
         delay(10);
          }
       
       analogWrite(rpin, 0);          // LED color green
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=0; x<256; x++) {
         analogWrite(rpin, x);
         delay(10);
          }
                
       analogWrite(rpin, 255);        // LED color yellow
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=255; x>153; x--) {
         analogWrite(gpin, x);
         delay(10);
          }

       analogWrite(rpin, 255);        // LED color orange
       analogWrite(gpin, 153);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=153; x>0; x--) {
         analogWrite(gpin, x);
         delay(10);
          }
       
       analogWrite(rpin, 255);        // LED color red
       analogWrite(gpin, 0);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=255; x>0; x--) {
         analogWrite(rpin, x);
         delay(10);
          }
  }
    if (val == LOW)
    {
    analogWrite (rpin, 0);
    analogWrite (gpin, 0);
    analogWrite (bpin, 0); 
      
      
    }
}

So, now all I need to figure out is how to chose one of these 7 colors at random and display it after it’s went through the sequence. I tried to #define each color and assign it a number, but that didn’t work. As this is my first project, it’s definitely teaching me quite a bit :slight_smile:
Thanks for all the help thus far

Nice one! Sorry I was being slow with my code, but a few things to add/change.

You could check for the button press by:

if(digitalRead(inPin) == HIGH){ // You said LOW instead
    code...
}

else {
    analogWrite(rpin, 0);
    analogWrite(gpin, 0);
    analogWrite(bpin, 0);
}

Which condenses it a bit and Is easier than checking twice.

You could write a function for each colour to colour fade and use; randomVal = random(7);

to select which fade function to use.

/me

Thanks, I'll remove the last "if" statement and fix the first one....forgot to change it in the comments.

For the random portion, what I want to do is have the program randomly pick one of the 7 colors I have listed, i.e. white, purple, blue, green, yellow, orange or red and then display that after the red fades out. I tried to #define each color with a number as I thought it would make it able to randomly pick a color if a number was assigned to it, like:

#define white 1
#define blue 2
etc.....

then try and make each color it's own void....

void white() {
.....

but that didn't work at all Any suggestions? Thanks again for the help.

I think this is the kind of thing you need:

char* colours[7] = { // Seven colours, 0-6 "255, 255, 255", // white "255, 0, 255", // purple "0, 0, 255", // blue "255, 255, 0", // green "0, 255, 0", // yellow "255, 153, 0", // orange "255, 0, 0"}; // red

int randomVal;

void setup(){ }

void loop(){ }

void chooseColour() { randomVal = random(0, 6); // Choose a random value, 0-6 switch(randomVal) { case 0: white(); case 1: purple(); case 2: blue(); case 3: green(); case 4: yellow(); case 5: orange(); case 6: red(); } }

void white(){ } void purple(){ } void blue(){ } void green(){ } void yellow(){ } void red(){ } void orange(){ }

Edit -

byte colours[7][3] = { // Seven colours, 0-6 255, 255, 255, // white 255, 0, 255, // purple 0, 0, 255, // blue 255, 255, 0, // green 0, 255, 0, // yellow 255, 153, 0, // orange 255, 0, 0}; // red

int randomVal;

void setup(){ }

void loop(){ }

void chooseColour() { int randomVal = random(0, 6); // Choose a random value, 0-6 byte redComponent = colours[randomVal][0]; byte greenComponent = colours[randomVal][1]; byte blueComponent = colours[randomVal][2]; analogWrite(redPin, redComponent); analogWrite(greenPin, greenComponent); analogWrite(bluePin, blueComponent); }

It has an array of the Colour values. It then chooses a random value using the random() function. Then it uses a switch:case function to choose which colour function to go to with the selected case.

I think the reason you had difficulty with the #define statements was because you tried to use them the wrong way round. They just let the compiler replace the words e.g WHITE that you use in the code with the value attached to that statement.

Try adding this to your code (with all the additional stuff of course) and it should do what what you want.

The edited code courtesy of halley!

PS. This has been a learning curve for me too.

/me

PA Skins, how were you hoping to convert the string (char*) into actual analogWrite-able values for red, green and blue components? Use the actual bytes, it’s smaller anyway.

byte colours[7][3] = {
  // Seven colours 0-6, and
  // each has three components 0-2 for red, green, blue
  255, 255, 255,  // white
  255, 0, 255,  // purple
  0, 0, 255,  // blue
  255, 255, 0,  // green
  0, 255, 0,  // yellow
  255, 153, 0,  // orange
  255, 0, 0,  // red
};

void setup(){
}

void loop(){
}

void chooseColour() {
 int randomVal = random(0, 6);  // Choose a random value, 0-6
 byte redComponent = colours[randomVal][0];
 byte greenComponent = colours[randomVal][1];
 byte blueComponent = colours[randomVal][2];
 analogWrite(redPin, redComponent);
 analogWrite(greenPin, greenComponent);
 analogWrite(bluePin, blueComponent);
 }
}

Ahh...I knew that I'd make a mistake somewhere.

That's what I get for cooking it up without thinking. Anyway thanks halley for that!

/me

Thanks to both of you ;) Halley, do I insert your code after my red color fades out? Sorry for so many ?'s.

Thanks a million guys, seems to be working great now. Here’s what I have:

byte colours[7][3] = {
  // Seven colours 0-6, and
  // each has three components 0-2 for red, green, blue
  255, 255, 255,  // white
  255, 0, 255,  // purple
  0, 0, 255,  // blue
  0, 255, 0,  // green
  255, 255, 0,  // yellow
  255, 153, 0,  // orange
  255, 0, 0,  // red
};

int val=0;                             
int inPin=4;                           // switch connected to pin 4
int rpin=3;
int gpin=5;
int bpin=6;

void setup() { 
pinMode (inPin, INPUT);  
} 
 
void loop()
{
  val=digitalRead(inPin);
  if (val==LOW)
  
  {
       analogWrite(rpin, 255);        // LED color white
       analogWrite(gpin, 255);
       analogWrite(bpin, 255);  
       delay(3000);
           for (int x=255; x>0; x--) {
           analogWrite(gpin, x);
           delay(10);
            }
   
       analogWrite(rpin, 255);        // LED color purple
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(3000);
          for (int x=255; x>0; x--) {
          analogWrite(rpin, x);
          delay(10);
          }

       analogWrite(rpin, 0);          // LED color blue
       analogWrite(gpin, 0);
       analogWrite(bpin, 255);
       delay(3000);
         for (int x=0; x<256; x++) {
         analogWrite(gpin, x);
         delay(10);
          }
         for (int x=255; x>0; x--) {
         analogWrite(bpin, x);
         delay(10);
          }
       
       analogWrite(rpin, 0);          // LED color green
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=0; x<256; x++) {
         analogWrite(rpin, x);
         delay(10);
          }
                
       analogWrite(rpin, 255);        // LED color yellow
       analogWrite(gpin, 255);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=255; x>153; x--) {
         analogWrite(gpin, x);
         delay(10);
          }

       analogWrite(rpin, 255);        // LED color orange
       analogWrite(gpin, 153);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=153; x>0; x--) {
         analogWrite(gpin, x);
         delay(10);
          }
       
       analogWrite(rpin, 255);        // LED color red
       analogWrite(gpin, 0);
       analogWrite(bpin, 0);
       delay(3000);
         for (int x=255; x>0; x--) {
         analogWrite(rpin, x);
         delay(10);
          }
          
       analogWrite(rpin, 0);        // All off
       analogWrite(gpin, 0);
       analogWrite(bpin, 0);
    
 int randomVal = random(0, 6);  // Choose a random value, 0-6
 byte redComponent = colours[randomVal][0];
 byte greenComponent = colours[randomVal][1];
 byte blueComponent = colours[randomVal][2];
 analogWrite(rpin, redComponent);
 analogWrite(gpin, greenComponent);
 analogWrite(bpin, blueComponent);
     delay(5000);
  }
  }

OK, might have spoke too soon. Seems the random color selector selects the same pattern of "randomness" once the board has been reset. I ran it through 5 times, and the "random" gave me purple, purple, orange, blue, then yellow. Reset the board, ran it five times and got the same "random" colors, in the same order.

Have a look at how random() is used. http://arduino.cc/en/Reference/RandomSeed

You can use a 'seed' to make the numbers more random. There is also a discussion here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235421386

Thanks PA Skins....that fixed it.

No problems; all I ask in return are some nice pictures or even a video of the code and hardware in working order!

Good luck :)

/me

Seems the random color selector selects the same pattern of "randomness" once the board has been reset.

Good observation!

Read this: randomSeed :)

[edit]I do not understand why this was not posted until now. Guess there must've been some problems with my connection or something. :-[[/edit]

After studying your code, I noticed that that the fading code could've been implemented using a function. So, I went ahed and made a function that recieved r g b values, and then it predicted the target rgb values from the values recieved. Then, I though that it would've been better to implement the function so that one could fade from any color, to any color. And when I got so far, I started to get tired of all the array indexing, and the long list of parameters to the functions. So I made a struct containing rgb data.

Now I could pass two arguments instead of six. And I would say that is is more intuitive to just say yellow.g than it is to say colours[4][1]. :)

I have no arduino nearby so I have had no possibility to test the code, but I will be so bold to say that logically I do not see why it should not function.

Because of it's length, the code will be posted in my next post.

Because of it’s length, the code will be posted in my next post.

/*
|| RGB fading example
|| Demonstrating the use of structs, functions, arrays, pointers, random number generation and millis timing.
||
|| Contributed:
|| Alexander Brevig
*/

//setup code
//using #define
#define DEBUG true //false if serial debugging is to be turned off
#define PULLUP false //true if pullup resistors are used : using pullup resistors
#define SWITCH_PRESSED (!PULLUP)

#define FADE_TIME 1000 //"(maybe a 1-2 second fade time)"
#define FADE_STEPS 255
#define FADE_DELAY (FADE_TIME/FADE_STEPS)

#define SWITCH_TIMEOUT 15000 //“display that color until the switch is released or after maybe a 15 second timeout”
#define COLOR_DISPLAY_TIME 2000 //“display for 2 seconds”
#define NUMBER_OF_COLORS 7
//using const
#define constant const

//wikipedia on struct
typedef struct SRGB{
byte r;
byte g;
byte b;
void operator= (const SRGB &arg){ r = arg.r; g = arg.g; b = arg.b; } //myColor = red; should be valid
} RGB;

//variables
constant RGB white = { 255 , 255 , 255 };
constant RGB purple = { 255, 0, 255 };
constant RGB blue = { 0, 0, 255 };
constant RGB green = { 0, 255, 0 };
constant RGB yellow = { 255, 255, 0 };
constant RGB orange = { 255, 153, 0 };
constant RGB red = { 255, 0, 0 };
constant RGB off = { 0, 0, 0 };

//provide an array for the randomization
//using pointers (those & and * symbols)
//using arrays
constant RGB* colorArray[NUMBER_OF_COLORS] = { &white , &purple, &blue, &green, &yellow, &orange, &red };

//provide a variable that holds the current RGB values
RGB currentColor = { 0 , 0 , 0 };

//pin declarations
constant RGB pin = { 3 , 5 , 6 };

byte inPin=2; // switch connected to pin 2

//function declarations
void fadeBetweenColors( constant RGB& fadeFrom, constant RGB& fadeTo );
void fadeColorChannel( byte& source, int fadeStep, byte from, byte to);
void displayCurrentColor();
void displayCurrentColorAndDelay(int del);
void displayColor( constant RGB& color );

void setup() {
pinMode (inPin, INPUT); // declare pushbutton as input
if (PULLUP){ digitalWrite(inPin,HIGH); }

pinMode (pin.r, OUTPUT); // declare pushbutton as input
pinMode (pin.g, OUTPUT); // declare pushbutton as input
pinMode (pin.b, OUTPUT); // declare pushbutton as input

randomSeed(analogRead(0));//using randomSeed(seed)

if (DEBUG) { Serial.begin(9600); }
}

void loop()
{
if (digitalRead(inPin) != SWITCH_PRESSED) { // check if input is high
displayColor( off );
} else {
if (DEBUG) { Serial.println(“SWITCH_PRESSED: starting fade sequence”); }

fadeBetweenColors( off , white );
fadeBetweenColors( white , purple );
fadeBetweenColors( purple , blue );
fadeBetweenColors( blue , green );
fadeBetweenColors( green , yellow );
fadeBetweenColors( yellow , orange );
fadeBetweenColors( orange , red );

delay(3000); //“At the end of the 7th color, pause for a period of maybe 3 seconds”

byte randomVal = random(0, 6); // Choose a random value, 0-6 : using random(min,max)
displayColor( *colorArray[randomVal] );
unsigned long preLoopTime = millis(); //using millis()
do {
//wait
} while ( (digitalRead(inPin)==SWITCH_PRESSED) && (millis()-SWITCH_TIMEOUT<preLoopTime) );
}
}

//fade the currentColor from a color to a color.
void fadeBetweenColors( constant RGB& fadeFrom, constant RGB& fadeTo ){
if (DEBUG) {
Serial.print(“Fading between “);
Serial.print(fadeFrom.r);
Serial.print(”,”);
Serial.print(fadeFrom.g);
Serial.print(",");
Serial.print(fadeFrom.b);
Serial.print(" and “);
Serial.print(fadeTo.r);
Serial.print(”,");
Serial.print(fadeTo.g);
Serial.print(",");
Serial.print(fadeTo.b);
}
for (int i=0; i<FADE_STEPS; i++){
fadeColorChannel(currentColor.r, i, fadeFrom.r, fadeTo.r);
fadeColorChannel(currentColor.g, i, fadeFrom.g, fadeTo.g);
fadeColorChannel(currentColor.b, i, fadeFrom.b, fadeTo.b);
displayCurrentColor();
delay(FADE_DELAY);
}
displayCurrentColorAndDelay(COLOR_DISPLAY_TIME);
}

//fade a specific color channel of the currentColor RGB to the target value
void fadeColorChannel( byte& source, int fadeStep, byte from, byte to){
//is modification needed?
if (from != to ){
if (from < to) {
//we need to increase
if ( fadeStep % ((to-from)/FADE_STEPS) == 0 ){ source++; }
} else {
//we need to decrease
if ( fadeStep % ((from-to)/FADE_STEPS) == 0 ){ source–; }
}
}
}

//display currentColor
void displayCurrentColor(){
if (DEBUG) { Serial.print(“currentColor: “); Serial.print(currentColor.r); Serial.print(”,”);Serial.print(currentColor.g); Serial.print(",");Serial.println(currentColor.b); delay(200);/remove delay/}
analogWrite(pin.r, currentColor.r);
analogWrite(pin.g, currentColor.g);
analogWrite(pin.b, currentColor.b);
}

//display currentColorAndDelay
void displayCurrentColorAndDelay(int del){
displayColor(currentColor);
delay(del);
}

//display any constant color
void displayColor( constant RGB& color ){
analogWrite(pin.r, color.r);
analogWrite(pin.g, color.g);
analogWrite(pin.b, color.b);
}

/me suddenly realized that the time is 0425, and should probably sleep. ::slight_smile: