Creating a 'sparkle' effect for a LED skirt - on/off button help needed

Hi everyone!

First of all - this forum is incredibly helpful! I've spent the last two days trying different codes and learning new packages in Arduino, but I still haven't quite found what I'm looking for.

Objective of project
The goal is to sew 5 connected Neopixel Strands (20 Neopixels each, for a total of 100 Neopixels) into a skirt, using the Flora microcontroller, and create either a steady pulsing (or 'sparkling') effect, which differs across the full length of the strand - so that the lights are not in sync but instead fading in/out each on their own. The colors of the lights just need to be shades of light blue to white, nothing fancy

I've experimented with the Sparkle Skirt tutorial on Adafruit, removing the motion sensor capability (which I couldn't get to work...), and successfully getting one LED to light up at a time, drawing from four random colors. However, any other attempts to either set the other 19 neopixels to the same color (so that the randomly selected one changes colors and then fades back to normal) with for loops and such have not been successful (e.g., the entire strip will change color at once, or the entire strip will stay constant but then the fading looks more 'glitchy' than fading in and out).

An effect like this other 'Sparkle skirt' on Adafruit would be perfect, but without the sound reactivity (going to experiment with it now as I write this).

I've read a few pages with folks looking for something similar, but none of those tutorials have helped yet. So would love a fresh start and pair of eyes on my code.

I think the best, simplest solution might be a code that sets all the strips to a light blue color, and then randomly selects one to fade to a lighter color before returning it to the original color. Ideally, all lights would do this at the same time, but staggered so that it doesn't look like all are lighting up and then back down at the same time.

Here is my code so far. I don't love the blues (and am happy to just have one base or gradient of blues, with the color change being to a lighter blue/white), so open to any ideas where I could: 1) Set a gradient of blues for the entire strand; 2) Set a for loop to randomly select lights to fade 'up' to white and then back down to the original color; 3) Create a larger loop that would tackle all lights at once, at different rates.

THANK YOU :slight_smile:

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

#define LED_PIN   12
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define LED_COUNT    20     // Change this to reflect the number of LEDs you have
#define BRIGHTNESS  250     // Set Brightness here 255

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
CRGB leds[LED_COUNT];

void setup() {
  
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, LED_COUNT);
}

// Here is where you can put in your favorite colors that will appear!
// just add new {nnn, nnn, nnn}, lines. They will be picked out randomly
//                                  R   G   B
uint8_t myFavoriteColors[][3] = {{83,   213, 253},   // teal
                                 {202,   240,   254},   // light blue
                                 {5, 189, 245},   // light blue 
                                 {200, 200, 200},   // white
                               };
// don't edit the line below
#define FAVCOLORS sizeof(myFavoriteColors) / 3

  void loop() {

  for(uint16_t i=0; i<4; i++) {
    // pick a random favorite color!
    int c = random(FAVCOLORS);
    int red = myFavoriteColors[c][0];
    int green = myFavoriteColors[c][1];
    int blue = myFavoriteColors[c][2]; 
    int teal = myFavoriteColors[c][3]; 

    // get a random pixel from the list
    int j = random(strip.numPixels());
    //Serial.print("Lighting up "); Serial.println(j); 
    // now we will 'fade' it in 5 steps
    for (int x=0; x < 5; x++) {
      int r = red * (x+1); r /= 5;
      int g = green * (x+1); g /= 5;
      int b = blue * (x+1); b /= 5;
      int t = teal * (x+1); b /= 5;

      strip.setPixelColor(j, strip.Color(r, g, b));
      
      //for (int k=0; k!=j && k<=LED_COUNT; k++) {
      //strip.setPixelColor(k, strip.Color(r, g, b));
      strip.show();
      delay(100); 
      //}
      
    }
    // & fade out in 5 steps
    for (int x=10; x >= 0; x--) {
      int r = red * x; r /= 10;
      int g = green * x; g /= 10;
      int b = blue * x; b /= 10;
      int t = teal * x; b /= 10;
      strip.setPixelColor(j, strip.Color(r, g, b));
      strip.show();
      delay(100);
    }
    
  }
  // LEDs will be off when done (they are faded to 0)
  }

OK, I see first you do this

uint8_t myFavoriteColors[][3] = {{83,   213, 253},   // teal
                                 {202,   240,   254},   // light blue
                                 {5, 189, 245},   // light blue 
                                 {200, 200, 200},   // white
                               };

