FastLED: fill_rainbow() - Unexpected red pixel

I’m using the builtin fill_rainbow function for generating a rainbow spectrum on an LED strip. The issue is, I get a random red pixel midway through the yellow region. I’ve tried it on 3 different Arduino nano’s, and two different LED-strips. Here’s the code:

#include <FastLED.h>

#define DATA_PIN 2
#define NUM_LEDS 114
CRGB leds[NUM_LEDS];

uint8_t hue = 0;

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);

  fill_rainbow( leds, NUM_LEDS, hue, 1);
  for(int i=0; i<NUM_LEDS; i++) {
    Serial.print(i);
    Serial.print(' ');
    Serial.print(leds[i].r);
    Serial.print(' ');
    Serial.print(leds[i].g);
    Serial.print(' ');
    Serial.println(leds[i].b);
  }

  CHSV hsv;
  CRGB rgb;
  //rgb = hsv;
}


void loop() {
  fill_rainbow( leds, NUM_LEDS, hue, 1);
  FastLED.show();
}

Here pixel number 60 gets the rgb code 160, 0, 0. When it should have something like 160, 150, 0.

The strangest part of all is that I can get rid of the problem in two ways, either by uncommenting the line rgb = hsv;, or by commenting out the fill_rainbow function in the loop function. Any ideas whats going wrong?

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 1
  • Comments: 28 (11 by maintainers)

Commits related to this issue

Most upvoted comments

If the code isn’t working, its worth it to me to understand exactly why that is, what changed in the compilation process, so that I can understand where else to be aware of it. Everyone has been very helpful here with this one, especially during a very hard personal time, and I really appreciate all of it.

Hi @kriegsman,

I managed to create my own workaround for this issue. By copying the rainbow function from the source to my sketch file and changing the sat value to 255, it seems to be working for now. Very strange issue and I’d love to hear if you are able to solve it!

If you are having this issue yourself you can either try using the online editor as @ddesborough suggested or you can copy the source code for the fill_rainbow function to your sketch and use it from there.

Devin

I am experiencing this problem. I am a coding novice, so I don’t know the significance of my findings. If you use delay() the red pixel shows. However if you use millis() it does not.

The following code creates a red pixel in the yellowish region:

fill_rainbow( leds, NUM_LEDS, hue, 1);
  FastLED.show();
  hue++;
delay(30);  //any delay causes red pixel

The following code does not create a red pixel:

if(millis() > time_now + period){ 
 time_now = millis();
 fill_rainbow( leds, NUM_LEDS, hue, 1);
 FastLED.show();
 hue++;
}

I don’t know if this helps solve the problem. Hopefully someone can use it to get rid of their red pixel.

OK, some findings after playing with compiler options. The file I am making the compiler changes in is D:\Program Files (x86)\Arduino\hardware\arduino\avr\platform.txt.

The lines in that file that I am editing are: compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects

and

compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics

The specific parameter I am changing is the -Os (that is the letter O).

Using -Os (the default value) produces the red flash we have seen. I then went through the following process:

  1. Close the Arduino IDE
  2. Edit the -O option on the two lines in platform.txt and save the file
  3. Start the IDE
  4. Compile and upload.

Here are my results with various settings:

-Os
avrdude: 4138 bytes of flash verified (causes the red flash)

-O1
avrdude: 4558 bytes of flash verified (animation is fine)

-O2
avrdude: 5448 bytes of flash verified (animation is fine)

-O3
avrdude: 6452 bytes of flash verified (animation is fine)

-Os optimizes purely for size. The other options start trading size for better performance. I did not do any sort of performance benchmarking, but you can see the image size is growing with each optimization step.

So, until there is some better answer, you can change the optimization flags in platform.txt to get around this issue. Credit to @jamesgohl for his post which made me go down this path.

-Davin

Much like @DMJoubert, I had conducted a simple test of having my own fill_rainbow like function in my sketch. I simply did the following:

