Serial Interrupters for Animation Switching? - Uno, FastLED, && Max for Live

First time poster here as I've been turning over every rock before coming to y'all hat in hand.

Admittedly, I'm quite the noob to Arduino.cc, FastLED, and now C++ so the issue I'm seeking advice in stems from that. Though, as you might see, there's a few pit stops I'll be making in other areas of the code in the near future, I'm sure.

What I'm trying to do:
-Broad Strokes: Control 6 96" self-made LED "bars" via Ableton, launching clips that send a serial buffer via Max for Live to tell Arduino.cc (and FastLED) which of the stored animations to switch to.

-Current Issue: I can switch between animations. My Serial communication is working as expected. However, when I try to switch to another animation while the current one is still playing out, I have to wait for it to finish.

For context, eventually I will also have a Color Palette Selector and global Brightness, Saturation, and Strobe dials (So, 5 dials/"knobs" in total; see code).
At the moment, I'd like to just sort out how to "interrupt" the current Animation when there's been a change in Serial buffer "knob == 0".

Much of the forum focuses on hardware interruptors. I've also tried replacing my "delay()"s with EVERY_N_MILLISECONDS (FastLED). Again, I'm a noob here definitely playing catch up in my studies for this octopus of a project. I've replaced my Animation Scene Selector's "if" statement with a "switch" (that's been nice and clean). But cutting off the animation mid-animation from a serial() change would be a dream come true.

I've included three files:
1.) The relevant piece of code wrapped up in it's own working sketch to give you enough of a taste of what's going on; small scale (including a bit of the Color Palette Selector elements so you can see where it's going - open to advice but should really maybe be linked to a separate CHSV ColorPalette discussion).
2.) The FULL shabang. Working (however there are elements I'm testing, not sure if I'll keep - Quick Patterns? - that I left in in case someone's familiar).
3.) Photo of my M4L Device.

Please let me know if there's a way I can ask for help or provide this information more succinctly in the future. Thank you for any help or guidance in this very big world.

(and for any NIN fans, the first song I'll be covering with this setup is "Into the Void", if you reeeally wanna follow along)

Cheers.

1.) A smaller version of the main project, in order to hone in on my current issue:

#include <FastLED.h>

  #define NUM_LEDS      150
  #define LED_TYPE  WS2812B
  #define COLOR_ORDER   GRB
  #define DATA_PIN1       3     // LED 01 
  #define DATA_PIN2       5     // LED 02
  #define DATA_PIN3       6     // LED 03
  #define DATA_PIN4       9     // LED 04
  #define DATA_PIN5      10     // LED 05
  #define DATA_PIN6      11     // LED 06
  //#define DATA_PIN7       4   // LED RGBW 01
  //#define DATA_PIN8       7   // LED RGBW 02    
  #define BRIGHTNESS     70
  #define VOLTS           5
  #define MAX_MA       5000

  #define UPDATES_PER_SECOND 100

// declare array of CRGB objects, used by FastLED
CRGB leds[NUM_LEDS];

int currentAnimation;
int currentPaletteSelector;
int currentBrightness;
int currentSaturation;
int currentStrobe;
int BPM;

class CRGBPalette16;
class CHSVPalette16;
 
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

void setup() {
  Serial.begin(9600);
  delay(1000); // Recovery delay

  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN1, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN3, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN4, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN5, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better     
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN6, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better   
    .setDither(BRIGHTNESS < 255);
  //FastLED.addLeds<LED_TYPE,DATA_PIN7,COLOR_ORDER>(leds, NUM_LEDS)
  //  .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better   
  //  .setDither(BRIGHTNESS < 255);
  //FastLED.addLeds<LED_TYPE,DATA_PIN8,COLOR_ORDER>(leds, NUM_LEDS)
  //  .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better                    
  //  .setDither(BRIGHTNESS < 255);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();   

}//setup


void loop()
{
  checkForKnob();                             //  this helps to continually check for the Serial, updating the loop, while looping what's been selected (ie knob == 0, value == __)
                                              //    As I understand it, this is my version of "polling", but it still results in animations needing to come to completion before switching to what was pulled.

      switch (currentAnimation) {          
        case 1:
          ncIntoTheVoidstart(); break;
        case 2:
          ncIntoTheVoidstring1(); break;
        case 3:
          ncIntoTheVoidstring2(); break;
        case 4:
          ncIntoTheVoiddrum(); break;
        case 5:
          ncIntoTheVoidINTRO(); break;
                                              //  there are/will be a total of 128 different animations to select from using the first knob ("potentiometer" built in Max for Live 
      }//switch(currentAnimation)             //    that I will be able to turn either by MIDI controller or with envelopes via launchable clips in Ableton's Session view)
}//loop


void checkForKnob()                           //  this helps to continually check for the Serial, updating the loop, while looping what's been selected (ie knob == 0, value == __)
                                              //    As I understand it, this is my version of "polling", but it still results in animations needing to come to completion before switching to what was pulled.
{
  while (Serial.available() >= 2) {
    int knob = Serial.read();                 //  My Max for Live device has 5 adjustable knobs (with a range of value from 1-128 each). I have Max for Live prepending a knob number 
    int value = Serial.read();                //    for each of the knobs so that when a knob sends a value through the serial, it's prefaced by it's assigned knob number.  
                                              //    Arduino then reads the buffered pair - ie. key, value-style - and parces it out here.
    if (knob == 0)  {                         //  Max 4 Live LED Scene/Animation Selector
      currentAnimation = value;
    }
    else if (knob == 1)  {                    //  Max 4 Live Color Palette Selector
      currentPaletteSelector = value;
      if( value == 0) { SetupNCAkira01Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 1) { SetupNCAkira01Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 2) { SetupNCAkira02Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 3) { SetupNCAkira03Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 4) { SetupNCAkira04Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 5) { SetupNCAkira05Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 6) { SetupNCAkira06Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 7) { SetupNCAkira07Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 8) { SetupNCAkira08Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 9) { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND;  }
      if( value == 10){ SetupFairyLightPalette();                 currentBlending = LINEARBLEND;  }      
      if( value == 11){ SetupSnowyPalette();                      currentBlending = LINEARBLEND;  }
    }
    else if (knob == 2)  {                    //  Max 4 Live Global Brightness
      currentBrightness = value;
    }
    else if (knob == 3)  {                    //  Max 4 Live Global Saturation
      currentSaturation = value;
    }
    else if (knob == 4)  {                    //  Max 4 Live Global Strobe
      currentStrobe = value;
    }
  }//while(Serial.avialable())
}//checkForKnob


//// "INTO THE VOID" COVER  ////
void ncIntoTheVoidstart() {                                                   // Serial.read(1)
                                                                              //  6 bars (24beats) at 93bpm = 37,200 milliseconds  
// ANIMATION 01: "Traveling Single White Light"
  EVERY_N_MILLISECONDS(1) { 

  // Move a single white led 
  for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
    // Turn our current led on to white, then show the leds
    leds[whiteLed] = CRGB::White;
  
    // Show the leds (only one of which is set to white, from above)
    FastLED.show();

//    checkForKnob();

    // Wait a little bit
//    delay(100);

    // Turn our current led back to black for the next loop around
    leds[whiteLed] = CRGB::Black;
  }//for(whiteLED...)
//    FastLED.show();  
  }//EVERY_N_MILLISECONDS
}//ncIntoTheVoidstart

void ncIntoTheVoidstring1() {                                                   // Serial.read(2)
// ANIMATION 02: "_____"   
  /* This function will turn ON all LEDs with a line swipe animation. */
  for(int i=0; i<NUM_LEDS; i++) {
    leds[i].setRGB(255, 0, 0);
    FastLED.show();
    delay(50);
  }
}

void ncIntoTheVoidstring2() {                                                   // Serial.read(3)
// ANIMATION 03: "_____"     
  EVERY_N_MILLISECONDS(50) {
    // Create a new pixel for led[0]
    leds[0] = CHSV(160, 0, random8(70, 180)); // sets led[0] to a blue hue with zero saturation and a random 256-digit value between 70-180 for brightness
  
    // Copy each pixel to the next one, starting at the far end
    //thereby 'moving' the pattern along the strip
    for (int i = NUM_LEDS - 1; i > 0; i--) {
      leds[i] = leds[i-1];
    }
    FastLED.show();
  }
  EVERY_N_MILLISECONDS(50) {
    // Create a new pixel for led[0]
    leds[0] = CHSV(160, 0, 0);  

    for (int i = NUM_LEDS - 1; i < NUM_LEDS; i++) {
      leds[i] = leds[i+1];
    }
    FastLED.show();
  }

}

void ncIntoTheVoiddrum() {                                                      //Serial.read(4)
// ANIMATION 04: "Swipe Off"      
  /* This function will turn OFF all LEDs with a line swipe animation. NOTE: Try switching `NUM_LEDS` and `0` for i in the for loop for a different effect. */
  for(int i=0; i<NUM_LEDS; i++) {
    leds[i].setRGB(0, 0, 0);
    FastLED.show();
    delay(50);
  }    

}

