FastLED Speed Difference on Adafruit Flora / Feather M0 Arduino

Hello, I have been testing the same FastLED code on an Adafruit Flora board which seems to work great and an Adafruit Feather M0 which is supposed to be more powerful and a few of the FastLED functions (bpm, juggle, sinelon which all use the beatsin function) seem to be extremely slow. This is connected to a 2m 60led/m strip, so 120leds total.

I've taken out the delay code fully on these functions when running on the Feather and it's still much slower than on the Flora. I can increase the numbers in the beatsin functions to a certain extent to speed them up but even the look or spread of some of the lights like on juggle look different.

Is the best option to just try to tweak the functions individually or is there a more universal way to address the slow down on the Feather?

void fastLEDBpm() {
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
 uint8_t BeatsPerMinute = 64;

  
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}


void fastLEDJuggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}

void fastLEDSinelon() {
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(13,0,NUM_LEDS);
  leds[pos] += CHSV( gHue, 255, 192);
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

      // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  } 
}

Hello, I have been testing the same FastLED code on an Adafruit Flora board which seems to work great and an Adafruit Feather M0 which is supposed to be more powerful and a few of the FastLED functions (bpm, juggle, sinelon which all use the beatsin function) seem to be extremely slow. This is connected to a 2m 60led/m strip, so 120leds total.

The Flora works on 5V, the Feather M0 on 3V3. They cannot have the same circuit. How did you connect the two? Wiring diagram?

This is not complete code, always post complete code!

On AVR boards the FastLED code sometimes uses the hardware to speed up. It doesn't do that on the ARM based boards so this might explain the slow down.

Thanks for the reply. Okay got it, I wasn't aware that those differences would affect the speed of the code.

I had both the Feather and Flora connected to a strip the same way which are powered by USB connection to a computer (- Wire to GND Pin, Data Wire to Pin 6, and + Wire to VBATT Pin on Flora and USB Pin on Feather).

What stood out to me is that it was only those three functions that were slower, everything else was at the same speed. I see the Feather 32u4 uses the same chip as the Flora but it also mentions 3.3V logic so I'm not sure if that would perform like the Flora or the Feather.

Here is the full code in sections as it exceeds the 9000 character limit. It's basically setup to cycle through different effects with a case select upon the press of a button.

Code Part 1:

#include <Adafruit_NeoPixel.h>
#include "FastLED.h"

//Adafruit Library Setup
#define BUTTON_PIN   9    // Digital IO pin connected to the button.  This will be
                          // driven with a pull-up resistor so the switch should
                          // pull the pin to ground momentarily.  On a high -> low
                          // transition the button press logic will execute.

#define PIXEL_PIN    6    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT   120   // Number of LEDs in Strip

// Parameter 1 = number of pixels in strip,  neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct for neopixel stick
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

bool oldState = HIGH;
bool newState = HIGH;
int InLoopPress = 0;
int showType = 0;
int knightRainbowpress = 0;

//FastLED Library Setup
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    6
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    120
CRGB leds[NUM_LEDS];

#define BRIGHTNESS          75
#define FRAMES_PER_SECOND  120


// Main Setup
void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  strip.begin();
  strip.setBrightness(75);
  strip.show(); // Initialize all pixels to 'off'
  Serial.begin(9600);

  delay(500); // 3 second delay for recovery
  
  // tell FastLED about the LED strip configuration
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);  
}

//FastLED Init
// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
//SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns

// Main Loop
void loop() {
  // Start Effect
  startShow(showType);
}

// Checks if button was pressed and changes variable to go to next effect
void checkInLoopPress() {
    newState = digitalRead(BUTTON_PIN);
    if (newState == LOW && oldState == HIGH) {
      InLoopPress = 1; 
      showType++;
      // Change this number according to the number of effects in case switch
      if (showType > 9)
        showType=0; 
     //need this below?
     oldState = newState;
    }
}

// Selects which effect to start
void startShow(int i) {
  switch(i){
    case 0: rainbow(10);
            break;
    case 1: rainbowCycle(10);
            break;
    case 2: fastLEDConfetti(); 
            break; 
    case 3: fastLEDRainbow(); 
            break;      
    case 4: fastLEDRainbowGlitter(); 
            break;    
    case 5: fastLEDBpm(); 
            break; 
    case 6: fastLEDJuggle(); 
            break;  
    case 7: fastLEDSinelon(); 
            break;          
    case 8: fastLEDColorPalette(); 
            break; 
    case 9: theaterChaseRainbow(50); 
            break; 
  }
}

