Search code examples
c++arduinorgbled

Neopixel arduino fading from colour to colour using a Sparkcore


This question is a follow from another question I asked here that was answered.

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 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 fading nicely between themselves.

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.


Solution

  • You have to call strip.show() in your for loop, like so:

    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));
        }
    
    
    
        // !!! Without this, you'll only see the result the next time you call
        // tinkerSetColor() !!!
        strip.show();
    
    
    
        delay(_delay);
    }
    

    To understand what's happening, you can look at the NeoPixel library source. You'll see that strip.setPixelColor() only stores the RGB value in memory (think of it as a drawing buffer, so that you can update the whole strip at once, which makes sense if you look at how the controller chips work). Calling strip.show() causes the routine that will push the values out to each pixel in serial to run.