and then you are doing this

    int teal = myFavoriteColors[c][3]; 

Oops! You are trying to read past the end of an array, which is a Bad Thing.

Sounds like fun!

When creating gradients, it is often much easier to use the HSV (Hue Saturation Value) or HSL (Hue Saturation Luminance) color spaces, rather than RGB. You can very easily create an HSL gradient, since the hue is blue and the saturation ranges from 0 to 100%.

There are simple functions that translate between the color schemes.

See for example HSL and HSV - Wikipedia

You have it here in your commented-out code... I added "k%256" to the blue and "0" to r and g.

      //for (int k=0; k!=j && k<=LED_COUNT; k++) {
      //strip.setPixelColor(k, strip.Color(0, 0, k%256));
      strip.show();
      delay(100); 
int randomPix = random(NUM_PIX);

If you replace "k" with "randomPix" you will get a random pixel somewhere from #0 to #NUM_PIX

I made this wokwi simulation for a user that disappeared after I finished it... It was to be sewn into a costume that had timed color displays. It is in the shape of a square only because that is the easiest way to see all the pixels. You can see the timing in the "interval.h" file/tab. have fun with it...

1 Like

Hi all! Thanks for the super quick responses :slight_smile:

odometer: good call - I haven't slept in a week and clearly shows. I've updated the array size. However, I was just digging into the fastLED palettes and hues - I think if I could just change the myFavoriteColors to select from the premade CloudColors_p palette, I'd be -so much- happier. I'm trying to sort that out now (which also ties into jremington's suggestion to create a HSL gradient! And agree, it could be a set of blues or just one blue fading to white.)

xfpd - thank you, let me try that out! I grayed it out because it would set everything as blue but then seem to glitch when the selected strand changed colors, and the entire strand seemed 'shaky' in terms of the colors (vs. smooth fading in and out). The original RGB numbers I had were a lighter blue, and the k is still selecting a random pixel out of the total strand of 20 - but will see if the code to select a random pixel helps vs. assigning a pixel.

Thanks for the simulation, that's really cool! I'll try to understand it and get it working.

I am wondering, however, if the simplest solution is just some constant fade throughout the chain with a set hue palette? (like in the second example I shared, where her skirt 'pulses' across Rainbow colors - for me, it would just need to pulse across the Cloud colors. I tried to backwards work out her code but... it ended up being the same code as the one I'm already using :neutral_face: )

Quick update:

  1. I made the changes recommended above (with the array and colors). Progress: Colors are better now; Challenge: 4-5 of the neopixels stayed entirely off.

  2. So I went back and re-read some examples I found earlier - and this Sparkle Fox Christmas tree code is getting me much closer to what I want. The colors are fading in and out and it's a mostly blue palette. I am going to experiment with it to see if I can get more lights filled in at once, and slow down the twinkle.

I would still love an alternative where all the lights are colored along the Cloud blue to white palette and then change colors (in a fading way similar to the FastLED fill_Rainbow command (but with my palette, not rainbow colors). I have some tutorials from their GitHub I'll experiment with now as well. And still need to try xfpd's code, now that my Arduino/MBP/Flora are cooperating again.

Also not sure if this is common, but my little Flora and MacBook Pro had a fight and I had to fully restart Arduino to get anything working again (Arduino claimed that the Flora wasn't plugged in, and unplugging it / plugging it back did not help).

You have these "blues":

{83,   213, 253},   // teal
{202,   240,   254},   // very light blue
{5, 189, 245},   // light blue

To fade from "teal" to "very light blue" you could take the difference of red1 and red2, grn1 and grn2, and blu1 and blu2, then decide if you want to fade "evenly" (same time to fade from rgb1 to rgb2, that is to say, if grn has 5 steps and blu has 25 steps, grn will take 1 step for every 5 blu steps), or "flat" (every color increases at the same time, that is to say, if grn has 5 steps and blu has 25 steps, grn will reach 255 in five steps, while blu has 20 more steps).

I use this line to make "random blues" (bluegreens):

(0, random(128, 256), random(128, 256); // random value min 128 max 255
1 Like

Thank you!!

I think I have it working nicely now, with some tweaks to the shades of blue and then building in the "TwinkleFox" example code from FastLED - it has quite a few pieces of code that allow the colors to be constantly fading in and out across changing hues. The big challenge was getting the max voltage / amps and the hues right to prevent short-circuiting (e.g., with 100 NeoPixels on the Flora, I removed any whites and kept it to grays and blues). It now seems to be running for 5 min+ (now to test it when connected to a battery... :crossed_fingers: )

Adafruit_Neopixel or FastLED have a "max amps" setting so "255,255,255" won't melt the power supply.

One new question - about push buttons!

I now have the code working and pulsating perfectly, and it's not causing any overheat issues. I also successfully soldered the wires to the board yesterday, and all working fine.

What I realized, is that the microcontroller will be tucked away under 2 layers of dress skirt, so a Push button could be an easy way to turn it on and off throughout the day.

I am using the Arduino code [here](https://docs.arduino.cc/built-in-examples/digital/Button/) to program a pushbutton on/off mode. I also found that someone had the same question, in terms of toggling the 'Twinklefox' code on/off here - and they were told to apply an if / else statement to the fastLED.show() statement.

I tried to apply this to my code. However, it keeps 'fritzing' as soon as the code is uploaded (lights will turn red / green / blue - even though red and green aren't in my code; microcontroller will start getting really hot; and I have to restart things multiple times in order for Arduino to see the microcontroller as plugged in to replace the 'faulty' code with my functioning one). I don't want to try / fail too many more times, lest I fry the board. But curious if there's anything obviously wrong with my code, below? I am thinking it could be the ordering of commands with the void loop() structure.

Note, this is just the partial code and does not include the void DrawTwinkles or individual palettes, since those parts of the code are all working and do not necessarily tie to the on/off switch part of the code

#include "FastLED.h"


#define NUM_LEDS      100
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          3.3
#define MAX_MA       2500
#define buttonPin       2
int buttonState=0; 
// variables will change:
// variable for reading the pushbutton status

CRGBArray<NUM_LEDS> leds;

// Overall twinkle speed.
// 0 (VERY slow) to 8 (VERY fast).  
// 4, 5, and 6 are recommended, default is 4.
#define TWINKLE_SPEED 4

// Overall twinkle density.
// 0 (NONE lit) to 8 (ALL lit at once).  
// Default is 5.
#define TWINKLE_DENSITY 6

// How often to change color palettes.
#define SECONDS_PER_PALETTE  60

CRGB gBackgroundColor = CRGB::Black; 

// If AUTO_SELECT_BACKGROUND_COLOR is set to 1,
// then for any palette where the first two entries 
// are the same, a dimmed version of that color will
// automatically be used as the background color.
#define AUTO_SELECT_BACKGROUND_COLOR 1

#define COOL_LIKE_INCANDESCENT 0

CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip);
  chooseNextColorPalette(gTargetPalette);
  pinMode(buttonPin,INPUT);
  pinMode(DATA_PIN, OUTPUT);
}


void loop()
{
  
  EVERY_N_SECONDS( SECONDS_PER_PALETTE ) { 
    chooseNextColorPalette( gTargetPalette ); 
  }
  
  EVERY_N_MILLISECONDS( 10 ) {
    nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12);
  }

  
buttonState = digitalRead(buttonPin);
if(buttonState==HIGH)
{
  digitalWrite(DATA_PIN, HIGH); 
  drawTwinkles( leds);
  FastLED.show()]
}
// digitalWrite(DATA_PIN,HIGH)
else{ 
  digitalWrite(DATA_PIN, LOW); 
}
  
}

Sounds like a drain on the microcontoller when power is being applied to the Neopixel... do you have your Neopixel hardware connected with a 300 ohm (current limiting) resistor on the data pin and a 1000uF capacitor across power and ground?

As far as a pushbutton, here is the classic "debounce" using changing states (pressed to released) and millis() for debounce timeout.

byte buttonPin = 2;
unsigned long timer, timeout = 50;
bool currentButtonState, lastButtonRead;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP); // oops... I forgot this line
}

void loop() {
  readButton(); // put the pushbutton-read in a function
}

void readButton() {
  bool currentButtonRead = digitalRead(buttonPin);  // read button pin

  if (currentButtonRead != lastButtonRead) {        // if button pin reading changes...
    timer = millis();                               // ...start a timer
    lastButtonRead = currentButtonRead;             // ... and store current state
  }

  if ((millis() - timer) > timeout) {                           // if button read change was longer than debounceTimeout
    if (currentButtonState == HIGH && lastButtonRead == LOW) {  // ... and State NOT pressed while Button PRESSED

      callAfunction(); // call a function or make your action here

    }
    currentButtonState = currentButtonRead;  // update button state
  }
}

void callAfunction() {
  Serial.println("Hello? World?");
}

this is not how it should be used

Thank you again for the quick response.

Without the switch code, the lights function normally and can run off of a 3.7v Lithium Ion battery without issues - the microcontroller and the lights do not overheat or show signs of overheating. Given that the lights seem fine (until the pushbutton is introduced), do you think the capacitor for the 3.7V 10050mAh Lithium battery (connected to the JST power portal on the Flora) and / or the resistor are still needed? I could see the resistor being helpful since I'm using a 5v+ strand (even though the lights are dimmed / not white / not always on all at once) with a 3v microcontroller to prevent any drain issues.

To also address any power drain, I set the following limits in the code:

#define VOLTS          3.3
#define MAX_MA       2500

However, the moment I attempt any sort of pushbutton code, and nest the main command into a function, then the lights turn all dim red as soon as the code is uploaded to the Flora (even if it compiles correctly).

I tried your code above, which makes more sense to me than the others I saw, but am still running into the challenge where the LEDs either a) remain off or b) turn dim red once the code is run.

