2

I have been trying to achieve a way to tap into the 16 million colors RGB provides for this LED strip. I thought of using LEDS.setBrightness(); but I have not been successful in my attempts. I have read the documentation on color fading, but I have not been able to write this to my Arduino Leonardo. Here is my code below, which cycles through the initial rainbow of 0-255. I was wondering how to get more than 0-255 if not all the colors.

#include <FastLED.h>

#define LED_COUNT 60
#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];
int wait_time = 5;

void setup() {
  Serial.begin(57600);
  LEDS.addLeds<WS2812B, LED_OUT, GRB>(leds, LED_COUNT);
  LEDS.show();
}

void loop() {
  //start from red
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = 255;
    int g = 0;
    int b = colorStep;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }

  //into blue
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = colorStep;
    int g = 0;
    int b = 255;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }
  //start from blue
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = 0;
    int g = colorStep;
    int b = 255;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }
  //into green
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = 0;
    int g = 255;
    int b = colorStep;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }
  //start from green
  for(int colorStep=0; colorStep <= 255; colorStep++) {
    int r = colorStep;
    int g = 255;
    int b = 0;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }
  //into yellow
  for(int colorStep=255; colorStep >= 0; colorStep--) {
    int r = 255;
    int g = colorStep;
    int b = 0;
    // Now loop though each of the LEDs and set each one to the current color
    for(int x = 0; x < LED_COUNT; x++) {
      leds[x] = CRGB(r,g,b);
    }
    // Display the colors we just set on the actual LEDs
    delay(wait_time);
    LEDS.show();
  }
} //end main loop
4
  • 1
    but RGB's 0-255 levels is all the colors, what are you trying to do?
    – dandavis
    Mar 13, 2017 at 2:52
  • that's correct, but if you follow my loops you'll see that I am only doing the combinations 0 < 255 and 0 > 255 for rgb. I.E. 0, 0, 255 // blue or 255, 0, 0 //red which is why i said the initial rainbow. there are no combinations of let's say 128, 64, 250.
    – Oddacon
    Mar 14, 2017 at 22:04
  • Ahh, i see; then just nest your loops...
    – dandavis
    Mar 14, 2017 at 22:06
  • tried that like w/ @6v6gt answer. unfortunately, it does not cycle thru the LEDs properly. There seems to be a iteration problem with the first nested loop (not the code provided) just the way the FastLED class handles the nesting?
    – Oddacon
    Mar 21, 2017 at 20:25

7 Answers 7

2

I think it's worth noting that the three 255 values for RGB colour space is just one way to encode the 255^3 (16,581,375) colours. These include each and every brightness level too.

If you are trying to get a rainbow effect, you may have more success or find it easier to use a HSL or HSV colour space.

HSV uses Hue, Saturation and Value instead of RGB. FastLED has optimized it's implementation of HSV to use a 0-255 addressing for Hue (instead of 360), keeping it fast for animations run on microcontrollers:

https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

1
  • Re-using fastled is indeed a very good option! You'll overcome reinventing the wheel, and have a more efficiënt wheel ;p
    – Paul
    Mar 15, 2017 at 9:17
1

I've included a simple sketch that will cycle a single RGB led using the sine fade technique

// Cycle a single RGB led using the sine fade technique
// For common cathode led

