Multiple, Different Random Values

Salutations fellow nerds.

I am using the Neopixel library to control four independent LED strips. I would like each strip to be a different colour but the random value and seed is consistent for each strip.

How do you suggest I modify to the code such that each buildings color is independent of the others?

  // Sets strips to (R,G,B, color load time)
  colourFill(Building1.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building2.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building3.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building4.Color(random(0,255),random(0,255),random(0,255)), 1);

Ryce:
Salutations fellow nerds.

I am using the Neopixel library to control four independent LED strips. I would like each strip to be a different colour but the random value and seed is consistent for each strip.

How do you suggest I modify to the code such that each buildings color is independent of the others?

You want random values in the range 0 up to 254 maximum?
And after each controller reset you want to start over with the same "random" values created with same seed value?

Perhaps try:

 // Sets strips to (R,G,B, color load time)
byte rand1, rand2, rand3;
rand1=random(0,255);
rand2=random(0,255);
rand3=random(0,255);

  colourFill(Building1.Color(rand1, rand2, rand3), 1);
  colourFill(Building2.Color(rand1, rand2, rand3), 1);
  colourFill(Building3.Color(rand1, rand2, rand3), 1);
  colourFill(Building4.Color(rand1, rand2, rand3), 1);

Not quite.

You see, this code results with the same problem. All four LED strips are emitting identical colours. I switched the positions of RandN and got the same result.

byte rand1, rand2, rand3;
rand1=random(0,255);
rand2=random(0,255);
rand3=random(0,255);

  colourFill(Building1.Color(rand1, rand2, rand3), 1);
  colourFill(Building2.Color(rand2, rand1, rand3), 1);
  colourFill(Building3.Color(rand3, rand2, rand1), 1);
  colourFill(Building4.Color(rand1, rand3, rand2), 1);

colourFill(Building1.Color(random(0,256), random(0,256), random(0,256)), 1);

etc

That is unfortunately the original code.

The random values are only regenerated from the seed once per cycle/loop execution, nice try though.

Ryce:
Salutations fellow nerds.

I am using the Neopixel library to control four independent LED strips. I would like each strip to be a different colour but the random value and seed is consistent for each strip.

How do you suggest I modify to the code such that each buildings color is independent of the others?

  // Sets strips to (R,G,B, color load time)

colourFill(Building1.Color(random(0,255),random(0,255),random(0,255)), 1);
 colourFill(Building2.Color(random(0,255),random(0,255),random(0,255)), 1);
 colourFill(Building3.Color(random(0,255),random(0,255),random(0,255)), 1);
 colourFill(Building4.Color(random(0,255),random(0,255),random(0,255)), 1);

Do you mean that you get the same "random" numbers each time you run the code or the same "random" number for each strip ?

If you posted the whole program it would be easier to provide help.

To be frank, adding the whole code will probably over-complicate the matter.

What is expected is that the colors displayed by the four strips are not only random, but also different from each other.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

// "Bl#" is name of the strip pin followed by PWM pin on Arduino
#define Bl1 9
#define Bl2 6
#define Bl3 5
#define Bl4 3