This is the full code I am using. I took the original TwinkleFox code within void loop(){..} and moved them to become the void callAfunction(){...}, which itself contains the function drawTwinkles()

#include "FastLED.h"


#define NUM_LEDS      100
#define LED_TYPE   WS2811
#define COLOR_ORDER   GRB
#define DATA_PIN        6
//#define CLK_PIN       4
#define VOLTS          3.3
#define MAX_MA       2500
#define buttonPin       2
// byte buttonPin = 10;
unsigned long timer, timeout = 50;
bool currentButtonState, lastButtonRead;

CRGBArray<NUM_LEDS> leds;

// Overall twinkle speed.
// 4, 5, and 6 are recommended, default is 4.
#define TWINKLE_SPEED 4

// Overall twinkle density.
// 0 (NONE lit) to 8 (ALL lit at once).  
#define TWINKLE_DENSITY 6

// How often to change color palettes.
#define SECONDS_PER_PALETTE  60
// Also: toward the bottom of the file is an array 
// called "ActivePaletteList" which controls which color
// palettes are used; 

// Background color for 'unlit' pixels
CRGB gBackgroundColor = CRGB::Black; 

#define AUTO_SELECT_BACKGROUND_COLOR 1

#define COOL_LIKE_INCANDESCENT 0

CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;