const uint8_t lights[360]={
  0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 35, 37, 39,
 42, 44, 47, 49, 52, 55, 58, 60, 63, 66, 69, 72, 75, 78, 81, 85, 88, 91, 94, 97, 101, 104, 107, 111, 114, 117, 121, 124, 127, 131, 134, 137,
141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 202, 205, 208, 210, 213, 215, 217, 220, 222, 224, 226, 229,
231, 232, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253,
252, 251, 251, 250, 249, 248, 246, 245, 244, 242, 241, 239, 238, 236, 234, 232, 231, 229, 226, 224, 222, 220, 217, 215, 213, 210, 208, 205, 202, 200, 197, 194,
191, 188, 185, 182, 179, 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 111, 107, 104, 101, 97, 94, 91,
 88, 85, 81, 78, 75, 72, 69, 66, 63, 60, 58, 55, 52, 49, 47, 44, 42, 39, 37, 35, 32, 30, 28, 26, 24, 22, 20, 18, 17, 15, 13, 12,
 11, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

const byte redpin = 3;  
const byte greenpin = 5;  
const byte bluepin = 6;  
int loopdelay = 5000; // ms  
int displaylength = 50; // ms  

boolean showiterations = false;  

//_______________________________  
void setup() {  
      Serial.begin(9600);  
}

void loop() {  
for (int k=0; k<360; k++)  
{  
    if (showiterations) {  
    Serial.print(k);  
    Serial.print(F(","));  
    }
analogWrite(redpin, lights[(k+120)%360]);  
analogWrite(greenpin, lights[k]);  
analogWrite(bluepin, lights[(k+240)%360]);  
delay(displaylength);  
}
if (showiterations) {  
Serial.println("  ");  
}
delay(loopdelay);  
}

This sketch is derived from an Instructables posting entitled "How to Make Proper Rainbow and Random Colors With the RGB Color Model", http://www.instructables.com/id/How-to-Make-Proper-Rainbow-and-Random-Colors-With-/
It additionally provides information and rationale behind different techniques for cycling colours.


If you are trying to stagger the colours along the strip whilst creating a rainbow effect, I have another sketch [from Adafruit, I believe] that will do this. I've used it effectively with different Neopixel ring configurations. The sketch demonstrates a number of different techniques. I have currently commented out the invocations of all but the theaterChaseRainbow, but you may wish to explore them all.

#include <Adafruit_NeoPixel.h>
// following atatement should be wrapped with an ifdef for __AVR__, but this facility botches it up.
// As it is, formatting for the sketch is not quite right, and I do not have a solution for that.
  #include <avr/power.h>

const  byte PIN = 7;

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800)`
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, 6, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code


  strip.begin();
   colorWipe(strip.Color(0, 0, 0), 50); // blank
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Some example procedures showing how to display to the pixels:
//  colorWipe(strip.Color(255, 0, 0), 50); // Red
//  colorWipe(strip.Color(0, 255, 0), 50); // Green
//  colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
  // Send a theater pixel chase in...
//  theaterChase(strip.Color(127, 127, 127), 50); // White
//  theaterChase(strip.Color(127, 0, 0), 50); // Red
//  theaterChase(strip.Color(0, 0, 127), 50); // Blue

//  rainbow(20);
//  delay(50000);
//  colorWipe(strip.Color(0, 0, 0), 50); // blank
//  rainbowCycle(10);
//  delay(5000);
//    colorWipe(strip.Color(0, 0, 0), 50); // blank
//   delay(5000);
  theaterChaseRainbow(50);
//  delay(5000);
//    colorWipe(strip.Color(0, 0, 0), 50); // blank
//   delay(5000);
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));     
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
2
  • Although your answer is 100% correct, it might also become 100% useless if that link is moved, changed, merged into another one or the main site just disappears... :( Therefore, please edit your answer, and copy the relevant steps from the link into your answer, thereby guaranteeing your answer for 100% of the lifetime of this site! ;) You can always leave the link in at the bottom of your answer as a source for your material...
    – Avamander
    Mar 14, 2017 at 17:53
  • 1
    @Avamander, suggestion taken, pls re-evaluate.
    – KC Tucker
    Mar 16, 2017 at 19:07
1

You can make a smooth transition/sliding rainbow effect by using a sine wave lookup table, then phase shifting green and blue by 120 and 240 degrees.

#define RED 9
#define GREEN 10
#define BLUE 11

uint8_t sins[360] = {
  127,129,131,134,136,138,140,143,145,147,149,151,154,156,158,160,162,164,166,169,171,173,175,177,179,181,183,185,187,189,191,193,195,196,198,200,
  202,204,205,207,209,211,212,214,216,217,219,220,222,223,225,226,227,229,230,231,233,234,235,236,237,239,240,241,242,243,243,244,245,246,247,248,
  248,249,250,250,251,251,252,252,253,253,253,254,254,254,254,254,254,254,255,254,254,254,254,254,254,254,253,253,253,252,252,251,251,250,250,249,
  248,248,247,246,245,244,243,243,242,241,240,239,237,236,235,234,233,231,230,229,227,226,225,223,222,220,219,217,216,214,212,211,209,207,205,204,
  202,200,198,196,195,193,191,189,187,185,183,181,179,177,175,173,171,169,166,164,162,160,158,156,154,151,149,147,145,143,140,138,136,134,131,129,
  127,125,123,120,118,116,114,111,109,107,105,103,100,98,96,94,92,90,88,85,83,81,79,77,75,73,71,69,67,65,63,61,59,58,56,54,
  52,50,49,47,45,43,42,40,38,37,35,34,32,31,29,28,27,25,24,23,21,20,19,18,17,15,14,13,12,11,11,10,9,8,7,6,
  6,5,4,4,3,3,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,3,4,4,5,
  6,6,7,8,9,10,11,11,12,13,14,15,17,18,19,20,21,23,24,25,27,28,29,31,32,34,35,37,38,40,42,43,45,47,49,50,
  52,54,56,58,59,61,63,65,67,69,71,73,75,77,79,81,83,85,88,90,92,94,96,98,100,103,105,107,109,111,114,116,118,120,123,125
};
  
void setup() {
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
}

void loop() {
  for (int i = 0; i < 360; ++i)
  {
    analogWrite(RED, sins[i]);
    analogWrite(GREEN, sins[(i+120)%360]);
    analogWrite(BLUE, sins[(i+240)%360]);
    delay(2);
  }
}
0

If you want to display every one of the about 16 million possible colours, you will have to nest your for loops like in this example:

x = 1 ;  // only for testing
for ( int redx = 0 ; redx <= 255 ; redx ++ ) {
    for ( int greenx = 0 ; greenx <= 255 ; greenx ++ ) {
        for ( int bluex = 0 ; bluex <= 255 ; bluex ++ ) {
             leds[ x ] = CRGB(redx,greenx,bluex);
             delay(wait_time); 
             LEDS.show(); 
        }
    }
}
1
  • An alternative could be to use HSB or HSV instead of RGB, this way you can increase the hue over time to get the rainbow effect.
    – Paul
    Mar 13, 2017 at 7:23
0

You should consider making it non-blocking :)

loop(){
   //if(millis() > previous+100){//uncomment this part to only do a step of the rainbow effect every 100ms
   rainbowEffect();
   //previous = millis();
   //}

   //you can do other stuff, like check a buttons' state here.
   //using the same structure as above, you can choose to give it a higher or lower priority.
}

unsigned char r,g,b;
void rainbowEffect(){
   if(r>254){
      r=0;
      g++;
   }
   if(g>254){
      g=0;
      b++;
   }
   if(b>254){
      b=0;
   }
   r++;
   ledStrip.set(r,g,b);
}
0

I think @Mazaryk was correct, HSV is the way to go for this. RGB's 16+ million colors include brightness, and some of them just won't display on the strip, so I found a way to at least better fade thru:

int thissat = 255;           //- LOOPS DELAY VAR
int idex = 0;                //-LED INDEX
int ihue = 0;                //-hue (0-255)

void rainbow_fade() {
    ihue++;
    if (ihue > 255) {ihue = 0;}
    for(int idex = 0 ; idex < LED_COUNT; idex++ ) {
      leds[idex] = CHSV(ihue, thissat, 255);
    }
    LEDS.show();    
    delay(wait_time);
}
0

You could take advantage that the rgb color could be represented in a unsigned long. And use a counter. But have patience looping through 16 mio colors with 1ms at iteration take some time :-). (around 4-5 hours: 16581375/(1000[ms] * 60[m] * 60[h]) = 4,6 )

void loopThrougAllColors(){
  // The trick here is to use a unsigned long value as the color representation. 
  // Each byte represent a color (except the first)
  //          none, R  G  B
  //          0x00 00 00 00                     
  // Note: static means it is a global variable - but only seen in thisfunction.                                            
  static unsigned long ledColor = 0;        
  static int ledIndex = 0;

  ledColor++;
  ledColor &= 0x00FFFFFF; /* Overflow preventing (instead of if sentence checking the boundaries). */           

  leds[0] = ledColor;

  FastLED.show();
  FastLED.delay(1);
  //delay(10);
} 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.