// Defines "Building#" names for Adafruit Library
Adafruit_NeoPixel Building1 = Adafruit_NeoPixel(30, Bl1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel Building2 = Adafruit_NeoPixel(30, Bl2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel Building3 = Adafruit_NeoPixel(25, Bl3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel Building4 = Adafruit_NeoPixel(25, Bl4, NEO_GRB + NEO_KHZ800);

void setup() {
  // Clear all strip data
  Building1.begin();
  Building2.begin();
  Building3.begin();
  Building4.begin();
    
  // Initialize pixel brightness (0-255), remember that more bright costs more power.
  Building1.setBrightness(255); 
  Building2.setBrightness(255);
  Building3.setBrightness(255);
  Building4.setBrightness(255);

  // Initialize all pixels to 'off'
  Building1.show(); 
  Building2.show();
  Building3.show();
  Building4.show();
}

void colourFill(uint32_t c, uint8_t wait) {
  // This script programs all LEDS on a strip to have the same color.
  for(uint16_t i=0; i<Building1.numPixels(); i++) {Building1.setPixelColor(i, c); Building1.show();}
  for(uint16_t i=0; i<Building2.numPixels(); i++) {Building2.setPixelColor(i, c); Building2.show();}
  for(uint16_t i=0; i<Building3.numPixels(); i++) {Building3.setPixelColor(i, c); Building3.show();}
  for(uint16_t i=0; i<Building4.numPixels(); i++) {Building4.setPixelColor(i, c); Building4.show();}
};

void loop() {
  // Sets Building strips to (R,G,B, color load time)
byte rand1, rand2, rand3;
rand1=random(0,255);
rand2=random(0,255);
rand3=random(0,255);

  colourFill(Building1.Color(rand1, rand2, rand3), 1);
  colourFill(Building2.Color(rand2, rand1, rand3), 1);
  colourFill(Building3.Color(rand3, rand2, rand1), 1);
  colourFill(Building4.Color(rand1, rand3, rand2), 1);

  // Delay period
  delay(1000); // Quarter minute between cycles
  //delay(30000); // Half minute between cycles
  //delay(60000); // One minute between cycles
}

The problem is in your colourFill function...

I'll give you a hint, try this code...

  // Sets strips to (R,G,B, color load time)
  colourFill(Building1.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building2.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building3.Color(random(0,255),random(0,255),random(0,255)), 1);
  colourFill(Building4.Color(255, 0, 0), 1); //red

I am willing to bet that all 4 strips turn red, why?

What is expected is that the colors displayed by the four strips are not only random, but also different from each other

They won't actually be random but only pseudo random. You can improve that somewhat by using the randomSeed() function perhaps fed by the value from a floating analogue input.

If you want each strip to be a different colour then you need to check that the colour has not already been generated by the random() statements (unlikely) and if so choose another colour.

You didn't actually answer my questions about what is happening with the current code.

void colourFill(uint32_t c, uint8_t wait) {
  // This script programs all LEDS on a strip to have the same color.

You call this function. If it does what the comment says could it be the basis of your problem ?

I have been asking repeatedly what the best method is for generating MULTIPLE random values during the SAME execution of a loop.

I do not think I can be more verbose. I am aware that the OP code was problematic, but I assumed that my readers would be capable of considering the original code in light of my request. I seem to have overestimated my audience.

First, colourFill is NOT a problem because it takes the values assigned in the MAIN loop as input. I could write independent values as input and achieve the desired effect, but the colors would NOT be random.

Second, randomseed does not have any purpose in this program because RandomSeed sets the value of all Randoms within an execution. For example, when Seed is A then all randoms per cycle are based on A (that does NOT mean that each random is different from the other). The random value is the same during the same execution of the Main and can be changed by a seed, but all references to random will be calling on the same value.

Keep posting ideas folks, I've got all morning.

First of all...that came off a little rude...
Second of all, if what you want is 4 strips of different colors, then colourFill DEFINITELY IS your problem!
Here is another hint!

void colourFill(uint32_t c, uint8_t wait) {
  // This script programs all LEDS on a strip to have the same color.

Read that comment, then check what your function ACUTALLY does...

Another hint...

  // Sets strips to (R,G,B, color load time)
  colourFill(Building4.Color(255, 0, 0), 1); //red

Run this code, now tell me, do ALL 4 of your strips turn red, even though I only set '1' strip? WHY?!!?!

Only posting colourFill() later did NOT aid your cause.

Ps991 - Struck gold. In my haste, I forgot that repeating the for loops within the same colourfill script with the same random input would pull the same colour value.

You were right that in identifying colourfill as the problem. The program now performs as expected. I apologize for expressing my frustration so crudely.

:slight_smile:

If you want them random but different from each other, one option is to use the HSB model. Pick a random angle between 0 and 2*PI, offset each strip by PI/2 degrees - that gives you the hue for that pixel. To produce RGB from the hue, use sin() and offset each component by a third (of 2PI).

This means that pixels 0/2 and 1/3 are complementary colours. If you are jumping around randomly, it perhaps won't be obvious.

Your pixels will have a mostly constant brightness, and the net colour of the sum of them will always be white (or close to).

float rnd = random(0,1000) / 1000f * 2 * PI;

byte colour[3];

for(int pixel = 0; pixel < 4; pixel ++) {
  for(int rgb = 0; rgb < 3; rgb++) {
    float theta = rnd + pixel/4f * 2 * PI + rgb/3f * 2 * PI;
    colour[rgb] = (byte) ( (sin(theta) + 1) / 2 * 255.99f);
  }

  Serial.print("pixel ");
  Serial.print(pixel);
  Serial.print(" red ");
  Serial.print(rgb[0]);
  Serial.print(" green ");
  Serial.print(rgb[1]);
  Serial.print(" blue ");
  Serial.print(rgb[2]);
  Serial.println();
}

Ps991:
If you want them random but different from each other, one option is to use the HSB model. Pick a random angle between 0 and 2*PI, offset each strip by PI/2 degrees - that gives you the hue for that pixel. To produce RGB from the hue, use sin() and offset each component by a third (of 2PI).

If I correct your code to what I think you intended, to get it to compile, it does behave in an "interesting" way.

I observe that the probability that an individual R, G or B value will be 0 or 255 is more than twice as great as the probability of the value being 1 or 254, with other values having lower probability.

Typically, the distribution comes out looking like this:

000 ****************************************************************
001 ****************************
002 *********************
003 ************************
004 ******************
005 ***************
006 **************
007 ************
008 ****************
009 *************
010 *******
011 **************
012 **********
013 **********
014 ************
015 **********
016 *********
017 ********
018 ***********
019 ******
020 ********
021 ******
022 ********
023 ******
024 **********
...
231 **********
232 ******
233 ********
234 ******
235 ********
236 ******
237 ***********
238 ********
239 *********
240 **********
241 ************
242 ************
243 ********
244 **************
245 *******
246 *************
247 ****************
248 ************
249 **************
250 ***************
251 ******************
252 ************************
253 *********************
254 ****************************
255 ****************************************************************

If that is deliberate, what is the advantage of that?