void ncIntoTheVoidINTRO() {                                                     //Serial.read(5)
// ANIMATION 05: "_____"     
  fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255)), CHSV(map(142, 0, 359, 0, 255), map(52, 0, 100, 0, 255), map(59, 0, 100, 0, 255)));
  FastLED.show();
  delay(500);
 
  fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(242, 0, 359, 0, 255), map(51, 0, 100, 0, 255), map(24, 0, 100, 0, 255)), CHSV(map(207, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(57, 0, 100, 0, 255)), CHSV(map(311, 0, 359, 0, 255), map(29, 0, 100, 0, 255), map(64, 0, 100, 0, 255)), CHSV(map(152, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(25, 0, 100, 0, 255)));
  FastLED.show();
  delay(500);
  
}



                                                                                ////****    COLOR PALETTE SECTION    ////****      
void SetupBlackAndWhiteStripedPalette()
{
    // 'black out' all 16 palette entries...
    fill_solid( currentPalette, 16, CRGB::Black);
    // and set every fourth one to white.
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;
}

void SetupNCAkira01Palette()
{
CHSV ncAkira01Orange = CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255)); 
CHSV ncAkira01Red = CHSV(map(351, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(78, 0, 100, 0, 255));                                   
CHSV ncAkira01NiteBlue = CHSV(map(242, 0, 359, 0, 255), map(51, 0, 100, 0, 255), map(24, 0, 100, 0, 255));               
CHSV ncAkira01DkBlue = CHSV(map(222, 0, 359, 0, 255), map(57, 0, 100, 0, 255), map(35, 0, 100, 0, 255));                 
CHSV ncAkira01Blue = CHSV(map(207, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(57, 0, 100, 0, 255));                                 
CHSV ncAkira01Teal = CHSV(map(188, 0, 359, 0, 255), map(35, 0, 100, 0, 255), map(65, 0, 100, 0, 255));                              
CHSV ncAkira01LitePurple = CHSV(map(311, 0, 359, 0, 255), map(29, 0, 100, 0, 255), map(64, 0, 100, 0, 255));                                  
CHSV ncAkira01Purple = CHSV(map(264, 0, 359, 0, 255), map(49, 0, 100, 0, 255), map(44, 0, 100, 0, 255));                                 
CHSV ncAkira01ForestGreen = CHSV(map(152, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(25, 0, 100, 0, 255));                  
CHSV ncAkira01Green = CHSV(map(142, 0, 359, 0, 255), map(52, 0, 100, 0, 255), map(59, 0, 100, 0, 255));            


    currentPalette = CRGBPalette16(
                                   ncAkira01Orange,  ncAkira01Red,  ncAkira01Red,  ncAkira01NiteBlue,
                                   ncAkira01DkBlue, ncAkira01Blue, ncAkira01Blue,  ncAkira01Teal,
                                   ncAkira01Teal,  ncAkira01LitePurple,  ncAkira01Purple,  ncAkira01Purple,
                                   ncAkira01ForestGreen, ncAkira01ForestGreen, ncAkira01Green,  ncAkira01Green );

}


void SetupNCAkira02Palette()
{
CHSV ncAkira02RoyalBlue = CHSV(map(225, 0, 359, 0, 255), map(89, 0, 100, 0, 255), map(29, 0, 100, 0, 255));                                           
CHSV ncAkira02Blue = CHSV(map(207, 0, 359, 0, 255), map(58, 0, 100, 0, 255), map(41, 0, 100, 0, 255));                             
CHSV ncAkira02Violet = CHSV(map(313, 0, 359, 0, 255), map(30, 0, 100, 0, 255), map(36, 0, 100, 0, 255));        
CHSV ncAkira02Plum = CHSV(map(330, 0, 359, 0, 255), map(74, 0, 100, 0, 255), map(33, 0, 100, 0, 255));                            
CHSV ncAkira02Burgundy = CHSV(map(3, 0, 359, 0, 255), map(84, 0, 100, 0, 255), map(27, 0, 100, 0, 255));                            
CHSV ncAkira02DkOrange = CHSV(map(15, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(64, 0, 100, 0, 255));     
CHSV ncAkira02NeonOrange = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(99, 0, 100, 0, 255));         
CHSV ncAkira02Orange = CHSV(map(31, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(82, 0, 100, 0, 255));  
CHSV ncAkira02Yellow = CHSV(map(49, 0, 359, 0, 255), map(78, 0, 100, 0, 255), map(73, 0, 100, 0, 255));           

    
    currentPalette = CRGBPalette16(
                                   ncAkira02RoyalBlue,  ncAkira02Blue,  ncAkira02Blue,  ncAkira02Violet,
                                   ncAkira02Plum, ncAkira02Plum, ncAkira02Burgundy,  ncAkira02Burgundy,
                                   ncAkira02DkOrange,  ncAkira02DkOrange,  ncAkira02NeonOrange,  ncAkira02NeonOrange,
                                   ncAkira02Orange, ncAkira02Orange, ncAkira02Yellow,  ncAkira02Yellow );

}

void SetupNCAkira03Palette()
{
CHSV ncAkira03SkinTone = CHSV(map(18, 0, 359, 0, 255), map(39, 0, 100, 0, 255), map(99, 0, 100, 0, 255));
CHSV ncAkira03Orange = CHSV(map(34, 0, 359, 0, 255), map(90, 0, 100, 0, 255), map(99, 0, 100, 0, 255));                      
CHSV ncAkira03Red = CHSV(map(5, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                                  
CHSV ncAkira03DkRed = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(52, 0, 100, 0, 255));                                 
CHSV ncAkira03Burgundy = CHSV(map(355, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(40, 0, 100, 0, 255));                               
CHSV ncAkira03Plum = CHSV(map(322, 0, 359, 0, 255), map(91, 0, 100, 0, 255), map(26, 0, 100, 0, 255));                              
CHSV ncAkira03Purple = CHSV(map(267, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(28, 0, 100, 0, 255));                                   
CHSV ncAkira03Blue = CHSV(map(239, 0, 359, 0, 255), map(62, 0, 100, 0, 255), map(25, 0, 100, 0, 255));                                
CHSV ncAkira03DkBlue = CHSV(map(249, 0, 359, 0, 255), map(77, 0, 100, 0, 255), map(17, 0, 100, 0, 255));                                  
CHSV ncAkira03NtViolet = CHSV(map(276, 0, 359, 0, 255), map(97, 0, 100, 0, 255), map(15, 0, 100, 0, 255));           

    
    currentPalette = CRGBPalette16(
                                   ncAkira03SkinTone,  ncAkira03Orange,  ncAkira03Orange,  ncAkira03Red,
                                   ncAkira03DkRed, ncAkira03Burgundy, ncAkira03Burgundy,  ncAkira03Plum,
                                   ncAkira03Plum,  ncAkira03Purple,  ncAkira03Blue,  ncAkira03Blue,
                                   ncAkira03DkBlue, ncAkira03DkBlue, ncAkira03NtViolet,  ncAkira03NtViolet );

}

void SetupNCAkira04Palette()
{
CHSV ncAkira04Red = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(56, 0, 100, 0, 255));
CHSV ncAkira04Burgundy = CHSV(map(358, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(29, 0, 100, 0, 255));          
CHSV ncAkira04DkGrey = CHSV(map(275, 0, 359, 0, 255), map(35, 0, 100, 0, 255), map(13, 0, 100, 0, 255));           
CHSV ncAkira04DkPurple = CHSV(map(236, 0, 359, 0, 255), map(48, 0, 100, 0, 255), map(27, 0, 100, 0, 255)); 
CHSV ncAkira04Blue = CHSV(map(214, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(45, 0, 100, 0, 255));                     
CHSV ncAkira04LtBlue = CHSV(map(205, 0, 359, 0, 255), map(66, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                        
CHSV ncAkira04Teal = CHSV(map(196, 0, 359, 0, 255), map(58, 0, 100, 0, 255), map(58, 0, 100, 0, 255));                              
CHSV ncAkira04BrtBlue = CHSV(map(200, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                                
CHSV ncAkira04Violet = CHSV(map(326, 0, 359, 0, 255), map(17, 0, 100, 0, 255), map(49, 0, 100, 0, 255));                                
CHSV ncAkira04DkViolet = CHSV(map(334, 0, 359, 0, 255), map(32, 0, 100, 0, 255), map(31, 0, 100, 0, 255));        

    
    currentPalette = CRGBPalette16(
                                   ncAkira04Red,  ncAkira04Burgundy,  ncAkira04Burgundy,  ncAkira04DkGrey,
                                   ncAkira04DkPurple, ncAkira04Blue, ncAkira04Blue,  ncAkira04LtBlue,
                                   ncAkira04LtBlue,  ncAkira04Teal,  ncAkira04BrtBlue,  ncAkira04BrtBlue,
                                   ncAkira04Violet, ncAkira04Violet, ncAkira04DkViolet,  ncAkira04DkViolet );

}

void SetupNCAkira05Palette()
{
CHSV ncAkira05Burgundy = CHSV(map(349, 0, 359, 0, 255), map(93, 0, 100, 0, 255), map(29, 0, 100, 0, 255));
CHSV ncAkira05Red = CHSV(map(0, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(72, 0, 100, 0, 255));     
CHSV ncAkira05Brown = CHSV(map(25, 0, 359, 0, 255), map(47, 0, 100, 0, 255), map(53, 0, 100, 0, 255));                     
CHSV ncAkira05SkinTone = CHSV(map(36, 0, 359, 0, 255), map(38, 0, 100, 0, 255), map(84, 0, 100, 0, 255)); 
CHSV ncAkira05Tan = CHSV(map(47, 0, 359, 0, 255), map(50, 0, 100, 0, 255), map(77, 0, 100, 0, 255));                 
CHSV ncAkira05EggshellWhite = CHSV(map(176, 0, 359, 0, 255), map(6, 0, 100, 0, 255), map(100, 0, 100, 0, 255));
CHSV ncAkira05Teal = CHSV(map(139, 0, 359, 0, 255), map(20, 0, 100, 0, 255), map(79, 0, 100, 0, 255));                
CHSV ncAkira05LtBlue = CHSV(map(174, 0, 359, 0, 255), map(24, 0, 100, 0, 255), map(64, 0, 100, 0, 255));            
CHSV ncAkira05Blue = CHSV(map(189, 0, 359, 0, 255), map(36, 0, 100, 0, 255), map(51, 0, 100, 0, 255));                           
CHSV ncAkira05DkBlue = CHSV(map(210, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(30, 0, 100, 0, 255));      

    
    currentPalette = CRGBPalette16(
                                   ncAkira05Burgundy,  ncAkira05Red,  ncAkira05Red,  ncAkira05Brown,
                                   ncAkira05SkinTone, ncAkira05Tan, ncAkira05Tan,  ncAkira05EggshellWhite,
                                   ncAkira05EggshellWhite,  ncAkira05Teal,  ncAkira05LtBlue,  ncAkira05LtBlue,
                                   ncAkira05Blue, ncAkira05Blue, ncAkira05DkBlue,  ncAkira05DkBlue );

}

void SetupNCAkira06Palette()
{
CHSV ncAkira06NtBlue = CHSV(map(240, 0, 359, 0, 255), map(45, 0, 100, 0, 255), map(22, 0, 100, 0, 255));
CHSV ncAkira06DkBlue = CHSV(map(224, 0, 359, 0, 255), map(46, 0, 100, 0, 255), map(36, 0, 100, 0, 255));                  
CHSV ncAkira06Blue = CHSV(map(191, 0, 359, 0, 255), map(54, 0, 100, 0, 255), map(44, 0, 100, 0, 255));                          
CHSV ncAkira06Teal = CHSV(map(166, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(43, 0, 100, 0, 255));                  
CHSV ncAkira06BrtGreen = CHSV(map(99, 0, 359, 0, 255), map(60, 0, 100, 0, 255), map(55, 0, 100, 0, 255));                 
CHSV ncAkira06Green3 = CHSV(map(114, 0, 359, 0, 255), map(39, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                     
CHSV ncAkira06Green2 = CHSV(map(119, 0, 359, 0, 255), map(31, 0, 100, 0, 255), map(63, 0, 100, 0, 255));                            
CHSV ncAkira06Green1 = CHSV(map(134, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                            
CHSV ncAkira06SkyBlue  = CHSV(map(194, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(95, 0, 100, 0, 255));                                  
CHSV ncAkira06Red = CHSV(map(357, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(55, 0, 100, 0, 255));   

    
    currentPalette = CRGBPalette16(
                                   ncAkira06NtBlue,  ncAkira06DkBlue,  ncAkira06DkBlue,  ncAkira06Blue,
                                   ncAkira06Teal, ncAkira06BrtGreen, ncAkira06BrtGreen,  ncAkira06Green3,
                                   ncAkira06Green3,  ncAkira06Green2,  ncAkira06Green1,  ncAkira06Green1,
                                   ncAkira06SkyBlue, ncAkira06SkyBlue, ncAkira06Red,  ncAkira06Red );

}

void SetupNCAkira07Palette()
{
CHSV ncAkira07DkBurgundy = CHSV(map(353, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(29, 0, 100, 0, 255));
CHSV ncAkira07DkRed = CHSV(map(357, 0, 359, 0, 255), map(92, 0, 100, 0, 255), map(52, 0, 100, 0, 255));                         
CHSV ncAkira07Red = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(84, 0, 100, 0, 255));                               
CHSV ncAkira07Yellow = CHSV(map(61, 0, 359, 0, 255), map(81, 0, 100, 0, 255), map(99, 0, 100, 0, 255));                               
CHSV ncAkira07Grey = CHSV(map(12, 0, 359, 0, 255), map(15, 0, 100, 0, 255), map(65, 0, 100, 0, 255));                               
CHSV ncAkira07LtBlue = CHSV(map(227, 0, 359, 0, 255), map(24, 0, 100, 0, 255), map(79, 0, 100, 0, 255));                               
CHSV ncAkira07Blue = CHSV(map(218, 0, 359, 0, 255), map(48, 0, 100, 0, 255), map(71, 0, 100, 0, 255));                                    
CHSV ncAkira07DkTeal = CHSV(map(196, 0, 359, 0, 255), map(45, 0, 100, 0, 255), map(46, 0, 100, 0, 255));                                
CHSV ncAkira07Green = CHSV(map(138, 0, 359, 0, 255), map(32, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                                       
CHSV ncAkira07Olive = CHSV(map(79, 0, 359, 0, 255), map(33, 0, 100, 0, 255), map(47, 0, 100, 0, 255));

    
    currentPalette = CRGBPalette16(
                                   ncAkira07DkBurgundy,  ncAkira07DkRed,  ncAkira07DkRed,  ncAkira07Red,
                                   ncAkira07Yellow, ncAkira07Grey, ncAkira07Grey,  ncAkira07LtBlue,
                                   ncAkira07LtBlue,  ncAkira07Blue,  ncAkira07DkTeal,  ncAkira07DkTeal,
                                   ncAkira07Green, ncAkira07Green, ncAkira07Olive,  ncAkira07Olive );

}

void SetupNCAkira08Palette()
{
CHSV ncAkira08Black = CHSV(map(341, 0, 359, 0, 255), map(90, 0, 100, 0, 255), map(8, 0, 100, 0, 255));
CHSV ncAkira08Burgundy = CHSV(map(354, 0, 359, 0, 255), map(86, 0, 100, 0, 255), map(27, 0, 100, 0, 255));                         
CHSV ncAkira08DeepRed = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(58, 0, 100, 0, 255));                               
CHSV ncAkira08LtViolet = CHSV(map(256, 0, 359, 0, 255), map(22, 0, 100, 0, 255), map(67, 0, 100, 0, 255));                               
CHSV ncAkira08Violet = CHSV(map(256, 0, 359, 0, 255), map(34, 0, 100, 0, 255), map(53, 0, 100, 0, 255));                               
CHSV ncAkira08DkBlue = CHSV(map(229, 0, 359, 0, 255), map(53, 0, 100, 0, 255), map(33, 0, 100, 0, 255));                               
CHSV ncAkira08ForestGreen = CHSV(map(182, 0, 359, 0, 255), map(54, 0, 100, 0, 255), map(20, 0, 100, 0, 255));                                    
CHSV ncAkira08DkTeal = CHSV(map(177, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(36, 0, 100, 0, 255));                                
CHSV ncAkira08LtGreen  = CHSV(map(104, 0, 359, 0, 255), map(33, 0, 100, 0, 255), map(63, 0, 100, 0, 255));                                       
CHSV ncAkira08Teal = CHSV(map(154, 0, 359, 0, 255), map(42, 0, 100, 0, 255), map(74, 0, 100, 0, 255));

    
    currentPalette = CRGBPalette16(
                                   ncAkira08Black,  ncAkira08Burgundy,  ncAkira08Burgundy,  ncAkira08DeepRed,
                                   ncAkira08LtViolet, ncAkira08Violet, ncAkira08Violet,  ncAkira08DkBlue,
                                   ncAkira08DkBlue,  ncAkira08ForestGreen,  ncAkira08DkTeal,  ncAkira08DkTeal,
                                   ncAkira08LtGreen, ncAkira08LtGreen, ncAkira08Teal,  ncAkira08Teal );

}

// Sets up a pure "fairy light" palette with some brightness variations
void SetupFairyLightPalette()
{
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
    
    currentPalette = CRGBPalette16(
                                   CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, 
                                   HALFFAIRY,        HALFFAIRY,        CRGB::FairyLight, CRGB::FairyLight, 
                                   QUARTERFAIRY,     QUARTERFAIRY,     CRGB::FairyLight, CRGB::FairyLight, 
                                   CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight );

}

// Sets up a palette of soft snowflakes with the occasional bright one
void SetupSnowyPalette()
{
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
    
    currentPalette = CRGBPalette16(
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0xE0F0FF );

}

2.) FULL version:

#include <quickPatterns.h>        //  I'm trying out Quick Patterns.  I don't know much about it just yet but thought 
#include <FastLED.h>              //    I'd include it so you can see where I'm trying to fit it in (which I know is wrong, 
                                  //    so please dismiss anything QuickPAtterns relevent unless you can see how to incorporate that element. I'd like to focus on the "interrupt" issue first and can address that in a separate post if need be)
  #define NUM_LEDS      150
  #define LED_TYPE  WS2812B       // Quick Patterns calls this "CHIPSET" in case it comes up in the transfer of examples
  #define COLOR_ORDER   GRB
  #define DATA_PIN1       3       // LED 01 
  #define DATA_PIN2       5       // LED 02
  #define DATA_PIN3       6       // LED 03
  #define DATA_PIN4       9       // LED 04
  #define DATA_PIN5      10       // LED 05
  #define DATA_PIN6      11       // LED 06
  //#define DATA_PIN7       4       // LED RGBW 01
  //#define DATA_PIN8       7       // LED RGBW 02    
  #define BRIGHTNESS     70
  #define VOLTS           5
  #define MAX_MA       5000       // 500 MA (milli amps) is the conservative maximum for Arduino Uno's 5v USB power supply (.5 amps).  If 5v AC/DC External Power Supply is plugged in, should be 10 AMPS (10,000 milliamps).

  #define UPDATES_PER_SECOND 100

  #define pinHue  
  #define pinSat  
  #define pinVal

  #define TICKLENGTH  20          //Quick Patterns' Ticklelength for example 01 on Documentation


// declare array of CRGB objects, used by FastLED
CRGB leds[NUM_LEDS];

int currentAnimation;
int currentPaletteSelector;
int currentBrightness;
int currentSaturation;
int currentStrobe;
int BPM;

class CRGBPalette16;
class CRGBPalette32;
class CHSVPalette16;
class CHSVPalette32;
 
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

//declare quickPatterns controller and pass in main led array
quickPatterns quickPatterns(leds, NUM_LEDS);

void setup() {
  Serial.begin(9600);
  delay(1000); // Recovery delay

  random16_add_entropy(analogRead(0)); // seed random number generator (Quick Patterns)

  FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
  FastLED.addLeds<LED_TYPE, DATA_PIN1, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN3, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN4, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN5, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better     
    .setDither(BRIGHTNESS < 255);
  FastLED.addLeds<LED_TYPE, DATA_PIN6, COLOR_ORDER>(leds, NUM_LEDS)
    .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better   
    .setDither(BRIGHTNESS < 255);
  //FastLED.addLeds<LED_TYPE,DATA_PIN7,COLOR_ORDER>(leds, NUM_LEDS)
  //  .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better   
  //  .setDither(BRIGHTNESS < 255);
  //FastLED.addLeds<LED_TYPE,DATA_PIN8,COLOR_ORDER>(leds, NUM_LEDS)
  //  .setCorrection(TypicalLEDStrip) // test "TypicalLEDStrip" against "UncorrectedColor" and "TypicalPixelString" to see what you like better                    
  //  .setDither(BRIGHTNESS < 255);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();   

  // ~ Configure quickPatterns......
//  my issue with Quick Patterns.  If I have 70 separate animations, do I really need to call out all 70 scenes individually here, under setup?
}


void loop() {

  checkForKnob();                                   //  this helps to continually check for the Serial, updating the loop, while looping what's been selected (ie knob == 0, value == __)
                                                    //    As I understand it, this is my version of "polling", but it still results in animations needing to come to completion before switching to what was pulled.
  switch (currentAnimation) {          
    case 1:  
      ncIntoTheVoidstart(); break;          
    case 2:
      ncIntoTheVoidstring1(); break;       
    case 3:
      ncIntoTheVoidstring2(); break;
    case 4:
      ncIntoTheVoiddrum(); break;          
    case 5:
      ncIntoTheVoidINTRO(); break;         
    case 6:
      quickPatternCylonExample01(); break;          //  I jump from case 6 to case 128 because I'm building up each scene in the song's animation in order from 1, working up
    case 128:                                       //     and then a library of general/utility animations from the back 128-and-down.      
      AllOff(); break;                      
    case 127:
      AllOn(255, 0, 0); break;             
    case 126:      
      FadeOff(255, 0, 0); break;           
    case 125:      
      FadeOn(255, 0, 0); break;            
    case 124:      
      SwipeOff(0, 0, 0); break;            
    case 123:      
      SwipeOn(255, 255, 255); break;       
    case 122:      
      swirlyTwirlyEffect(); break;         
    case 121:      
      breathingEffect(); break;             
    case 120:      
      pewPewLights(); break;               
    case 119:      
      color1UpColor2Down();  break;        
    case 118:      
      singleBackAndForth(); break;         
    case 117:      
      fillSolidThree(); break;             
    case 116:      
      fillRainbowWindow(); break;          
    case 115:      
      iceBlueGlowUpDown(); break;          
    case 114:      
      fullGradientFlashing(); break;               
    case 113:      
      quickPatternExample01(); break;
                                                //  there are/will be a total of 128 different animations to select from using the first knob ("potentiometer" built in Max for Live 
  }//switch(currentAnimation)                   //    that I will be able to turn either by MIDI controller or with envelopes via launchable clips in Ableton's Session view)
}//loop





void checkForKnob()                             //  this helps to continually check for the Serial, updating the loop, while looping what's been selected (ie knob == 0, value == __)
                                                //    As I understand it, this is my version of "polling", but it still results in animations needing to come to completion before switching to what was pulled.
{
  while (Serial.available() >= 2) {
    int knob = Serial.read();                 //  My Max for Live (M4L) device has 5 adjustable knobs (with a range of value from 1-128 each). I have Max for Live prepending a knob number 
    int value = Serial.read();                //    for each of the knobs so that when a knob sends a value through the serial, it's prefaced by it's assigned knob number.  
                                              //    Arduino then reads the buffered pair - ie. key, value-style - and parces it out here.
    if (knob == 0)  {                         //  M4L LED Scene/Animation Selector
      currentAnimation = value;
    }
    else if (knob == 1)  {                    //  M4L Color Palette Selector
      currentPaletteSelector = value;
      if( value == 0) { SetupNCAkira01Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 1) { SetupNCAkira01Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 2) { SetupNCAkira02Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 3) { SetupNCAkira03Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 4) { SetupNCAkira04Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 5) { SetupNCAkira05Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 6) { SetupNCAkira06Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 7) { SetupNCAkira07Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 8) { SetupNCAkira08Palette();                  currentBlending = LINEARBLEND;  }
      if( value == 9) { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND;  }
      if( value == 10){ SetupFairyLightPalette();                 currentBlending = LINEARBLEND;  }      
      if( value == 11){ SetupSnowyPalette();                      currentBlending = LINEARBLEND;  }
    }
    else if (knob == 2)  {                    //  M4L Global Brightness
      currentBrightness = value;
    }
    else if (knob == 3)  {                    //  M4L Global Saturation
      currentSaturation = value;
    }
    else if (knob == 4)  {                    //  M4L Global Strobe
      currentStrobe = value;
    }
  }
}


//// "INTO THE VOID"  ////
void ncIntoTheVoidstart() {                                                  // 6 bars (24beats) at 93bpm = 37,200 milliseconds  
                                                                             //  Serial.read(1)
// ANIMATION: "Traveling Single White"
  EVERY_N_MILLISECONDS(1) {
//  FastLED.clear();
  // Move a single white led 
  for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
    // Turn our current led on to white, then show the leds
    leds[whiteLed] = CRGB::White;
  
    // Show the leds (only one of which is set to white, from above)
    FastLED.show();

//    checkForKnob();

    // Wait a little bit
//    delay(100);

    // Turn our current led back to black for the next loop around
    leds[whiteLed] = CRGB::Black;
  }
//    FastLED.show();  
  }
}

void ncIntoTheVoidstring1() {                                         // Serial.read(2)
   
// ANIMATION: "Traveling Single White"                                // this animation is the same as the above.  Just wanted to test 
  EVERY_N_MILLISECONDS(1) {                                           //  switching between the same animation to see if i could "interrupt" it...
  // Move a single white led 
  for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
    // Turn our current led on to white, then show the leds
    leds[whiteLed] = CRGB::White;

    // Show the leds (only one of which is set to white, from above)
    FastLED.show();
    checkForKnob();
    // Wait a little bit
//    delay(100);

    // Turn our current led back to black for the next loop around
    leds[whiteLed] = CRGB::Black;
  }
    FastLED.show();  
  }
}

void ncIntoTheVoidstring2() {                                           // Serial.read(3)
//  if I get QuickPatterns to work, try adding the following layer "//" for this scene (ncIntoTheVoidstring2()):
//  quickPatterns.sameLayer().addPreRenderEffect(new qpContinuallyFadeLayerBy(20)); //layer 1 will fade to black by 20/255 once per tick
  
  EVERY_N_MILLISECONDS(50) {
    // Create a new pixel for led[0]
    leds[0] = CHSV(160, 0, random8(70, 180)); // sets led[0] to a blue hue with zero saturation and a random 256-digit value between 70-180 for brightness
  
    // Copy each pixel to the next one, starting at the far end
    //thereby 'moving' the pattern along the strip
    for (int i = NUM_LEDS - 1; i > 0; i--) {
      leds[i] = leds[i-1];
    }
    FastLED.show();
  }
  EVERY_N_MILLISECONDS(50) {
    // Create a new pixel for led[0]
    leds[0] = CHSV(160, 0, 0);  

    for (int i = NUM_LEDS - 1; i < NUM_LEDS; i++) {
      leds[i] = leds[i+1];
    }
    FastLED.show();
  }

}

void ncIntoTheVoiddrum() {                                              //Serial.read(4)
//  ANIMATION 04: "____"
    

}

void ncIntoTheVoidINTRO() {
  //accentColor2_1 = CRGB::Magenta;
  //secondaryColor1 = CRGB::Yellow;
  //ColorPalette ncAkira01Palette(ncAkira01Red, ncAkira01Orange, ncAkira01Orange, ncAkira01NiteBlue, ncAkira01DkBlue, ncAkira01Blue, ncAkira01Blue, ncAkira01Teal, ncAkira01Teal, ncAkira01LitePurple, ncAkira01Purple, ncAkira01Purple, ncAkira01Green, ncAkira01Green, ncAkira01ForestGreen, ncAkira01ForestGreen);
  fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255)), CHSV(map(142, 0, 359, 0, 255), map(52, 0, 100, 0, 255), map(59, 0, 100, 0, 255)));
  FastLED.show();
  delay(500);
 
  fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(242, 0, 359, 0, 255), map(51, 0, 100, 0, 255), map(24, 0, 100, 0, 255)), CHSV(map(207, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(57, 0, 100, 0, 255)), CHSV(map(311, 0, 359, 0, 255), map(29, 0, 100, 0, 255), map(64, 0, 100, 0, 255)), CHSV(map(152, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(25, 0, 100, 0, 255)));
  FastLED.show();
  delay(500);
  
}


void quickPatternCylonExample01()                                      //Serial.read(6)
{
  quickPatternExample01();
  quickPatterns.show();
}



////  BASIC ANIMATIONS /functions  ////
                                                                            ////  https://www.youtube.com/watch?v=DuaK0yV4gA4&t=5s
void AllOff() {
                                                                              // Serial.read(128) =  All Off Effect   
  /* This function will turn OFF all the LEDs. */
  FastLED.clear();
  FastLED.show();
}

void AllOn(int red, int green, int blue) {
                                                                              // Serial.read(127) =  All On Effect
  /* This function will turn ON all the LEDs to a solid color. */
  fill_solid(leds, NUM_LEDS, CRGB(red, green, blue));
  FastLED.show();
}

void FadeOff(int red, int green, int blue) {
                                                                              // Serial.read(126) = Fade Off Effect  
  /* This function will turn OFF all LEDs with a fade animation. NOTE: Color values must be provided as an initial starting point for the animation. */
  float r, g, b;
  for(int i=255; i>=0; i--) {
    r = (i/256.0)*red;
    g = (i/256.0)*green;
    b = (i/256.0)*blue;
    fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
    FastLED.show();
    delay(2);
  }
}

void FadeOn(int red, int green, int blue) {
                                                                              // Serial.read(125) = Fade On Effect  
  /* This function will turn ON all LEDs with a fade animation. */
  float r, g, b;
  for(int i=0; i<=255; i++) {
    r = (i/256.0)*red;
    g = (i/256.0)*green;
    b = (i/256.0)*blue;
    fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
    FastLED.show();
    delay(2);
  }
}

void SwipeOff(int red, int green, int blue) {
                                                                              // Serial.read(124) = Swipe Off Effect
  /* This function will turn OFF all LEDs with a line swipe animation. NOTE: Try switching `NUM_LEDS` and `0` for i in the for loop for a different effect. */
  for(int i=0; i<NUM_LEDS; i++) {
    leds[i].setRGB(0, 0, 0);
    FastLED.show();
    delay(50);
  }
}

void SwipeOn(int red, int green, int blue) {
                                                                              // Serial.read(123) = Swipe On Effect  
  /* This function will turn ON all LEDs with a line swipe animation. */
  for(int i=0; i<NUM_LEDS; i++) {
    leds[i].setRGB(red, green, blue);
    FastLED.show();
    delay(50);
  }
}

////  BASIC ANIMATIONS 2 /functions  ////
                                                                              ////  https://www.youtube.com/watch?v=DKXi1491et8
void swirlyTwirlyEffect() { 
                                                                              // Serial.read(122) = Swirly, twirly EFFECT  
  FastLED.clear();                      
  for (int i=0; i<NUM_LEDS; i++) {
    leds[i] = CRGB(0,255 - 4*i,4*i);
    FastLED.show();
    delay(10); //even shorter delay this time
  }
}

void breathingEffect() { 
                                                                              // Serial.read(121) = Breathing EFFECT
  for (int i=0; i<NUM_LEDS; i++) {
    leds[i] = CRGB::Yellow; 
  }
  for (int i=0; i<BRIGHTNESS; i++) {
    FastLED.setBrightness(i);
    FastLED.show();
    delay(10);
  }
  for (int i=BRIGHTNESS; i>=0; i--) {
    FastLED.setBrightness(i);
    FastLED.show();
    delay(10);
  }

  //decrements down
  for (int i=NUM_LEDS - 1; i>=0; i--) { 
    leds[i] = CRGB::Purple; 
  }
  for (int i=0; i<BRIGHTNESS; i++) {
    FastLED.setBrightness(i);
    FastLED.show();
    delay(10);
  }
  for (int i=BRIGHTNESS; i>=0; i--) {
    FastLED.setBrightness(i);
    FastLED.show();
    delay(10);
  }
}




void pewPewLights() {                                                         // https://www.youtube.com/watch?v=50UeB2GqU-4
                                                                              // Serial.read(120)
  ////////// PEW! PEW! LIGHTS! ////////////////////// (see 2024.10.12)
}




void color1UpColor2Down() {                                                    // https://howtomechatronics.com/tutorials/arduino/how-to-control-ws2812b-individually-addressable-leds-using-arduino/
                                                                               // Serial.read(119)
  for (int i = 0; i <= NUM_LEDS; i++) {
    leds[i] = CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255));           // ncAkira01Orange
    FastLED.show();
    delay(40);
  }
  for (int i = NUM_LEDS; i >= 0; i--) {
    leds[i] = CHSV(map(222, 0, 359, 0, 255), map(57, 0, 100, 0, 255), map(35, 0, 100, 0, 255));           // ncAkira01DkBlue
    FastLED.show();
    delay(40);
  }
}

void singleBackAndForth() {                                                     //  https://fastled.io/docs/_color_palette_8ino-example.html
                                                                                // Serial.read(118)
  for(int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CRGB::Red;
    FastLED.show();
    delay(5);
    leds[i] = CRGB::Black;
  }

  for(int i = NUM_LEDS - 1; i >= 0; i--) {
    leds[i] = CRGB::Red;
    FastLED.show();
    delay(5);
    leds[i] = CRGB::Black;
  }
}                                                                    

void fillSolidThree() {
                                                                                // Serial.read(117)
  fill_solid(leds, NUM_LEDS, CRGB::Red);
  FastLED.show();
  delay(500);

  fill_solid(leds, NUM_LEDS, CRGB::Green);
  FastLED.show();
  delay(500);

  fill_solid(leds, NUM_LEDS, CRGB::Blue);
  FastLED.show();
  delay(500);
}

void fillRainbowWindow() {
                                                                                // Serial.read(116)
  fill_rainbow(leds, NUM_LEDS, 0, 2);
  FastLED.show();
}

void iceBlueGlowUpDown() {
                                                                                // Serial.read(115)
  EVERY_N_MILLISECONDS(70)  {
    // Create a newpixel for led[0]
    leds[0] = CHSV(map(242, 0, 359, 0, 255), random8(), random8(150, 255));  

    // Copy each pixel to the next one, starting at the far end
    // thereby 'moving' the pattern along the strip
    for (int i = NUM_LEDS - 1; i> 0; i--) {
      leds[i] = leds[i - 1];
    }
  }  
    FastLED.show();
}

void fullGradientFlashing() {
                                                                                //  Serial.read(114)  
  fill_gradient_RGB(leds, NUM_LEDS, CRGB::Green, CRGB::Blue);
  FastLED.show();
  delay(100);
 
  fill_gradient_RGB(leds, NUM_LEDS, CRGB::Gray, CRGB::Yellow, CRGB::Blue, CRGB::Orange);
  FastLED.show();
  delay(100);
}


void quickPatternExample01()  {
                                                                                //  Serial.read(113)   
  quickPatterns.setTickMillis(TICKLENGTH); //sets tick length to "__" milliseconds. Updates and changes in quickPatterns operate on a tick system. Each tick, active patterns are drawn and any pending changes processed.
///By default each pattern will update once per tick. This can be changed with the pattern configuration method drawEveryNTicks(), which allows for lowering a patterns render frequency. ie. If you added drawEveryNTicks(2) to the configuration chain, our pulse pattern would then animate at half speed.
  // Cylon of 8 pixels that cycles through the rainbow (layer 0)
  quickPatterns.newScene().addPattern(new qpBouncingBars(8))
    .chooseColorFromPalette(currentPalette, SEQUENTIAL)
    .changeColorEveryNTicks(2);

  // Periodically toss in some lightning flashes at random places along the strand, 10 pixels wide (layer 1)
  quickPatterns.sameScene().addPattern(new qpLightning(10))
      .singleColor(CRGB::White)
      .activatePeriodicallyEveryNTicks(100, 200) // activate at random intervals between 100 and 200 ticks
      .stayActiveForNCycles(2, 4); // each activation will trigger 2 to 4 lightning flashes

}



////****    COLOR PALETTE SECTION    ////****      

void SetupBlackAndWhiteStripedPalette()
{
    // 'black out' all 16 palette entries...
    fill_solid( currentPalette, 16, CRGB::Black);
    // and set every fourth one to white.
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;
}

void SetupNCAkira01Palette()
{
CHSV ncAkira01Orange = CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255)); 
CHSV ncAkira01Red = CHSV(map(351, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(78, 0, 100, 0, 255));                                   
CHSV ncAkira01NiteBlue = CHSV(map(242, 0, 359, 0, 255), map(51, 0, 100, 0, 255), map(24, 0, 100, 0, 255));               
CHSV ncAkira01DkBlue = CHSV(map(222, 0, 359, 0, 255), map(57, 0, 100, 0, 255), map(35, 0, 100, 0, 255));                 
CHSV ncAkira01Blue = CHSV(map(207, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(57, 0, 100, 0, 255));                                 
CHSV ncAkira01Teal = CHSV(map(188, 0, 359, 0, 255), map(35, 0, 100, 0, 255), map(65, 0, 100, 0, 255));                              
CHSV ncAkira01LitePurple = CHSV(map(311, 0, 359, 0, 255), map(29, 0, 100, 0, 255), map(64, 0, 100, 0, 255));                                  
CHSV ncAkira01Purple = CHSV(map(264, 0, 359, 0, 255), map(49, 0, 100, 0, 255), map(44, 0, 100, 0, 255));                                 
CHSV ncAkira01ForestGreen = CHSV(map(152, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(25, 0, 100, 0, 255));                  
CHSV ncAkira01Green = CHSV(map(142, 0, 359, 0, 255), map(52, 0, 100, 0, 255), map(59, 0, 100, 0, 255));            


    currentPalette = CRGBPalette16(
                                   ncAkira01Orange,  ncAkira01Red,  ncAkira01Red,  ncAkira01NiteBlue,
                                   ncAkira01DkBlue, ncAkira01Blue, ncAkira01Blue,  ncAkira01Teal,
                                   ncAkira01Teal,  ncAkira01LitePurple,  ncAkira01Purple,  ncAkira01Purple,
                                   ncAkira01ForestGreen, ncAkira01ForestGreen, ncAkira01Green,  ncAkira01Green );

}


void SetupNCAkira02Palette()
{
CHSV ncAkira02RoyalBlue = CHSV(map(225, 0, 359, 0, 255), map(89, 0, 100, 0, 255), map(29, 0, 100, 0, 255));                                           
CHSV ncAkira02Blue = CHSV(map(207, 0, 359, 0, 255), map(58, 0, 100, 0, 255), map(41, 0, 100, 0, 255));                             
CHSV ncAkira02Violet = CHSV(map(313, 0, 359, 0, 255), map(30, 0, 100, 0, 255), map(36, 0, 100, 0, 255));        
CHSV ncAkira02Plum = CHSV(map(330, 0, 359, 0, 255), map(74, 0, 100, 0, 255), map(33, 0, 100, 0, 255));                            
CHSV ncAkira02Burgundy = CHSV(map(3, 0, 359, 0, 255), map(84, 0, 100, 0, 255), map(27, 0, 100, 0, 255));                            
CHSV ncAkira02DkOrange = CHSV(map(15, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(64, 0, 100, 0, 255));     
CHSV ncAkira02NeonOrange = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(99, 0, 100, 0, 255));         
CHSV ncAkira02Orange = CHSV(map(31, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(82, 0, 100, 0, 255));  
CHSV ncAkira02Yellow = CHSV(map(49, 0, 359, 0, 255), map(78, 0, 100, 0, 255), map(73, 0, 100, 0, 255));           

    
    currentPalette = CRGBPalette16(
                                   ncAkira02RoyalBlue,  ncAkira02Blue,  ncAkira02Blue,  ncAkira02Violet,
                                   ncAkira02Plum, ncAkira02Plum, ncAkira02Burgundy,  ncAkira02Burgundy,
                                   ncAkira02DkOrange,  ncAkira02DkOrange,  ncAkira02NeonOrange,  ncAkira02NeonOrange,
                                   ncAkira02Orange, ncAkira02Orange, ncAkira02Yellow,  ncAkira02Yellow );

}

void SetupNCAkira03Palette()
{
CHSV ncAkira03SkinTone = CHSV(map(18, 0, 359, 0, 255), map(39, 0, 100, 0, 255), map(99, 0, 100, 0, 255));
CHSV ncAkira03Orange = CHSV(map(34, 0, 359, 0, 255), map(90, 0, 100, 0, 255), map(99, 0, 100, 0, 255));                      
CHSV ncAkira03Red = CHSV(map(5, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                                  
CHSV ncAkira03DkRed = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(52, 0, 100, 0, 255));                                 
CHSV ncAkira03Burgundy = CHSV(map(355, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(40, 0, 100, 0, 255));                               
CHSV ncAkira03Plum = CHSV(map(322, 0, 359, 0, 255), map(91, 0, 100, 0, 255), map(26, 0, 100, 0, 255));                              
CHSV ncAkira03Purple = CHSV(map(267, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(28, 0, 100, 0, 255));                                   
CHSV ncAkira03Blue = CHSV(map(239, 0, 359, 0, 255), map(62, 0, 100, 0, 255), map(25, 0, 100, 0, 255));                                
CHSV ncAkira03DkBlue = CHSV(map(249, 0, 359, 0, 255), map(77, 0, 100, 0, 255), map(17, 0, 100, 0, 255));                                  
CHSV ncAkira03NtViolet = CHSV(map(276, 0, 359, 0, 255), map(97, 0, 100, 0, 255), map(15, 0, 100, 0, 255));           

    
    currentPalette = CRGBPalette16(
                                   ncAkira03SkinTone,  ncAkira03Orange,  ncAkira03Orange,  ncAkira03Red,
                                   ncAkira03DkRed, ncAkira03Burgundy, ncAkira03Burgundy,  ncAkira03Plum,
                                   ncAkira03Plum,  ncAkira03Purple,  ncAkira03Blue,  ncAkira03Blue,
                                   ncAkira03DkBlue, ncAkira03DkBlue, ncAkira03NtViolet,  ncAkira03NtViolet );

}

void SetupNCAkira04Palette()
{
CHSV ncAkira04Red = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(56, 0, 100, 0, 255));
CHSV ncAkira04Burgundy = CHSV(map(358, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(29, 0, 100, 0, 255));          
CHSV ncAkira04DkGrey = CHSV(map(275, 0, 359, 0, 255), map(35, 0, 100, 0, 255), map(13, 0, 100, 0, 255));           
CHSV ncAkira04DkPurple = CHSV(map(236, 0, 359, 0, 255), map(48, 0, 100, 0, 255), map(27, 0, 100, 0, 255)); 
CHSV ncAkira04Blue = CHSV(map(214, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(45, 0, 100, 0, 255));                     
CHSV ncAkira04LtBlue = CHSV(map(205, 0, 359, 0, 255), map(66, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                        
CHSV ncAkira04Teal = CHSV(map(196, 0, 359, 0, 255), map(58, 0, 100, 0, 255), map(58, 0, 100, 0, 255));                              
CHSV ncAkira04BrtBlue = CHSV(map(200, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                                
CHSV ncAkira04Violet = CHSV(map(326, 0, 359, 0, 255), map(17, 0, 100, 0, 255), map(49, 0, 100, 0, 255));                                
CHSV ncAkira04DkViolet = CHSV(map(334, 0, 359, 0, 255), map(32, 0, 100, 0, 255), map(31, 0, 100, 0, 255));        

    
    currentPalette = CRGBPalette16(
                                   ncAkira04Red,  ncAkira04Burgundy,  ncAkira04Burgundy,  ncAkira04DkGrey,
                                   ncAkira04DkPurple, ncAkira04Blue, ncAkira04Blue,  ncAkira04LtBlue,
                                   ncAkira04LtBlue,  ncAkira04Teal,  ncAkira04BrtBlue,  ncAkira04BrtBlue,
                                   ncAkira04Violet, ncAkira04Violet, ncAkira04DkViolet,  ncAkira04DkViolet );

}

void SetupNCAkira05Palette()
{
CHSV ncAkira05Burgundy = CHSV(map(349, 0, 359, 0, 255), map(93, 0, 100, 0, 255), map(29, 0, 100, 0, 255));
CHSV ncAkira05Red = CHSV(map(0, 0, 359, 0, 255), map(99, 0, 100, 0, 255), map(72, 0, 100, 0, 255));     
CHSV ncAkira05Brown = CHSV(map(25, 0, 359, 0, 255), map(47, 0, 100, 0, 255), map(53, 0, 100, 0, 255));                     
CHSV ncAkira05SkinTone = CHSV(map(36, 0, 359, 0, 255), map(38, 0, 100, 0, 255), map(84, 0, 100, 0, 255)); 
CHSV ncAkira05Tan = CHSV(map(47, 0, 359, 0, 255), map(50, 0, 100, 0, 255), map(77, 0, 100, 0, 255));                 
CHSV ncAkira05EggshellWhite = CHSV(map(176, 0, 359, 0, 255), map(6, 0, 100, 0, 255), map(100, 0, 100, 0, 255));
CHSV ncAkira05Teal = CHSV(map(139, 0, 359, 0, 255), map(20, 0, 100, 0, 255), map(79, 0, 100, 0, 255));                
CHSV ncAkira05LtBlue = CHSV(map(174, 0, 359, 0, 255), map(24, 0, 100, 0, 255), map(64, 0, 100, 0, 255));            
CHSV ncAkira05Blue = CHSV(map(189, 0, 359, 0, 255), map(36, 0, 100, 0, 255), map(51, 0, 100, 0, 255));                           
CHSV ncAkira05DkBlue = CHSV(map(210, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(30, 0, 100, 0, 255));      

    
    currentPalette = CRGBPalette16(
                                   ncAkira05Burgundy,  ncAkira05Red,  ncAkira05Red,  ncAkira05Brown,
                                   ncAkira05SkinTone, ncAkira05Tan, ncAkira05Tan,  ncAkira05EggshellWhite,
                                   ncAkira05EggshellWhite,  ncAkira05Teal,  ncAkira05LtBlue,  ncAkira05LtBlue,
                                   ncAkira05Blue, ncAkira05Blue, ncAkira05DkBlue,  ncAkira05DkBlue );

}

void SetupNCAkira06Palette()
{
CHSV ncAkira06NtBlue = CHSV(map(240, 0, 359, 0, 255), map(45, 0, 100, 0, 255), map(22, 0, 100, 0, 255));
CHSV ncAkira06DkBlue = CHSV(map(224, 0, 359, 0, 255), map(46, 0, 100, 0, 255), map(36, 0, 100, 0, 255));                  
CHSV ncAkira06Blue = CHSV(map(191, 0, 359, 0, 255), map(54, 0, 100, 0, 255), map(44, 0, 100, 0, 255));                          
CHSV ncAkira06Teal = CHSV(map(166, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(43, 0, 100, 0, 255));                  
CHSV ncAkira06BrtGreen = CHSV(map(99, 0, 359, 0, 255), map(60, 0, 100, 0, 255), map(55, 0, 100, 0, 255));                 
CHSV ncAkira06Green3 = CHSV(map(114, 0, 359, 0, 255), map(39, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                     
CHSV ncAkira06Green2 = CHSV(map(119, 0, 359, 0, 255), map(31, 0, 100, 0, 255), map(63, 0, 100, 0, 255));                            
CHSV ncAkira06Green1 = CHSV(map(134, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(70, 0, 100, 0, 255));                            
CHSV ncAkira06SkyBlue  = CHSV(map(194, 0, 359, 0, 255), map(26, 0, 100, 0, 255), map(95, 0, 100, 0, 255));                                  
CHSV ncAkira06Red = CHSV(map(357, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(55, 0, 100, 0, 255));   

    
    currentPalette = CRGBPalette16(
                                   ncAkira06NtBlue,  ncAkira06DkBlue,  ncAkira06DkBlue,  ncAkira06Blue,
                                   ncAkira06Teal, ncAkira06BrtGreen, ncAkira06BrtGreen,  ncAkira06Green3,
                                   ncAkira06Green3,  ncAkira06Green2,  ncAkira06Green1,  ncAkira06Green1,
                                   ncAkira06SkyBlue, ncAkira06SkyBlue, ncAkira06Red,  ncAkira06Red );

}

void SetupNCAkira07Palette()
{
CHSV ncAkira07DkBurgundy = CHSV(map(353, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(29, 0, 100, 0, 255));
CHSV ncAkira07DkRed = CHSV(map(357, 0, 359, 0, 255), map(92, 0, 100, 0, 255), map(52, 0, 100, 0, 255));                         
CHSV ncAkira07Red = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(84, 0, 100, 0, 255));                               
CHSV ncAkira07Yellow = CHSV(map(61, 0, 359, 0, 255), map(81, 0, 100, 0, 255), map(99, 0, 100, 0, 255));                               
CHSV ncAkira07Grey = CHSV(map(12, 0, 359, 0, 255), map(15, 0, 100, 0, 255), map(65, 0, 100, 0, 255));                               
CHSV ncAkira07LtBlue = CHSV(map(227, 0, 359, 0, 255), map(24, 0, 100, 0, 255), map(79, 0, 100, 0, 255));                               
CHSV ncAkira07Blue = CHSV(map(218, 0, 359, 0, 255), map(48, 0, 100, 0, 255), map(71, 0, 100, 0, 255));                                    
CHSV ncAkira07DkTeal = CHSV(map(196, 0, 359, 0, 255), map(45, 0, 100, 0, 255), map(46, 0, 100, 0, 255));                                
CHSV ncAkira07Green = CHSV(map(138, 0, 359, 0, 255), map(32, 0, 100, 0, 255), map(56, 0, 100, 0, 255));                                       
CHSV ncAkira07Olive = CHSV(map(79, 0, 359, 0, 255), map(33, 0, 100, 0, 255), map(47, 0, 100, 0, 255));

    
    currentPalette = CRGBPalette16(
                                   ncAkira07DkBurgundy,  ncAkira07DkRed,  ncAkira07DkRed,  ncAkira07Red,
                                   ncAkira07Yellow, ncAkira07Grey, ncAkira07Grey,  ncAkira07LtBlue,
                                   ncAkira07LtBlue,  ncAkira07Blue,  ncAkira07DkTeal,  ncAkira07DkTeal,
                                   ncAkira07Green, ncAkira07Green, ncAkira07Olive,  ncAkira07Olive );

}

void SetupNCAkira08Palette()
{
CHSV ncAkira08Black = CHSV(map(341, 0, 359, 0, 255), map(90, 0, 100, 0, 255), map(8, 0, 100, 0, 255));
CHSV ncAkira08Burgundy = CHSV(map(354, 0, 359, 0, 255), map(86, 0, 100, 0, 255), map(27, 0, 100, 0, 255));                         
CHSV ncAkira08DeepRed = CHSV(map(0, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(58, 0, 100, 0, 255));                               
CHSV ncAkira08LtViolet = CHSV(map(256, 0, 359, 0, 255), map(22, 0, 100, 0, 255), map(67, 0, 100, 0, 255));                               
CHSV ncAkira08Violet = CHSV(map(256, 0, 359, 0, 255), map(34, 0, 100, 0, 255), map(53, 0, 100, 0, 255));                               
CHSV ncAkira08DkBlue = CHSV(map(229, 0, 359, 0, 255), map(53, 0, 100, 0, 255), map(33, 0, 100, 0, 255));                               
CHSV ncAkira08ForestGreen = CHSV(map(182, 0, 359, 0, 255), map(54, 0, 100, 0, 255), map(20, 0, 100, 0, 255));                                    
CHSV ncAkira08DkTeal = CHSV(map(177, 0, 359, 0, 255), map(68, 0, 100, 0, 255), map(36, 0, 100, 0, 255));                                
CHSV ncAkira08LtGreen  = CHSV(map(104, 0, 359, 0, 255), map(33, 0, 100, 0, 255), map(63, 0, 100, 0, 255));                                       
CHSV ncAkira08Teal = CHSV(map(154, 0, 359, 0, 255), map(42, 0, 100, 0, 255), map(74, 0, 100, 0, 255));

    
    currentPalette = CRGBPalette16(
                                   ncAkira08Black,  ncAkira08Burgundy,  ncAkira08Burgundy,  ncAkira08DeepRed,
                                   ncAkira08LtViolet, ncAkira08Violet, ncAkira08Violet,  ncAkira08DkBlue,
                                   ncAkira08DkBlue,  ncAkira08ForestGreen,  ncAkira08DkTeal,  ncAkira08DkTeal,
                                   ncAkira08LtGreen, ncAkira08LtGreen, ncAkira08Teal,  ncAkira08Teal );

}

// Sets up a pure "fairy light" palette with some brightness variations
void SetupFairyLightPalette()
{
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
    
    currentPalette = CRGBPalette16(
                                   CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, 
                                   HALFFAIRY,        HALFFAIRY,        CRGB::FairyLight, CRGB::FairyLight, 
                                   QUARTERFAIRY,     QUARTERFAIRY,     CRGB::FairyLight, CRGB::FairyLight, 
                                   CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight );

}

// Sets up a palette of soft snowflakes with the occasional bright one
void SetupSnowyPalette()
{
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
    
    currentPalette = CRGBPalette16(
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0x304048,
                                   0x304048, 0x304048, 0x304048, 0xE0F0FF );

}


3.) Max for Live Device (the window in the center):

The main trick is that the animations that you want to stop need to relinquish control early.

Would adding a control-relinquishment test and break like this help speed things along?

if(Serial.available()) break;

as in:

void ncIntoTheVoiddrum() {                                                      //Serial.read(4)
// ANIMATION 04: "Swipe Off"      
  /* This function will turn OFF all LEDs with a line swipe animation. NOTE: Try switching `NUM_LEDS` and `0` for i in the for loop for a different effect. */
  for(int i=0; i<NUM_LEDS; i++) {
    leds[i].setRGB(0, 0, 0);
    FastLED.show();
    if(Serial.available()) break; // abort early
    delay(50);
  }    
}
1 Like

Sure. All for-loops run from start-number to end-number except you "break-out" with the command

break;

a variant would be to use while-loops that check for

while (Serial.available()  == 0 && i < NUM_LEDS ) {

}

where Serial.available() returns the number of bytes in the serial-rx-buffer
This numbers of bytes is zero as long as nothing is received new over the serial connection and counts up with every byte received.

When receiving and then processing serial received bytes,
You have to make sure that you have read all bytes from the serial interface to obtain a zero.

2 Likes

Adafruit addresses this in Part 3 of their Multi-tasking the Arduino Series.

2 Likes

I have looked into the uses of millis() in combination with classes/inheritance, my issue is that if you look at my checkForKnob() function in the FULL sketch - I'm using FastLED, not Adafruit, so some of the class/variable referrals are different than "Adafruit-MultiTasking...Part 3"'s full example, nonethelesss...), I'm looking to use a change in Serial value to determine switching patterns, not an amount of time that's passed since ____, relative to millis(). Unless you're suggesting I wrap my currentAnimation switch in a rapid millis() tracker to see if there's been a switch. Does this listen for Serial changes during a selected "case" pattern where my while (Serial.available() >= 2){} is not?

I've seen soooo many examples of what they're mapping out in all of Part 3 but none of my attempts with that structure result in me controlling those changes with Serial buffers I'm passing in, they all rely on millis().

How might you translate constantly checking to see if an amount of time has passed (like the linked tutorial and so many of the others) to checking to see if the value under "knob 0" has changed in the middle of a pattern?

What I'm trying to do also differs from the many examples that show how to do this with hardware (ie. buttons/AnalogIn like the above Part 3 example and others I've seen).

My checkForKnob() function does what it needs to do in pulling the state of the knobs, it just doesn't interrupt after seeing value has changed, yet.

Thank you DaveX! This worked great for functions where I had a for-loop with a delay(). I unfortunately couldn't figure out how to make it work in an EVERY_N_MILLISECONDS{} function (trying to get rid of delay()). Is there a way to break out of non-loops/switches? This is what I'm getting the compilation error on:

void ncIntoTheVoidINTRO() {
                                                                              //Serial.read(5)
  EVERY_N_MILLISECONDS(500) {
    fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(28, 0, 359, 0, 255), map(100, 0, 100, 0, 255), map(85, 0, 100, 0, 255)), CHSV(map(142, 0, 359, 0, 255), map(52, 0, 100, 0, 255), map(59, 0, 100, 0, 255)));  
    FastLED.show();
    // while (Serial.available() > 0) {
    //   Serial.read();
    // }
    if(Serial.available()) break;                            //  abort early

  }//EVERY_N_MILLI

  EVERY_N_MILLISECONDS(1000) { 
    fill_gradient_RGB(leds, NUM_LEDS, CHSV(map(242, 0, 359, 0, 255), map(51, 0, 100, 0, 255), map(24, 0, 100, 0, 255)), CHSV(map(207, 0, 359, 0, 255), map(56, 0, 100, 0, 255), map(57, 0, 100, 0, 255)), CHSV(map(311, 0, 359, 0, 255), map(29, 0, 100, 0, 255), map(64, 0, 100, 0, 255)), CHSV(map(152, 0, 359, 0, 255), map(59, 0, 100, 0, 255), map(25, 0, 100, 0, 255)));
    FastLED.show();
    // while (Serial.available() > 0) {
    //   Serial.read();
    // }
    if(Serial.available()) break;                            //  abort early

  }//EVERY_N_MILLI
}

I also tried @StefanL38 's fix from above (commented out in the clipped sketch directly above - any thoughts @StefanL38 ?), but I couldn't get it to work as well... @StefanL38 , is this not what my checkForKnob() function (top of loop()) does before the switch statement is called? Would I wrap each EVERY_N_MILLISECONDS in your proposed while(Serial.available()....) and I'm assuming still include my checkForKnob() function at the top?

@DaveX @StefanL38 I tried here to get the "if(Serial.available()) break;" to work, but since it wasn't contained in a loop or switch, I got an error.

I tried while (Serial.available() > 0) {Serial.read()} but it didn't break me out of the loop unfortunately. I wonder if the "while" approach should be taking in both Serial.reads? (one is prepended to the other in a key/value-pair approach, providing a knob int and then a value int associated with that knob; in this case: knob == 0 (so, LED Scene Selector) and value == 117 (fillSolidThree()) or rather, Serial.read(117).

void fillSolidThree() {
                                                                                // Serial.read(117)
  EVERY_N_MILLISECONDS(500)  {
    fill_solid(leds, NUM_LEDS, CRGB::Red);
    FastLED.show();
    // while (Serial.available() > 0) {
    //   Serial.read();
    // }
  }//EVERY_N_MILLI

  EVERY_N_MILLISECONDS(1000)  {
    fill_solid(leds, NUM_LEDS, CRGB::Green);
    FastLED.show();
    // while (Serial.available() > 0) {
    //   Serial.read();
    // }
  }//EVERY_N_MILLI

  EVERY_N_MILLISECONDS(1500)  {
    fill_solid(leds, NUM_LEDS, CRGB::Blue);
    FastLED.show();
    // while (Serial.available() > 0) {
    //     Serial.read();
    // }
  }//EVERY_N_MILLI
}//fillSolidThree()

To break out of a function, you could abort early with "return":

if(Serial.available()) return;"

https://docs.arduino.cc/language-reference/en/structure/control-structure/return/

Although it is possible to escape with break and return, it is better to write the animations to not kneecap the rest of the program by trapping the processor within themselves. The advice to break loops in:

One commonly suggested solution to the responsiveness problem is to check your switches inside your loops and quit the loop if a switch is pressed. The switch check can be neatly combined with the delay. And the loop can be re-written to exit early.

This does make your program more responsive, but there are a couple of fundamental problems with this approach:

  • You are still using delay(), so you still can't do two (or more) patterns at once.
  • And what if you don’t really want to quit? We want a way to remain responsive - without necessarily disturbing the execution of the pattern.

As a general advice: in programming you have to express yourself very precisely.
"the loop" is way too unprecise to exactly know which loop you are meaning.

You seem to look at the code line by line instead of looking for functional blocks of code.

You have a fundamental misunderstanding of what

  • a while-loop does
  • what break does

a while-loop does what its name says: LOOPING
repeat the lines of code INSIDE the while-loop

while (Serial.available > 0) { // <= OPENING curly brace
    // the lines
    // of code 
    // that shall be executed
    // again, and again, and again and again and again .......
    // as long as
    // the condition
    // ( Serial.available > 0 )  is true)
} // <= CLOSING curly brace

You could see the loop as a prison: stay INSIDE the loop until the condition becomes false.

break; does what its name says: BREAK
in the sense of breaking out BEFORE the "standard" condition becomes false

the (macro)-function EVERY_N_MILLISECONDS()
does what its name says

only EVERY_N_MILLISECONDS() execute the lines of code INSIDE the curly braces

EVERY_N_MILLISECONDS(1000) { // <= OPENING curly brace
     // the lines of code
     // that get only executed 
     // ONCE
     // every 1000 millisecons
} // <== CLOSING curly brace

I highly recommend:
If you want to do so many modifications of an existing code you should really learn the basics of programming in C++

Here are some graphics that show the basic principle how to write always responsive code

quoting from
Part 3 of their Multi-tasking the Arduino Series

Thinking outside the loop:

It is possible to solve all these problems. But we will need to both ditch the delay and lose the loop. The good news is, the resulting code is surprisingly simple.

The main takeaway from the Adafruit article is not FastLED vs Neopixel, millis() vs switches or classes / inheritance, etc. It's what the article refers to as " Deconstructing the Loop". Read that section again and "Thinking outside the loop". As its says, you will need to "ditch the delay and lose the loop".

@DaveX also pointed this out in Post #8 where, as a hint to you, he quoted directly from the Adafruit article.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.