Function to fade an RGB from one color to the next using a Neopixel strip

I have the following function:

MotiColor startColor;
MotiColor endColor;

void setup()
{
    // Begin strip.
    strip.begin();

    // Initialize all pixels to 'off'.
    strip.show();

    Serial1.begin(9600);

    startColor = MotiColor(0, 0, 0);
    endColor = MotiColor(0, 0, 0);
}

void loop () {
}

int tinkerSetColour(String command)
{
    strip.show();

    int commaIndex = command.indexOf(',');
    int secondCommaIndex = command.indexOf(',', commaIndex+1);
    int lastCommaIndex = command.lastIndexOf(',');

    String red = command.substring(0, commaIndex);
    String grn = command.substring(commaIndex+1, secondCommaIndex);
    String blu = command.substring(lastCommaIndex+1);

    startColor = MotiColor(red.toInt(), grn.toInt(), blu.toInt());

    int16_t redDiff = endColor.getR() - startColor.getR();
    int16_t greenDiff = endColor.getG() - startColor.getG();
    int16_t blueDiff = endColor.getB() - startColor.getB();

    int16_t _delay = 500;
    int16_t duration = 3500;
    int16_t steps = duration / _delay;

    int16_t redValue, greenValue, blueValue;

    for (int16_t i = steps; i >= 0; i--) {
        redValue = (int16_t)startColor.getR() + (redDiff * i / steps);
        greenValue = (int16_t)startColor.getG() + (greenDiff * i / steps);
        blueValue = (int16_t)startColor.getB() + (blueDiff * i / steps);

        sprintf(rgbString, "%i,%i,%i", redValue, greenValue, blueValue);
        Spark.publish("rgb", rgbString);

        for (uint16_t i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(redValue, greenValue, blueValue));
        }
        
        delay(_delay);
    }

    delay(_delay);

    for (uint16_t i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(endColor.getR(), endColor.getG(), endColor.getB()));
    }

    delay(_delay);

    endColor = MotiColor(startColor.getR(), startColor.getG(), startColor.getB());

    return 1;
}

I’m trying to fade from one RGB colour to the next.

I am seeing the published results correctly:

This is from OFF (0,0,0) -> RED (255,0,0) -> GREEN (0,255,0).

enter image description here

It works fine when I publish the results back to a web console via the Spark.publish() event, however the actual Neopixel LED’s don’t fade from colour to colour as expected. They just change from colour to colour instead of actually fading.

I’m just wondering where I’m going wrong or how I can improve my code so that I actually see the fading in real time.

Try moving the strip.show(); at the top of int tinkerSetColour(String command) to two places, right before the first and third delay(_delay);

The way the NeoPixel library works is like this…

// These calls just change the RAM associated with each pixel
strip.setPixelColor(i,strip.Color(0,0,0)); 

// This call actually clocks all of the pixel data out, essentially updating the strip each time you call it.
strip.show();

Also be careful not to take up too much time in your tinkerSetColour(String command) function. If you have a lot of pixels and the cumulative delays stack up to somewhere north of 10 seconds you might lose your connection to the Cloud. One way to combat this is to pull your commands in, parse them and save them in global variables that can be accessed in loop(). Then in loop() you can put all of your fading code and instead of using hard delay()'s you can use the millis() counter like so:

if( (millis() - lastUpdate) > DELAY_IN_MS ) {
  // update the colors and strip.show();
}

Here it is in practice… instead of calling rainbow(20); from loop() which blocks loop for a good long time… we can do this:

uint32_t lastPixelUpdate = 0;

void loop(){
  // Taste the rainbow!
  // rainbow(20);
  // Unroll the above line of code to avoid blocking the loop()

  if(millis() - lastPixelUpdate > 20UL) {
    lastPixelUpdate = millis();

    static uint16_t j = 0;
    if(j>256) j=0;
    for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    j++;
    strip.show();
    //no more hard delay
    //delay(wait);
  }
}

Please share your project when you get it working :slight_smile: It looks like it’s going to be awexome!

1 Like