void setup() {
  delay( 3000 ); //safety startup delay
  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip);
  chooseNextColorPalette(gTargetPalette);
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
}


void loop()
{
  readButton(); // put the pushbutton-read in a function
}

void readButton() {
  bool currentButtonRead = digitalRead(buttonPin);  // read button pin

  if (currentButtonRead != lastButtonRead) {        // if button pin reading changes...
    timer = millis();                               // ...start a timer
    lastButtonRead = currentButtonRead;             // ... and store current state
  }

  if ((millis() - timer) > timeout) {                           // if button read change was longer than debounceTimeout
    if (currentButtonState == HIGH && lastButtonRead == LOW) {  // ... and State NOT pressed while Button PRESSED

      callAfunction(); // call a function or make your action here

    }
    currentButtonState = currentButtonRead;  // update button state
  }
}

void callAfunction() {
  EVERY_N_SECONDS( SECONDS_PER_PALETTE ) { 
    chooseNextColorPalette( gTargetPalette ); 
  }
  
  EVERY_N_MILLISECONDS( 10 ) {
    nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12);
  }

  drawTwinkles( leds);
  
  FastLED.show();
}

//  This function loops over each pixel, calculates the 
//  adjusted 'clock' that this pixel should use, and calls 
//  "CalculateOneTwinkle" on each pixel.  It then displays
//  either the twinkle color of the background color, 
//  whichever is brighter.
void drawTwinkles( CRGBSet& L)
{
  // "PRNG16" is the pseudorandom number generator
  // It MUST be reset to the same starting value each time
  // this function is called, so that the sequence of 'random'
  // numbers that it generates is (paradoxically) stable.
  uint16_t PRNG16 = 11337;
  
  uint32_t clock32 = millis();

  // Set up the background color, "bg".
  // if AUTO_SELECT_BACKGROUND_COLOR == 1, and the first two colors of
  // the current palette are identical, then a deeply faded version of
  // that color is used for the background color
  CRGB bg;
  if( (AUTO_SELECT_BACKGROUND_COLOR == 1) &&
      (gCurrentPalette[0] == gCurrentPalette[1] )) {
    bg = gCurrentPalette[0];
    uint8_t bglight = bg.getAverageLight();
    if( bglight > 64) {
      bg.nscale8_video( 16); // very bright, so scale to 1/16th
    } else if( bglight > 16) {
      bg.nscale8_video( 64); // not that bright, so scale to 1/4th
    } else {
      bg.nscale8_video( 86); // dim, scale to 1/3rd.
    }
  } else {
    bg = gBackgroundColor; // just use the explicitly defined background color
  }

  uint8_t backgroundBrightness = bg.getAverageLight();
  
  for( CRGB& pixel: L) {
    PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
    uint16_t myclockoffset16= PRNG16; // use that number as clock offset
    PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number
    // use that number as clock speed adjustment factor (in 8ths, from 8/8ths to 23/8ths)
    uint8_t myspeedmultiplierQ5_3 =  ((((PRNG16 & 0xFF)>>4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;
    uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
    uint8_t  myunique8 = PRNG16 >> 8; // get 'salt' value for this pixel

    // We now have the adjusted 'clock' for this pixel, now we call
    // the function that computes what color the pixel should be based
    // on the "brightness = f( time )" idea.
    CRGB c = computeOneTwinkle( myclock30, myunique8);

    uint8_t cbright = c.getAverageLight();
    int16_t deltabright = cbright - backgroundBrightness;
    if( deltabright >= 32 || (!bg)) {
      // If the new pixel is significantly brighter than the background color, 
      // use the new color.
      pixel = c;
    } else if( deltabright > 0 ) {
      // If the new pixel is just slightly brighter than the background color,
      // mix a blend of the new color and the background color
      pixel = blend( bg, c, deltabright * 8);
    } else { 
      // if the new pixel is not at all brighter than the background color,
      // just use the background color.
      pixel = bg;
    }
  }
}


//  This function takes a time in pseudo-milliseconds,
//  figures out brightness = f( time ), and also hue = f( time )
//  The 'low digits' of the millisecond time are used as 
//  input to the brightness wave function.  
//  The 'high digits' are used to select a color, so that the color
//  does not change over the course of the fade-in, fade-out
//  of one cycle of the brightness wave function.
//  The 'high digits' are also used to determine whether this pixel
//  should light at all during this cycle, based on the TWINKLE_DENSITY.
CRGB computeOneTwinkle( uint32_t ms, uint8_t salt)
{
  uint16_t ticks = ms >> (8-TWINKLE_SPEED);
  uint8_t fastcycle8 = ticks;
  uint16_t slowcycle16 = (ticks >> 8) + salt;
  slowcycle16 += sin8( slowcycle16);
  slowcycle16 =  (slowcycle16 * 2053) + 1384;
  uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);
  
  uint8_t bright = 0;
  if( ((slowcycle8 & 0x0E)/2) < TWINKLE_DENSITY) {
    bright = attackDecayWave8( fastcycle8);
  }

  uint8_t hue = slowcycle8 - salt;
  CRGB c;
  if( bright > 0) {
    c = ColorFromPalette( gCurrentPalette, hue, bright, NOBLEND);
    //if( COOL_LIKE_INCANDESCENT == 1 ) {
    //  coolLikeIncandescent( c, fastcycle8);
    //}
  } else {
    c = CRGB::Black;
  }
  return c;
}


// This function is like 'triwave8', which produces a 
// symmetrical up-and-down triangle sawtooth waveform, except that this
// function produces a triangle wave with a faster attack and a slower decay:
//
//     / \ 
//    /     \ 
//   /         \ 
//  /             \ 
//

uint8_t attackDecayWave8( uint8_t i)
{
  if( i < 86) {
    return i * 3;
  } else {
    i -= 86;
    return 255 - (i + (i/2));
  }
}

// This function takes a pixel, and if its in the 'fading down'
// part of the cycle, it adjusts the color a little bit like the 
// way that incandescent bulbs fade toward 'red' as they dim.
//void coolLikeIncandescent( CRGB& c, uint8_t phase)
//{
//  if( phase < 128) return;

 // uint8_t cooling = (phase - 128) >> 4;
 // c.g = qsub8( c.g, cooling);
 // c.b = qsub8( c.b, cooling * 2);
//}

// A mostly blue palette with white accents.
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM =
{  CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, 
   CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray };

// Cloudy Blue
   const TProgmemRGBPalette16 BlueCloud_p FL_PROGMEM =
{  CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue, 
   CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue,
   CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue, CRGB::DodgerBlue,
   CRGB::DodgerBlue, CRGB::Gray, CRGB::Gray, CRGB::Gray };

// A palette of soft snowflakes with the occasional bright one
const TProgmemRGBPalette16 Snow_p FL_PROGMEM =
{  0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0x304048,
   0x304048, 0x304048, 0x304048, 0xE0F0FF };

// A cold, icy pale blue palette
#define Ice_Blue1 0x0C1040
#define Ice_Blue2 0x182080
#define Ice_Blue3 0x5080C0
const TProgmemRGBPalette16 Ice_p FL_PROGMEM =
{
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
  Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3
};


// Add or remove palette names from this list to control which color
// palettes are used, and in what order.
const TProgmemRGBPalette16* ActivePaletteList[] = {
  //&BlueWhite_p,
  &Snow_p,
  &Ice_p,
  &BlueCloud_p
};


// Advance to the next color palette in the list (above).
void chooseNextColorPalette( CRGBPalette16& pal)
{
  const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]);
  static uint8_t whichPalette = -1; 
  whichPalette = addmod8( whichPalette, 1, numberOfPalettes);

  pal = *(ActivePaletteList[whichPalette]);
}

