Help on random led coloring?

I am new to arduino and was wondering how to make an led flash one random color for a project I am doing. I have looked at the page on the arduino site and other ones too but when I set it to show one color, at random and stay on that color, it always shows the same color, no matter what, making it not very random. Please help! [smiley=cheesy.gif]

A single LED will only ever emit one color of light (within a very small window of variation.) If you want multiple colors, you need a so-called multicolor LED, which are really just multiple LEDs in the same package - you basically need to power (and/or control) each LED separately.

These multicolor LEDs are available in lots of two- and three-color combinations, i.e. red/green, and red/green/blue. With any multi-color LED, you can get a whole range of colors between the various endpoints by fading each color appropriately. For instance, if you have a red/blue LED, you can get purple light by powering both equally - or, purplish-red light by powering the red at full power, and the blue at a smaller current (or PWM duty cycle).

So, to give you the short answer, if you want lots of colors, go get an RGB LED, and feed each color with it's own PWM signal, from one of the PWM pins on your arduino. Then, apply the logic you've already seen in the examples you talked about (i.e. fading) to blend the colors. Here is an example of such an LED:

Note that it has a single cathode, and an anode for each color.

Sorry, I guess I should have mentioned that I am dealing with an rgb led. I want it to show one random color but that one random color is always the same.

well for a big mix of random colors you could create a random value generator for the pwm of each rgb pin. http://arduino.cc/en/Reference/RandomSeed

yes, but I want it to show just one random color and stop.

Can you post your code so we can see how you are using randomSeed()? It is the key to what you want to do. Don't forget to use the code button [#] when you post code.

I'm using this code:
#define PIN_RED 9
#define PIN_GREEN 10
#define PIN_BLUE 11
void color(byte v)
{
digitalWrite(PIN_RED, v & 0x01);
digitalWrite(PIN_GREEN, (v >> 1) & 0x01);
digitalWrite(PIN_BLUE, (v >> 2) & 0x01);
}
void setup()
{
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE, OUTPUT);
randomSeed(analogRead(0));
}
void loop()
{
color(random(100));
}

I got it off a website and changed it a little so it doesn't change colors all the time but no matter what, my led just shows white and it sort of blinks rapidly so all you see is this white light that is flashing extremely fast

void loop()
{
 color(random(100));
}

What happens if you move the "color(random(100));" into "setup()", and leave "loop();" empty?

That'll stop the flashing.

The white light is probably your eye "averaging" the rapidly-changing colours caused by "loop ()", well, looping and picking a new colour every time.

BTW "random (8);" should work just as well.

that worked, but how do I get it to be a tatally random color not one of eight?

Then you need a random number in the range 0.. 224-1, and use PWM pins for the LEDs and "analogWrite". (actually, you'd probably get away with a number in the range 0..215-1, but you'd still need "analogWrite", scaled appropriately)

Sorry, I'm still quite new to arduino and I don't really get what you're saying. Could you please show mw an example?

