Trying to program RGB fading between RANDOM colours

Upon research for help I have not found anything for my exact situation. Is it possible for an RGB led to fade into a random colour? All other projects have pre-defined colours that the led specifically fades into not the arduino randomly picking one between fade loops. I am trying to combine the example Fade code with and RGB random colour code (attached as RGBLedChange). I have made many prototypes of code and none of them work properly, is there a solution or must I use predetermined colours?

RGBLedChange.ino (414 Bytes)

RGBTransitionRandom.ino (735 Bytes)

Fade.ino (358 Bytes)

In RGBTransitionRandom, you set a random brightness once and next you use brightness (which goes from 0 to 255 and back). You should assign the random value to a variable and next work with that variable.

Below code uses 6 variables (2 per color); a value that you want to reach (the endvalue) and the current brightness value.

int pin1 = 9;
int pin2 = 10;
int pin3 = 11;


void setup() {
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
}


// desired brightness for the colors
int endRed = 0;
int endGreen = 0;
int endBlue = 0;

// current brightness of the colors
int brRed = 0;
int brGreen = 0;
int brBlue = 0;

void loop()
{

  // assign an endvalue for the three colors
  endRed = random(0, 255);
  endGreen = random(0, 255);
  endBlue = random(0, 255);

  // while the endvalues are not reached, increase brightness of each color
  while (brRed < endRed || brGreen < endGreen || brBlue < endBlue)
  {
    if (brRed < endRed) brRed++;
    if (brGreen < endGreen) brGreen++;
    if (brBlue < endBlue) brBlue++;

    analogWrite(pin1, brRed);
    analogWrite(pin2, brGreen);
    analogWrite(pin3, brBlue);

    delay(500);
  }

  // assign a new endvalue for the three colors
  endRed = random(0, 255);
  endGreen = random(0, 255);
  endBlue = random(0, 255);

  // while the endvalues are not reached, decrease brightness of each color
  while (brRed > endRed || brGreen > endGreen || brBlue < endBlue)
  {
    if (brRed  > endRed) brRed--;
    if (brGreen  > endGreen) brGreen--;
    if (brBlue  > endBlue) brBlue--;

    analogWrite(pin1, brRed);
    analogWrite(pin2, brGreen);
    analogWrite(pin3, brBlue);

    delay(500);
  }

}

Not tested (but compiles).

I uploaded you sketch and it only stays on one colour, a pale green, it incrementally gets brighter then stays bright. This has opened my mind to other options for documentation, thank you. It seems this is a difficult project. :slight_smile:

Colour is a proportional ratio between RGB.

Maybe make colours using a ratio and then fade in proportion.

E.g.

Ratio RGB = 3:2:1 (255,170,85) = "Orangey". Again, some clibration values of the LEDs may be needed as I assume luminance is different at different voltage levels per colour.

Then a fade would be done as such:

for (byte i=255; i>0;i--){
analogWrite(Rled,i);
analogWrite(Gled,(i*(2.0/3.0));
analogWrite(BLed,(i*(1.0/3.0));
}

Agian, no idea if it would work...but a calibration curve may also be required.
Different colours (RGB) have different luminances at the same voltage. Blue may be twice as bright as red at analogWrite(100) for example.

AVRdudes:
I uploaded you sketch and it only stays on one colour, a pale green, it incrementally gets brighter then stays bright. This has opened my mind to other options for documentation, thank you. It seems this is a difficult project. :slight_smile:

There was one bug in the second while loop; it should be

  while (brRed > endRed || brGreen > endGreen || brBlue > endBlue)
  {
  }

Not sure how it affected the code.

The other issue with the code is that it e.g. counts red up to 100, green to 50 and blue to 100. Next it assigns new endvalues for the decrement; if one or more of those new values are higher than the current values, the decrement for the specific color does nothing. Similar for the increment (if the new values are lower then the current ones).

The below code contains a modified loop (fixed the bug) and displays the RGB values (both current value and end value, the latter between brackets) on the serial port to make clear what happens. I hope it helps to understand. I have also renamed pin1, pin2 and pin3 to more sensible names.

int pinRed = 9;
int pinGreen = 10;
int pinBlue = 11;


void setup() {
  pinMode(pinRed, OUTPUT);
  pinMode(pinGreen, OUTPUT);
  pinMode(pinBlue, OUTPUT);

  Serial.begin(9600);
}


// desired brightness for the colors
int endRed = 0;
int endGreen = 0;
int endBlue = 0;

// current brightness of the colors
int brRed = 0;
int brGreen = 0;
int brBlue = 0;

void loop()
{
char buffer[50];
  // assign an endvalue for the three colors
  endRed = random(0, 255);
  endGreen = random(0, 255);
  endBlue = random(0, 255);


  // while the endvalues are not reached, increase brightness of each color
  while (brRed < endRed || brGreen < endGreen || brBlue < endBlue)
  {
    if (brRed < endRed) brRed++;
    if (brGreen < endGreen) brGreen++;
    if (brBlue < endBlue) brBlue++;

    analogWrite(pinRed, brRed);
    analogWrite(pinGreen, brGreen);
    analogWrite(pinBlue, brBlue);

    snprintf(buffer, sizeof(buffer), "inc: r = %03d (%03d), g = %03d (%03d), b = %03d (%03d)", brRed, endRed, brGreen, endGreen, brBlue, endBlue);
    Serial.println(buffer);
    delay(250);
  }

  // assign a new endvalue for the three colors
  endRed = random(0, 255);
  endGreen = random(0, 255);
  endBlue = random(0, 255);

  // while the endvalues are not reached, decrease brightness of each color
  while (brRed > endRed || brGreen > endGreen || brBlue > endBlue)
  {
    if (brRed > endRed) brRed--;
    if (brGreen > endGreen) brGreen--;
    if (brBlue > endBlue) brBlue--;

    analogWrite(pinRed, brRed);
    analogWrite(pinGreen, brGreen);
    analogWrite(pinBlue, brBlue);

    snprintf(buffer, sizeof(buffer), "dec: r = %03d (%03d), g = %03d (%03d), b = %03d (%03d)", brRed, endRed, brGreen, endGreen, brBlue, endBlue);
    Serial.println(buffer);
    delay(250);
  }

}

R = map(val,0,max,redStart,redEnd);
G = map(val,0,max,greenStart,greenEnd);
B = map(val,0,max,blueStart,blueEnd);

..where val goes from zero to max.

At val == 0, you get the Start color.
At val == max, you get the End color.

For larger values of max, you get slower/smoother fades.

You can also have a look at sparkfun RGB example.

hi i have made a system to FADE or SNAP (Fadetime), Scenetime and predefined Steps/colors.

i would also recommend to use predefined colors, and if you make STEPS inside a chase. the arduino can randomly choose a STEP. so the chase will always look differnt.

because if you randomly choose the RGB values you will het allot!!! of realy ugly colors.
and if you predefine it your allways sure the color will look nice.

spirit:
if you randomly choose the RGB values you will het allot!!! of realy ugly colors.
and if you predefine it your allways sure the color will look nice.

Agreed. If you want "rainbow" type colors, limit yourself to only using two colors at a time. Transitions between red and green, green and blue, and blue and red all look good. If you start adding a third color, the color will look less saturated.

Simple linear fading along the RGB axes will result in some odd effects. You may like the effect. If not, consider linear fades along the YUV axes. This will look more "correct" to the human eye. You will need to keep your colours in YUV coordinates and then convert to RGB for output to the LEDs. The math is fairly complex but so long as you're not trying to colour a thousand LEDs, it should be easy enough for the Arduino.

Interpolating between colours is just like drawing lines between two points in a space. The simplest space to get your head round is RGB colour cubic space. Split the distance between the two points into three orthogonal components and work out the distance between each. Then work out the step needed for each component to go between the points in the number of steps you need. Simply use step size = distance / number of steps.

Then to drive it move each component by one step and display, repeat at regular time intervals until the transition is done. It might help to use floating point or better fixed point arithmetic.

Note that if the two colours are on opposite side of the grey line, that is the diagonal across the cube between black and white, will fade through grey.

You get a different set of colours produced depending on the colour space you use, so the colour transition has different colours in the RGB cubic colour space or the HSV hex cone space.

Thank you for all your help with this it is much appreciated. I will go ahead and use predefined colours for this project as that seems the more feasible and easier choice. I will need to make sure I have the right resistors for even brightness through all three colours. Thank you for all your help.