void testRainbow() 
{
  for(int i = 0; i < NUM_LEDS; i++){
    leds[i].setHue(gHue + 8*i);
  }
}

This works without issue. Change the 8 to whatever hue step you would like to take. Obviously gHue is a global. I was running this in the context of the DemoReel100 example.

The root cause would be interesting to understand. It makes me wonder if there are other things going slightly astray that are not so noticeable (in projects in general, not just FastLED).

Anyway, there are plenty of ways to work around this until Mark is able to return.

Hello @kriegsman . I also ran into this. One thing I have found is that the exact same code loaded through Arduino Create (the web editor) works without the red pixel flash. I noticed that when I uploaded the first time it had to update some drivers on my machine, but that didn’t help the native Arduino client. It still uploads code that has the issue. The code size between the two is different, so that seems in-line with prior findings that things that change the image size seem to matter. I have been trying to compare avrdude.conf and anything else I can think of, but no leads so far.

So, to anyone who is blocked by this, try loading your code through Arduino Create as a possible work around for now.

-Davin

Hi together,

first of all I’d like to thank you for the wonderful FastLED library. I’m using it in “my” MobaLedLib library which could be found here: https://github.com/Hardi-St The library controls the lights and more on a model railway. The functions are described here: https://www.stummiforum.de/viewtopic.php?f=7&t=165060&sd=a&start=0

I have been struggling over the same problem in the function “fill_rainbow()” where a wrong color is generated if hue = 60.

During my investigations I detected a strange behavior. The generated code size differs if the number of leds is changed in the “fill_rainbow()” call: fill_rainbow( leds, 69, hue, 1); => 4786 Bytes No Error fill_rainbow( leds, 70, hue, 1); => 4844 Bytes Error !!

For the tests I use GCC 7.03.00, FastLED version 3.003.002. But the effect is similar with GCC 5.04.00

Next I compared the generated ASM code of the two builds. For some reasons there are a lot of changes in the ASM code. One change may cause the problem. It affects the call to “scale8_LEAVING_R1_DIRTY”. For me it looks like the compiler has changed the sequence of the R1 usage. It’s shown in this picture: https://abload.de/image.php?img=compare_fill_rainbow_afjvu.jpg

Unfortunately I have no experience with the AVR assembler code. I hope that this may help to fix the problem.

Here is the code I use for the tests:

#include <FastLED.h>

#define DATA_PIN 6
#define NUM_LEDS 114
CRGB leds[NUM_LEDS];

uint8_t hue = 59;

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);

  fill_rainbow( leds, 70 /*NUM_LEDS*/, hue, 1);
  for(int i=0; i<NUM_LEDS; i++) {
    Serial.print(i);
    Serial.print(' ');
    Serial.print(leds[i].r);
    Serial.print(' ');
    Serial.print(leds[i].g);
    Serial.print(' ');
    Serial.println(leds[i].b);
  }
  FastLED.show();
  CHSV hsv;
  CRGB rgb;
  //rgb = hsv;
}
/*
    6 LEDs 4786 Bytes No Error
   60 LEDs 4786 Bytes No Error
   65 LEDs 4786 Bytes No Error
   67 LEDs 4786 Bytes No Error
   68 LEDs 4786 Bytes No Error
   69 LEDs 4786 Bytes No Error
   70 LEDs 4844 Bytes Error
   75 LEDs 4844 Bytes Error
   96 LEDs 4844 Bytes Error
*/


void loop() {
//  fill_rainbow( leds, NUM_LEDS, hue, 1);
//  FastLED.show();
}

In my test program I have noticed that the wrong LED could also be pink if NUM_LEDS is modified. RGB values 160 147 0 160 0 160 <= Error pink LED 160 152 0 160 155 0 160 158 0 160 160 0 But I have not been able to generate this failure with the code above.

As a work around I have changed the “hsv.sat = 240;” to 242. This has also been mentioned by jamesgohl.

Hardi