// EFFECTS //

// Begin Adafruit Functions

// 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);

    // Check for inloop button press (include this to every effect loop)
    oldState = newState;
    checkInLoopPress();
    if (InLoopPress == 1) {
        InLoopPress = 0;
        break;
    }
  }
}

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);

    // Check for inloop button press (include this to every effect loop)
    oldState = newState;
    checkInLoopPress();
    if (InLoopPress == 1) {
        InLoopPress = 0;
        break;
    }
  }
}

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

  for(j=0; j<256*1; 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);
  
    // Check for inloop button press (include this to every effect loop)
    oldState = newState;
    checkInLoopPress();
    if (InLoopPress == 1) {
        InLoopPress = 0;
        break;
    }
  }
}

// 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);
}

// End Adafruit Functions

//FastLED Functions

void fastLEDConfetti() {
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 200, 255);

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  //EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically

        // Check for inloop button press (include this to every effect loop)
      oldState = newState;
      checkInLoopPress();
      if (InLoopPress == 1) {
          InLoopPress = 0;
      }      
}

void fastLEDRainbow() {
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}


void fastLEDRainbowGlitter() {
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
  // variable to set chance of glittler 
  if( random8() < 80) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}

Code Part 2:

void fastLEDBpm() {
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
 uint8_t BeatsPerMinute = 64;

  
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}


void fastLEDJuggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  }      
}

void fastLEDSinelon() {
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(13,0,NUM_LEDS);
  leds[pos] += CHSV( gHue, 255, 192);
  
  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 
  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

      // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  } 
}

void theaterChaseRainbow(int SpeedDelay) {
  byte *c;
  
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < NUM_LEDS; i=i+3) {
          c = fastLEDWheel( (i+j) % 255);
          fastLEDsetPixel(i+q, *c, *(c+1), *(c+2));    //turn every third pixel on
        }
        fastLEDshowStrip();
        delay(SpeedDelay);
  
        for (int i=0; i < NUM_LEDS; i=i+3) {
          fastLEDsetPixel(i+q, 0,0,0);        //turn every third pixel off
        }
    }
    
    // Check for inloop button press (include this to every effect loop)
    oldState = newState;
    checkInLoopPress();
    if (InLoopPress == 1) {
        InLoopPress = 0;
        break;
    }
  }
}

byte * fastLEDWheel(byte WheelPos) {
  static byte c[3];
  
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

void fastLEDshowStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void fastLEDsetPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H 
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

Code Part 3:

// Begin Color Palette Functions

#define UPDATES_PER_SECOND 100

// Gradient palette "bhw1_05_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_05.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 8 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw1_05_gp ) {
    0,   1,221, 53,
  255,  73,  3,178};


// Gradient palette "bhw1_06_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_06.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 16 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw1_06_gp ) {
    0, 184,  1,128,
  160,   1,193,182,
  255, 255,255,255};

// Gradient palette "bhw1_purplered_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_purplered.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 8 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw1_purplered_gp ) {
    0, 255,  0,  0,
  255, 107,  1,205};

// Gradient palette "bhw2_50_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw2/tn/bhw2_50.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw2_50_gp ) {
    0,   8,  2, 23,
   84,  47,  7,102,
  138,  16, 46,147,
  173,   2,127,203,
  255,   1,  7, 11};

// Gradient palette "bhw1_28_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw1/tn/bhw1_28.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw1_28_gp ) {
    0,  75,  1,221,
   30, 252, 73,255,
   48, 169,  0,242,
  119,   0,149,242,
  170,  43,  0,242,
  206, 252, 73,255,
  232,  78, 12,214,
  255,   0,149,242};

// Gradient palette "bhw3_61_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw3/tn/bhw3_61.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw3_61_gp ) {
    0,  14,  1, 27,
   48,  17,  1, 88,
  104,   1, 88,156,
  160,   1, 54, 42,
  219,   9,235, 52,
  255, 139,235,233};

// Gradient palette "bhw4_099_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/bhw/bhw4/tn/bhw4_099.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 48 bytes of program space.

