Randomize RGB LED colors

I'm thinking about working on a new project with multiple RGB LEDs. what I'd like to be able to do is have the LEDs randomize through a set of predefined colors. The problem is I'm not entirely sure how to go about it. What I did was #define the colors (#define RED 255, 0, 0) then I made an array of the colors

int colorArray[]={WHITE, RED, BLUE, GREEN};

then I created a random number between 0 and the total array number. The problem with this is that when it returns the array it only outputs (if that's the correct term) the first number in the #define. so colorArray[1] returns just 255.

I'm sure my problem is that I only have 1 year of learning c++ coding from over 20+ years ago so I'm probably not doing something right. I'm putting my code below that works so there is an idea of what I'm doing.

what I'd like to do is to have the code pick and display a random color on each LED but only from a predefined set of colors

#include <RGBLed.h>
// LEDS
#define LED1 12, 11, 10
#define LED2 9, 8, 7
#define LED3 6, 5, 4
#define LED4 A0, 2, 3
#define LED5 A3, A2, A1
//Buttons
#define button1 A6
#define button2 A7
//Colors
#define WHITE 255, 255, 255
#define RED 255, 0, 0
#define GREEN 0, 255, 0
#define BLUE 0, 0, 255
#define PURPLE 170, 0, 255
#define LIGHT_BLUE 127, 127, 127

// define LEDS
RGBLed led1(LED1, RGBLed::COMMON_CATHODE);
RGBLed led2(LED2, RGBLed::COMMON_CATHODE);
RGBLed led3(LED3, RGBLed::COMMON_CATHODE);
RGBLed led4(LED4, RGBLed::COMMON_CATHODE);
RGBLed led5(LED5, RGBLed::COMMON_CATHODE);

// Arrays 
int outputLEDArray[] = {LED1, LED2, LED3, LED4, LED5};
int outputLEDNumber = sizeof(outputLEDArray) / sizeof(outputLEDArray[0]);


//initialize pins
void initPins() {
  //set buttons pins to input
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
}

void setup() {
  // put your setup code here, to run once:
  initPins();
}

void loop() {
  // put your main code here, to run repeatedly:
  led1.setColor(WHITE);
  led2.setColor(RED);
  led3.setColor(GREEN);
  led4.setColor(BLUE);
  led5.setColor(PURPLE);
}

Hi @piperdave welcom to the forum.

Can you tell us what sort of LEDs do you have?
Also what sort of Arduino you have?
And where you got the RGBLed.h library.
Did this library come with examples?

The two main ways of controlling addressable LED strips are the AdaFruit
AdaFruit neopixels
or the fastLED libraries.
Fast LED

You might want to look at this How to get the best out of this forum before you proceed any further.
We only know what you tell us, and without knowing what you have, we don't stand a chance.

Sorry, more details always help. I’m using six 5mm rgb diodes and a nano board. The RGBLed.h library I just stumbled across when trying to work on this problem on wokwi. It seems pretty barebones and I think I may be doing things with it in a way it wasn’t really designed for. I do have the habit of getting locked into doing something one way which makes figuring out a better way to do things harder than it should be

Do you have a resistor in each of the RGB leads? You need this. If you have just one resistor then that will not work.

That seems key to understanding your problems, can you zip it up and post it?

Your code is rather complex, and I don't think you are using the #define correctly.

You can use # define, but not in both places you try.

# define does a text level substitution, so

  led1.setColor(WHITE);

turns into

  led1.setColor(255, 255, 255);

But here, the text substitution fails

int outputLEDArray[] = {LED1, LED2, LED3, LED4, LED5};

turns into

int outputLEDArray[] = {12, 11, 10,  9,  8, 7, 6, 5, 4, A0, 2, 3, A3, A2, A1};

Prove it to yourself by printing the value of outputLEDNumber - surprise, it's 15.

So you need a different way to express the array of LEDs. I can't now, but you should be able to make an array with elements of type RGBLed, then refer to them by indexing the array.

So instead of led1, led2 and so forth, you could refer to myRGBLedArray[0], myRGBLedArray[1] &c.

RGBLed myRGBLedArray[] = {led1, led2, led3, led4, led5};

and like

  myRGBLedArray[3].setColor(WHITE);

You may at some point have to do a similar thing with the color, where simple text substitution does not just work out well as it happens to in this case.

a7

Here's your sketch with the changes that I suggested and a few others.

You'll have to work out any way to deal with the colours other than getting with the library's means.

The code is still verbose; there are a few things that can be expressed more concisely. And you are risking what one risks using define without a full understanding. No matter.

Try it here:


// https://wokwi.com/projects/422957716593624065
// https://forum.arduino.cc/t/randomize-rgb-led-colors/1354125

# include "RGBLed.h"

# define LED1 12, 11, 10
# define LED2 9, 8, 7
# define LED3 6, 5, 4
# define LED4 A0, 2, 3
# define LED5 A3, A2, A1

RGBLed led1(LED1, RGBLed::COMMON_CATHODE);
RGBLed led2(LED2, RGBLed::COMMON_CATHODE);
RGBLed led3(LED3, RGBLed::COMMON_CATHODE);
RGBLed led4(LED4, RGBLed::COMMON_CATHODE);
RGBLed led5(LED5, RGBLed::COMMON_CATHODE);

RGBLed myRGBLedArray[] = {led1, led2, led3, led4, led5};
const byte outputLEDNumber = sizeof myRGBLedArray / sizeof *myRGBLedArray;

void setup() {
}

void loop() {
  myRGBLedArray[0].setColor(RGBLed::WHITE);
  myRGBLedArray[1].setColor(RGBLed::RED);
  myRGBLedArray[2].setColor(RGBLed::GREEN);
  myRGBLedArray[3].setColor(RGBLed::BLUE);
  myRGBLedArray[4].setColor(RGBLed::MAGENTA);
}

I removed the comments, be they gratuitous or not. I removed anything that was not required for this functionality.

HTH

a7

Taken literally, that's creating 10 RGBLed objects; the first five individually, then five in the array via copy construction from the first five. In reality, Copy Elision probably prevents the duplication. But, I think it's clearer to create the array directly:

# include "RGBLed.h"

# define LED1 12, 11, 10
# define LED2 9, 8, 7
# define LED3 6, 5, 4
# define LED4 A0, 2, 3
# define LED5 A3, A2, A1

RGBLed myRGBLedArray[] = {
  {LED1, RGBLed::COMMON_CATHODE},
  {LED2, RGBLed::COMMON_CATHODE},
  {LED3, RGBLed::COMMON_CATHODE},
  {LED4, RGBLed::COMMON_CATHODE},
  {LED5, RGBLed::COMMON_CATHODE}
};
const byte outputLEDNumber = sizeof myRGBLedArray / sizeof myRGBLedArray[0];
1 Like

There are many Nano boards these days with different chips and capabilities. It's important to know which type you have.

Assuming you have the most common classic Nano V3 (ATMEGA328), I can see some problems:

#define LED1 12, 11, 10
#define LED2 9, 8, 7
#define LED3 6, 5, 4
#define LED4 A0, 2, 3
#define LED5 A3, A2, A1

Only pins 3, 5, 6, 9, 10, 11 are PWM capable. If you use other pins, you will be limited to only 6 basic colours and will not be able to mix other colours like these:

#define PURPLE 170, 0, 255
#define LIGHT_BLUE 127, 127, 127

Next possible problem:

#define button1 A6
#define button2 A7

These pins can be used only as analog inputs. You cannot use digitalRead(). You cannot use INPUT_PULLUP mode, so an external pull-up resistor will be required. But you could use analogRead() and compare the result with 512.

1 Like

Thanks. I did not see (know) that I would create ten objects doing that. I have seen the pattern elsewhere and naively duplicated it.

The concision I alluded to was more or less what you have written; I did not like the two-step even without the very real objection. I have managed to directly make arrays of objects.

I thought it would be clearer the way I left it… so let's call that ironic.

a7

A lot of the problems are of my own creation. One of the things I remember from my first programming professor said was, the computer doesnt make a mistake, it does exactly what you tell it to, you just don't know what you're telling it.

First, I know what #define is used for, basically a placeholder to make things easier. I didn't think through what adding a complex #define to an array actually was doing, and that was causing problems.

I re-did the code. Removed the library that wasn't really needed. I have a bunch of defines in there but a lot of them are so I can just use one reference per LED rather than having to list each pin individually. Plus I made it all digital for now so I don't have to dick around with which pins work the way I want.

Now the problem is, is there any easy way to have each LED randomly change color? That's what Im trying to figure out.

// LEDS pins
#define led1Red 12
#define led1Green 11
#define led1Blue 10
#define led2Red 9
#define led2Green 8
#define led2Blue 7
#define led3Red 6
#define led3Green 5
#define led3Blue 4
#define led4Red A0
#define led4Green 2
#define led4Blue 3
#define led5Red A3
#define led5Green A2 
#define led5Blue A1
//LED groups
#define LED1 12, 11, 10
#define LED2 9, 8, 7
#define LED3 6, 5, 4
#define LED4 A0, 2, 3
#define LED5 A3, A2, A1
//Buttons
#define button1 A6
#define button2 A7
//Colors
#define RED HIGH, LOW, LOW
#define GREEN LOW, HIGH, LOW
#define BLUE LOW, LOW, HIGH
#define WHITE HIGH, HIGH, HIGH
#define LIGHT_BLUE LOW, HIGH, HIGH
#define PURPLE HIGH, LOW, HIGH


// Arrays 
int outputLEDArray[] = {led1Red, led1Green, led1Blue, led2Red, led2Green, 
led2Blue, led3Red, led3Green, led3Blue, led4Red, led4Green, led4Blue, 
led5Red, led5Green, led5Blue}; //creates array of all the LED pins
int outputLEDNumber = sizeof(outputLEDArray) / sizeof(outputLEDArray[0]);


//initialize pins
void initPins() {
  //set LED pins to output
  for(int i = 0; i < outputLEDNumber; i++) {
    pinMode(outputLEDArray[i], OUTPUT);
  }
  //set buttons pins to input
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
}

// setColor(LED, COLOR)
void setColor(int redPin, int greenPin, int bluePin, int redValue, int greenValue,  int blueValue) {
   digitalWrite(redPin, redValue);
   digitalWrite(greenPin,  greenValue);
   digitalWrite(bluePin, blueValue);
}

void setup() {
  // put your setup code here, to run once:
  initPins();
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  setColor(LED1, RED);
  setColor(LED2, GREEN);
  setColor(LED3, BLUE);
  setColor(LED4, LIGHT_BLUE);
  setColor(LED5, PURPLE);
}

Looks like you want to do you. Without sorting out what you've been up to in the code, I can only say you should be able to write a function

void turnThisLEDThatColor(int whichLED, int whatColor)
{
//...
}

by referring to the LEDs and the colors as indices into arrays of them. Becuase you will have arranged them to be. In arrays.

Then you must know about random(), so anywhere you want

  turnThisLEDThatColor(random(6), random(12));

assuming you have five LEDs and twelve colors.

You could use delay() to involve time in this random behaviour, but you may be smart enough to skip directly to the use of millis() as seen in the IDE "blink without delay" example.

a7

I inadvertently saved over the first code in the simulation after making changes as suggested by @gfvalvo and @alto777.

I also numbered things from 0 by habit.

The code
// https://wokwi.com/projects/422957716593624065
// https://forum.arduino.cc/t/randomize-rgb-led-colors/1354125

# include "RGBLed.h"

# define LED0 12, 11, 10
# define LED1 9, 8, 7
# define LED2 6, 5, 4
# define LED3 A0, 2, 3
# define LED4 A3, A2, A1

# define button1 A6
# define button2 A7

int myColor[][3] = {
// OFF
  {255, 0, 0},
// RED
  {255, 0, 0},
// GREEN
  {0, 255, 0},
// BLUE
  {0, 0, 255},
// CYAN
  {0, 255, 255},
// MAGENTA
  {255, 0, 255},
// YELLOW
  {255, 255, 0},
// WHITE
  {255, 255, 255},
};

const byte nColors = sizeof myColor / sizeof *myColor;
enum byName {Black, Red, Green, Blue, Cyan, Magenta, Yellow, White};

RGBLed myRGBLedArray[] = {
  {LED0, RGBLed::COMMON_CATHODE},
  {LED1, RGBLed::COMMON_CATHODE},
  {LED2, RGBLed::COMMON_CATHODE},
  {LED3, RGBLed::COMMON_CATHODE},
  {LED4, RGBLed::COMMON_CATHODE},
};

const byte outputLEDNumber = sizeof myRGBLedArray / sizeof *myRGBLedArray;

void initPins() {
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
}

void setup() {
  initPins();
}

void loop() {
  myRGBLedArray[0].setColor(myColor[White]);

  myRGBLedArray[1].setColor(myColor[Red]);
  myRGBLedArray[2].setColor(myColor[Green]);
  myRGBLedArray[3].setColor(myColor[Blue]);

  myRGBLedArray[4].setColor(myColor[Magenta]);
}

//This text will be hidden

a7

You are quite correct. What you want can't be done easily because of the way you have written your code. Use more arrays and it will become much easier.

Any time you make variables or constants (like #define) with numbers in their names, this should probably be an array.

An array is just like any other type of variable, except that instead of holding only one value, it can hold many values. Each value has an index number that you can use to specify which value in the array you want to use.

Always remember that array indexes begin at 0, not 1. If an array holds 10 values, their indexes are 0 to 9, not 1 to 10.

1 Like

@piperdave - I usually don't use libraries I can avoid, and TBH my first thought was to wonder why you would bother with RGBLed.h, as figuring out how to use it might be the more trouble than writing code that would be your own.

Now however it seems jettisoning the library is a step in the wrong direction. The library object RGBLed makes it somewhat easy to talk about N of them and deal with all those pins and stuff.

I recommend you take a big bite of C++ and write your own class for this, or use the library to save the trouble and either way do this in a straightforward manner.

You could probably do it old school in plain C and still end up with a better base upon which to build.

a7

I’ll be honest, I don’t really grasp the concept of arrays. I kind of get it and can do basic things with them. I know there is so much more they can do I just have a mental block on how to work with them. I’ve read a half dozen websites and tutorials about them and I just don’t quite get it

Chapter 5 of The C Programming Language by Kernighan and Ritchie would be worth any time spent.

It's not just arrays, but pointers. In C these two enjoy a very nice companionship, a thorough understanding of which is IMO essential to being able to read and write effectively in the language and its successor.

Any edition will do, it can be found for free online.

It's dense but is one of the best books on a language I have ever used. I've lost and given away copies; the one I use is > 40 years of age and shows it.

a7

I explained it pretty simply in post #13. What don't you get?

I have assumed you might remember more from "1 year of learning c++ coding from over 20+ years ago", but I have certainly forgotten more than I ever knew about things from that long ago. I've prolly managed to forget what I have forgotten.

IDK what all search hits you've slogged through. It's a jungle out there. Here's two articles from the simple trick of adding "Arduino" to any search, like arduino array:

https://docs.arduino.cc/language-reference/en/variables/data-types/array/

and

https://docs.arduino.cc/built-in-examples/control-structures/Arrays/

Work some examples. I find it easier to use the simulator or even just an online C++ compiler to learn about new language features, in the latter case free of any of the twists that show up in programming for microprocessors and the real world they control.

a7

Interesting fact, at least to me. Somewhere in my storage unit I have a box of books from my dad’s house that have sat there since he died 5 years ago. One of the books is a signed first edition of this book that was given as a gift from one of the authors to my dad. He helped write some of the early C libraries.

My dad was a programmer who started in the 60s. One of his biggest regrets was that I became a musician instead of a programmer. I’ve been using computers since the late 70s. We had a terminal in out house with a dedicated dial in line to a server at his work. After a year of studying computer science in school I switched my major to fine arts. I just didn’t understand it

This was more of a general statement about arrays, not anything against what you said. When I get home tonight I’ll be rereading this thread and trying to do some more work