How is your button wired? "Normal" button wiring is from Arduino pin to button (normally open contact) then button pin to ground. The pinMode is set to INPUT_PULLUP ( pinMode(buttonPin, INPUT_PULLUP). When the button is not pressed, the pin senses HIGH. When the button is pressed, the pin senses LOW.

I am using the adafruit tactile pushbutton, where the button doesn't 'stay' in a set position. I have the button data pin connected to pin 2 and the ground pin connected to the nearest ground pin. I used this same button set up on my Playground Express (hasn't been soldered yet) and just moved it over to the Flora for testing purposes, so there shouldn't be an issue with the wiring.

Please, show your wiring. Maybe that will show a reason for the button issue.


This is the current set up. Included a photograph to show the lights running just fine with the 3.7V battery when the microcontroller has the normal code (no pushbutton) uploaded.

MicroUSB is to just plug into the computer to download code.

I assume this is a 3.3vdc board.
I see the black pushbutton is connected to GND and (pin) #2.

How do you know which is the GND wire and which is the DATA wire with the clear insulation?
Please, check the pushbutton is N.O. (normally open). I suspect is is N.C. (normally closed).

Yes. I have the same tactile switch set up on a different board, and the right wire is the DATA wire and the left wire is the GND wire (I also tested with that same pushbutton set up, since it's easy to move between boards with the alligator clips).

How would I know whether it's NO or NC? This is the exact button I am using. The button is always in the 'up' position and then is clicked 'down', which in my other set up would turn the LEDs on. It then returns to the 'up' position right after, and needs to be clicked again to turn the LEDs off. I got the other code to work in MakeCode for the Playground Express, but needed Arduino to run this code on my Flora - that's why I was able to get the pushbutton code to work before but not now :expressionless:

In case helpful, this is the 'Javascript' version of the MakeCode I created for my other LED project, using the same tactile pushbutton.

let brightness = 0
let strip = light.createStrip(pins.A1, 60)
pins.A4.setPull(PinPullMode.PullUp)
forever(function () {
    if (!(pins.A4.digitalRead())) {
        light.setAll(0x007fff)
        strip.setBrightness(50)
        strip.setGradient(0x00ffff, 0xffffff)
        for (let i = 0; i < 150; i++) {
            strip.setBrightness(brightness)
            brightness += 1
        }
        strip.setBrightness(200)
        pause(200)
        strip.setBrightness(170)
        pause(100)
        strip.setBrightness(200)
        pause(100)
        strip.setBrightness(170)
        for (let i = 0; i < 150; i++) {
            strip.setBrightness(brightness)
            brightness += -1
        }
    } else {
        light.clear()
    }
})