DEFINE_GRADIENT_PALETTE( bhw4_099_gp ) {
    0, 249, 32,145,
   28, 208,  1,  7,
   43, 249,  1, 19,
   56, 126,152, 10,
   73, 234, 23, 84,
   89, 224, 45,119,
  107, 232,127,158,
  127, 244, 13, 89,
  150, 188,  6, 52,
  175, 177, 70, 14,
  221, 194,  1,  8,
  255, 112,  0,  1};



// This example shows how to cross-fade between different color palettes
// using the function nblendPaletteTowardPalette.
//
// The basic idea is that you always have a "current palette" that you're
// pulling colors from with ColorFromPalette, and you have a "target palette"
// which is the 'next' palette that you want to get to.
// 
// After that, implementation is relatively simple: just periodically call
//   nblendPaletteTowardPalette( currentPalette, targetPalette);
// If the current palette is not yet equal to the target palette, this 
// function will make a few small changes to the current palette to make
// it slightly more like the target.  Over time, the current palette will
// come to be equal to the target.
// There's no need to test the current and target for equality; it's safe
// to keep calling nblendPaletteTowardPalette even after current reaches target.
// For faster blending, call nblendPaletteTowardPalette twice per loop.

// Initial Palettes
CRGBPalette16 currentPalette( CRGB::Black );
CRGBPalette16 targetPalette( PartyColors_p );

void fastLEDColorPalette()
{
 
  ChangePalettePeriodically();

  // Crossfade current palette slowly toward the target palette
  //
  // Each time that nblendPaletteTowardPalette is called, small changes
  // are made to currentPalette to bring it closer to matching targetPalette.
  // You can control how many changes are made in each call:
  //   - the default of 24 is a good balance
  //   - meaningful values are 1-48.  1=veeeeeeeery slow, 48=quickest
  //   - "0" means do not change the currentPalette at all; freeze
  
  uint8_t maxChanges = 24; 
  nblendPaletteTowardPalette( currentPalette, targetPalette, maxChanges);

  static uint8_t startIndex = 0;
  startIndex = startIndex + 1; /* motion speed */
  FillLEDsFromPaletteColors( startIndex);
  //addGlitter(50);
  FastLED.show();
  FastLED.delay(500 / UPDATES_PER_SECOND);

  // Check for inloop button press (include this to every effect loop)
  oldState = newState;
  checkInLoopPress();
  if (InLoopPress == 1) {
      InLoopPress = 0;
  } 
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
  uint8_t brightness = 255;
  
  for( int i = 0; i < NUM_LEDS; i++) {
    leds[i] = ColorFromPalette( currentPalette, colorIndex + sin8(i*16), brightness);
    colorIndex += 3;
  }
}

void ChangePalettePeriodically()
{
  uint8_t secondHand = (millis() / 1000) % 60;
  static uint8_t lastSecond = 99;
  
  if( lastSecond != secondHand) {
    lastSecond = secondHand;

    // Custom Palette Colors
    CRGB p = CHSV( HUE_PURPLE, 255, 255);
    CRGB g = CHSV( HUE_GREEN, 255, 255);
    CRGB b = CRGB::Black;
    CRGB w = CRGB::White;
    CRGB c1 = CRGB::SlateBlue;
    CRGB c2 = CRGB::Aqua;
    CRGB c3 = CRGB::MediumOrchid;
    CRGB c4 = CRGB::MediumVioletRed;
    CRGB c5 = CRGB::SpringGreen;

    //Custom Palette Colors
    //if( secondHand == 0)  { targetPalette = CRGBPalette16( p,g,b,w, p,g,b,w, p,g,b,w, p,g,b,w); }
    if( secondHand == 0)  { targetPalette = bhw1_05_gp; }
    //if( secondHand == 10)  { targetPalette = bhw3_61_gp; }
    if( secondHand == 10)  { targetPalette = CRGBPalette16( c1,c2,b,c3, b,c2,c1,c4, b,c5,c3,c4, c1,c3,c4,c5); }
    if( secondHand == 20)  { targetPalette = bhw1_28_gp; }
    if( secondHand == 30)  { targetPalette = PartyColors_p; }
    if( secondHand == 40)  { targetPalette = bhw4_099_gp; }
    if( secondHand == 50)  { targetPalette = bhw1_purplered_gp; }
  }
}

void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

// End Color Palette Functions