If you use a single binary bit to light an LED, the best you can manage is eight distinct states.
LEDs are either ON or OFF (HIGH or LOW).
The Arduino has pins which are PWM-capable (for the Duemilanova these are 3, 5 ,6, 9, 10 and 11, accesible via "analogWrite").
A PWM signal gives a fixed-frequency, variable mark:space ratio which approximates an analogue signal; the higher the mark (HIGH) time, the brighter a connected LED will appear.
So, if you have a LED connected to, say, pin 3, "analogWrite (3, 128);" will give a roughly 50:50 on/off signal, so the LED will appear less bright than if you'd executed "analogWrite (3, 255);"
(the relationship is not linear, but that's complicating things)

So, for your example: (uncompiled, untested)

const byte PIN_RED     = 3;
const byte PIN_GREEN = 5;
const byte PIN_BLUE    = 6;

void color(unsigned long v)
{
 analogWrite(PIN_RED,    v  & 255); 
 analogWrite(PIN_GREEN, (v >> 8) & 255);
 analogWrite(PIN_BLUE,  (v >> 16) & 255); 
}
void setup()
{
 pinMode(PIN_RED,   OUTPUT);   
 pinMode(PIN_GREEN, OUTPUT);   
 pinMode(PIN_BLUE,  OUTPUT); 
 randomSeed(analogRead(0));
 color((unsigned long)random(0x01000000));
}
void loop()
{
}

Thanks, the code worked, and I understand it now. :slight_smile: Now do you think at any one color it will know the value of the blue, red, and green pins so I can do something else with it?

Not quite sure what you want to do, but there are several things you could do:

void color(unsigned long v)
{
 byte red = v & 255;
 byte green = (v >> 8) & 255;
 byte blue = (v >> 16) & 255; 
 analogWrite(PIN_RED,    red);
 analogWrite(PIN_GREEN, green);
 analogWrite(PIN_BLUE,  blue);
 // red green blue values are available for other uses
}

or you could declare "red" "green" "blue" with global scope, or call "random (256);" three times, and pass separate values to your LED lighting function.
Lots of different ways.

Ok, I did that, and then I did this code to test it:

const byte PIN_RED     = 9;
const byte PIN_GREEN = 10;
const byte PIN_BLUE    = 11;

void color(unsigned long v)
{
 byte red = v & 255;
 byte green = (v >> 8) & 255;
 byte blue = (v >> 16) & 255;
 analogWrite(PIN_RED,    red);
 analogWrite(PIN_GREEN, green);
 analogWrite(PIN_BLUE,  blue);
 // red green blue values are available for other uses
} 


void setup()
{
Serial.begin(9600);
 pinMode(PIN_RED,   OUTPUT);  
 pinMode(PIN_GREEN, OUTPUT);  
 pinMode(PIN_BLUE,  OUTPUT);
 randomSeed(analogRead(0));
 color((unsigned long)random(0x01000000));
}
void loop()
{
  if(PIN_RED > 100);{
    Serial.print("redled on ");
  }
    
    if(PIN_RED < 100);{
     Serial.print("redled off ");
    }
      delay(3000);
}

Unfortunately, the serial monitor just says "led on led off" every 3 seconds. Why does it do that?

Remove the color call from setup and add as the first line of loop()

const byte PIN_RED     = 9;
const byte PIN_GREEN = 10;
const byte PIN_BLUE    = 11;

void color(unsigned long v)
{
 byte red = v & 255;
 byte green = (v >> 8) & 255;
 byte blue = (v >> 16) & 255;
 analogWrite(PIN_RED,    red);
 analogWrite(PIN_GREEN, green);
 analogWrite(PIN_BLUE,  blue);
 // red green blue values are available for other uses
}


void setup()
{
Serial.begin(9600);
 pinMode(PIN_RED,   OUTPUT);  
 pinMode(PIN_GREEN, OUTPUT);  
 pinMode(PIN_BLUE,  OUTPUT);
 randomSeed(analogRead(0));

}
void loop()
{
   color((unsigned long)random(0x01000000));
  if(PIN_RED > 100);{
    Serial.print("redled on ");
  }
    
    if(PIN_RED < 100);{
     Serial.print("redled off ");
    }
      delay(3000);
}

void loop()
{
if(PIN_RED > 100);{
Serial.print("redled on ");
}

if(PIN_RED < 100);{
Serial.print("redled off ");
}
delay(3000);
}

Unfortunately, the serial monitor just says "led on led off" every 3 seconds. Why does it do that?

There is no way your code as posted will say "led on led off".
It may say, "redled on redled off", but even this is unlikely because the value of PIN_RED is a constant 9.

  if(PIN_RED > 100)[glow];[/glow]{
 ...
    if(PIN_RED < 100)[glow];[/glow]{

Oops - well-spotted!

What I have found is that using the HSV spectrum really helps when you want to pull random colors. What you will notice from a function that gets any random color out of 16 million is that you end up with white-out colors and the result may be less than what you really want.

Also, you most likely want to control more than one LED and will want more control than just setting a random color. To that end I am working on an LED class and I have put together some randomizing functions. You can set a random color (out of the 16 M) or you can set a random hue from 0 to 255. While the normal hue spectrum is 0 to 360, I convert this to a 0 to 255 spectrum to allow the storage of a full color in one byte (not three) .. when all I care about is the color.

This allows you to control your Saturation and Brightness (Value) and when your color (Hue) changes .. it keeps the same basic brightness / look. Then when you want to keep the same color but just make it more or less bright - you can adjust the Hue and Saturation and the basic color will stay the same.

This is a full demo you can copy / paste into a new project.

Hope this helps.

//- Joseph Francis - Open Source - As Is, etc.

#ifndef RGBCommonLED_H
#define RGBCommonLED_H

#include "WProgram.h"


class RGBCommonLED { 
public:
  RGBCommonLED(int rpin, int gpin, int bpin);
  ~RGBCommonLED();

  //--- methods
  void setRGB(byte r, byte g, byte b);
  void setHSV(byte h, byte s, byte v);
  void setColor(unsigned long v);
  void setHue(byte level);
  void setSat(byte level);
  void setVal(byte level);

  void adjHue(int level);
  void adjSat(int level);
  void adjVal(int level);

  void setRandomColor();
  void setRandomHue();
  void setRandomSat();
  void setRandomVal();

  //--- easy for the chip / code
  void setHSVLevel(int section, byte level);
  void adjHSVLevel(int section, int level);
  void setRandomHSVLevel(int section);
  
  //--- Used to update the led pins (or related vars that update on scan)
  void updateLED();

  //--- Conversion routine that loads the "o"s with a value from 0 to 255 for RGVB
  void HSVToRGB( unsigned int inHue, unsigned int inSaturation, unsigned int inValue,
    unsigned int *oR, unsigned int *oG, unsigned int *oB );

  //--- Conversion routine that loads the "o"s with a value from 0 to 255 for S and V
  //    and load oH with a value from 0 to 360 .. use map(returnval,0,360,0,255) to convert
  void RGBToHSV( unsigned int inRed, unsigned int inGreen, unsigned int inBlue,
    unsigned int *oH, unsigned int *oS, unsigned int *oV );

  //--- When needed - this will update the HSV value by converting from the RGB value
  //   currently set
  void updateHSVFromRGB();

  //--- pins for this led, in order R G B
  int pins[3];
  //--- colors for this led, in order R G B
  int rgb[3];
  //--- colors in HSV format, in order H S V
  int hsv[3];

private:
  //--- used to keep from converting when we dont have to (already did - no change);
  boolean hsvSet;
  void setRGBFromHSV();
  void setHSVFromRGB();
};

#endif


//<<constructor>> 
RGBCommonLED::RGBCommonLED(int rpin, int gpin, int bpin){
  pins[0] = rpin;
  pins[1] = gpin;
  pins[2] = bpin;
  hsvSet = false;
}

//<<destructor>>
RGBCommonLED::~RGBCommonLED(){/*nothing to destruct*/
}

void RGBCommonLED::setColor(unsigned long v)
{
  this->setRGB((v & 255),((v >> 8) & 255),(v >> 16) & 255);
}


void RGBCommonLED::setRGB(byte r, byte g, byte b){
  rgb[0] = r;
  rgb[1] = g;
  rgb[2] = b;
  hsvSet = false;
}

void RGBCommonLED::setHSV(byte h, byte s, byte v){
  hsv[0] = h;
  hsv[1] = s;
  hsv[2] = v;
  this->setRGBFromHSV();
  hsvSet = true;
}


void RGBCommonLED::setHSVLevel(int section, byte level){
  updateHSVFromRGB();
  hsv[section] = level;
  this->setRGBFromHSV();
}

void RGBCommonLED::setHue(byte level){
  this->setHSVLevel(0,level);
}

void RGBCommonLED::setSat(byte level){
  this->setHSVLevel(1,level);
}

void RGBCommonLED::setVal(byte level){
  this->setHSVLevel(2,level);
}

void RGBCommonLED::adjHSVLevel(int section, int level){
  updateHSVFromRGB();
  int th = hsv[section] + level;

  if( th < 0 ){
    th = 255 + th;    
  } 
  else if( th > 255 ) {
    th = 255 - th;    
  }

  th = constrain(th,0,255); //just in case?
  hsv[section] = th;
  this->setRGBFromHSV();
}

void RGBCommonLED::adjHue(int level){
  this->adjHSVLevel(0,level);
}

void RGBCommonLED::adjSat(int level){
  this->adjHSVLevel(1,level);
}

void RGBCommonLED::adjVal(int level){
  this->adjHSVLevel(2,level);
}



void RGBCommonLED::RGBToHSV( unsigned int inRed, unsigned int inGreen, unsigned int inBlue,
unsigned int *oH, unsigned int *oS, unsigned int *oV )
{
  //struct Color_HSV HSV; //structure to return
  double vals[3]; //thue = temporary var (linked to hue)
  unsigned char maxc=0, minc=0; //red=0, green=1, blue=2
  double hue, sat, val;

  vals[0]=inRed;
  vals[1]=inGreen;
  vals[2]=inBlue;
  //red is set as maximum and minimum
  if(vals[1]>vals[maxc]) maxc=1; //if green is greater, make green the max.
  if(vals[2]>vals[maxc]) maxc=2; //if blue is greater, make blue the max
  if(vals[1]<vals[minc]) minc=1; //if green is less, make green the min.
  if(vals[2]<vals[minc]) minc=2; //if blue is less, make blue the min.
  val = vals[maxc]; //set the HSV.val to the maximum component value (this is a final value)
  if(vals[maxc]==0) //if maximum component is 0, color must be black
    sat = hue = 0; //so set values to 0 manually to avoid div by 0 errors
  else
  { //otherwise, calculate the values
    sat=255*(1-(vals[minc]/vals[maxc])); //compressed equation - original: HSV.sat=((vals[maxc]-vals[minc])/vals[maxc])*255;
    hue = 60 * ((maxc*2) + (vals[(maxc+1)%3] - vals[(maxc+2)%3])/(vals[maxc] - vals[minc])); //this cannot be simplified - and i havn't got time to explain it
  }
  if(hue < 0) hue += 360; //corrector for hues in -60 to 0 range
  *oH = hue; //map(hue,0,360,0,255);
  *oS = sat;
  *oV = val;
}

void RGBCommonLED::HSVToRGB( unsigned int inHue, unsigned int inSaturation, unsigned int inValue,
unsigned int *oR, unsigned int *oG, unsigned int *oB )
{
  if( inSaturation == 0 )
  {
    // achromatic (grey)
    *oR = *oG = *oB = inValue;
  }
  else
  {
    unsigned int scaledHue = (inHue * 6);
    unsigned int sector = scaledHue >> 8; // sector 0 to 5 around the color wheel
    unsigned int offsetInSector = scaledHue - (sector << 8);      // position within the sector
    unsigned int p = (inValue * ( 255 - inSaturation )) >> 8;
    unsigned int q = (inValue * ( 255 - ((inSaturation * offsetInSector) >> 8) )) >> 8;
    unsigned int t = (inValue * ( 255 - ((inSaturation * ( 255 - offsetInSector )) >> 8) )) >> 8;

    switch( sector ) {
    case 0:
      *oR = inValue;
      *oG = t;
      *oB = p;
      break;
    case 1:
      *oR = q;
      *oG = inValue;
      *oB = p;
      break;
    case 2:
      *oR = p;
      *oG = inValue;
      *oB = t;
      break;
    case 3:
      *oR = p;
      *oG = q;
      *oB = inValue;
      break;
    case 4:
      *oR = t;
      *oG = p;
      *oB = inValue;
      break;
    default:            // case 5:
      *oR = inValue;
      *oG = p;
      *oB = q;
      break;
    }
  }
} 

void RGBCommonLED::setRandomColor(){
  this->setColor((unsigned long)random(0x01000000));
}

void RGBCommonLED::setRandomHue(){
  this->setRandomHSVLevel(0);
}
void RGBCommonLED::setRandomSat(){
  this->setRandomHSVLevel(1);
}
void RGBCommonLED::setRandomVal(){
  this->setRandomHSVLevel(2);
}

void RGBCommonLED::setRandomHSVLevel(int section){
  this->setHSVLevel(section, (unsigned int)random(0x0100));
}


void RGBCommonLED::updateHSVFromRGB(){
  //   if (hsvSet)
  //     return;
  this->setHSVFromRGB();   
  hsvSet = true;
}


void RGBCommonLED::updateLED(){
  analogWrite(this->pins[0], rgb[0]);
  analogWrite(this->pins[1], rgb[1]);
  analogWrite(this->pins[2], rgb[2]);
}


void RGBCommonLED::setRGBFromHSV(){
  unsigned int h = hsv[0];
  unsigned int s = hsv[1];
  unsigned int v = hsv[2];
  unsigned int r = 0;
  unsigned int g = 0;
  unsigned int b = 0;
  HSVToRGB(h,s,v,&r,&g,&b);
  this->setRGB(r,g,b);
}

void RGBCommonLED::setHSVFromRGB(){
  unsigned int r = rgb[0];
  unsigned int g = rgb[1];
  unsigned int b = rgb[2];
  unsigned int h;
  unsigned int s;
  unsigned int v;

  this->RGBToHSV(r,g,b,&h,&s,&v);
  hsv[0] = map(h,0,360,0,255);
  hsv[1] = s;
  hsv[2] = v;
  hsvSet = true;
}

RGBCommonLED led1(10,11,9);

void setup()
{
  Serial.begin(9600);
  randomSeed(analogRead(0));
  testRGB();
}

void testRGB(){
  led1.setRGB(255,0,0);
  led1.updateLED();
  delay(500);
  led1.setRGB(0,255,0);
  led1.updateLED();
  delay(500);
  led1.setRGB(0,0,255);
  led1.updateLED();
  delay(2000);
  return;

}

void loop()
{  
  led1.setRandomHue();
  led1.setSat(255);
  led1.setVal(255);
  led1.updateLED();
  delay(1000);
  led1.setRandomColor();
  led1.updateLED();
  delay(1000);
  return;

}