# LEDs Randomly smooth transitioning, accounting for black or how-to switch using HSV

I am stuck trying to get it not to account for black in RGB. My first instinct was to use the HSV color spectrum over the RGB rainbow but, the same code will behaves differently in HSV. If i could get the same effect in HSV I would, and that would account for the black, but I have not found a solution for that or the accounting for black in RGB. Here is my code:

#include <FastLED.h>

#define LED_COUNT     96
#define LED_OUT       13
#define BUTTON_IN     10
#define ANALOG_INPUT  A9
#define EXTRA_PIN_A    7
#define EXTRA_PIN_B   11

struct CRGB leds[LED_COUNT];

void setup() {
Serial.begin(57600);
LEDS.show();
}

void colorLoop() {

static int Col1;
static int Col2;
static int Col3;

static int C1;
static int C2;
static int C3;

if ((((Col1 == 0) || (Col1 == 250)) && (((Col2 == 0) || (Col2 == 250)) && ((Col3 == 0) || (Col3 == 250))))) {

// select a random number from 1 to 2 for the array
C1 = random(1, 3);
C2 = random(1, 3);
C3 = random(1, 3);
}

if (((C1 == 1) && (Col1 != 0))) {
Col1 = (Col1 - 10);
}
if (((C2 == 1) && (Col2 != 0))) {
Col2 = (Col2 - 10);
}
if (((C3 == 1) && (Col3 != 0))) {
Col3 = (Col3 - 10);
}

if (((C1 == 2) && (Col1 != 250))) {
Col1 = (Col1 + 10);
}
if (((C2 == 2) && (Col2 != 250))) {
Col2 = (Col2 + 10);
}
if (((C3 == 2) && (Col3 != 250))) {
Col3 = (Col3 + 10);
}

for (uint8_t i = 0; i < LED_COUNT; i++) {
leds[i] = CRGB(Col1, Col2, Col3);
}
delay(100);
LEDS.show();
}

void loop() {
colorLoop();
}
• Does your definition of black refers to all the LEDs off? – Photon Aug 9 '17 at 4:03
• yes, RGB(0, 0, 0) displays the same as the option "off". – Oddacon Aug 9 '17 at 4:05

Black will basically be when all the colours have reduced to 0. That can only happen when all three of C1, C2 and C3 are 1. So you basically need to ensure that never happens.

And that is simple enough to arrange, with a "try again" construct:

if ((((Col1 == 0) || (Col1 == 250)) && (((Col2 == 0) || (Col2 == 250)) && ((Col3 == 0) || (Col3 == 250))))) {

// select a random number from 1 to 2 for the C1,C2,C3 array
do {
C1 = random(1, 3);
C2 = random(1, 3);
C3 = random(1, 3);
} while ((C1 == 1) && (C2 == 1) && (C3 == 1));
}

Pick three numbers. If they are all 1 then you are destined towards black. So go back and pick three new random numbers. Keep trying until you get at least one result that isn't 1.

• nice approach @Majenko but, that would simply take away from the functionality. – Oddacon Aug 10 '17 at 4:10
• How so? It gives you the same range of random numbers for the three values except it rules out getting 1,1,1 which would fade all the channels to black. It would give you 1,1,2 1,2,1 1,2,2 ... 2,2,2 but never 1,1,1 – Majenko Aug 10 '17 at 10:42

For it not to be black, at least one color (R,G,B) have to be on.

Before assigning the color values to the LED, maybe you can try using the constrain function to keep the values within a range. For example,

...

Col1 = constrain(Col1, 50, 150);  //If anything falls below 50, set it to the minimum value (50)
Col2 = constrain(Col2, 50, 150);
Col3 = constrain(Col3, 50, 150);

for (uint8_t i = 0; i < LED_COUNT; i++) {
leds[i] = CRGB(Col1, Col2, Col3);
}

....

Sure enough! adding the constrain function to one of the static integers fixed the RGB from going to black. Now simply set 50 as the min value in the rest of the code:

void colorLoop() {
//Set the minimum value to 50
static int Col1 = constrain(Col1, 50, 255);
static int Col2;
static int Col3;

static int C1;
static int C2;
static int C3;

if ((((Col1 == 50) || (Col1 == 250)) && (((Col2 == 0) || (Col2 == 250)) && ((Col3 == 0) || (Col3 == 250))))) {

// select a random number from 1 to 2 for the C1,C2,C3 array
C1 = random(1, 3);
C2 = random(1, 3);
C3 = random(1, 3);
}

if (((C1 == 1) && (Col1 != 50))) {
Col1 = (Col1 - 10);
}
if (((C2 == 1) && (Col2 != 0))) {
Col2 = (Col2 - 10);
}
if (((C3 == 1) && (Col3 != 0))) {
Col3 = (Col3 - 10);
}
if (((C1 == 2) && (Col1 != 250))) {
Col1 = (Col1 + 10);
}
if (((C2 == 2) && (Col2 != 250))) {
Col2 = (Col2 + 10);
}
if (((C3 == 2) && (Col3 != 250))) {
Col3 = (Col3 + 10);
}

for (uint8_t i = 0; i < LED_COUNT; i++) {
leds[i] = CRGB(Col1, Col2, Col3);
}
delay(100);
LEDS.show();
}
• great approach @Photon! however, using the constrain eliminates a lot of color possibilities. – Oddacon Aug 9 '17 at 5:45

I found this approach works:

if (((Col1 <= 50) && ((Col2 <= 50) && (Col3 <= 50)))) {  //avoid black
C1 = 2;
C2 = 2;
C3 = 2;
}