/* * seirlight led lighting effects for FastLED. * * By: Andrew Tuline * Date: March, 2017 * URL: www.tuline.com * Email: atuline@gmail.com * GitHub: https://github.com/atuline * Pastebin: http://pastebin.com/u/atuline * Youtube: https://www.youtube.com/user/atuline/videos * * * CAUTION ************************************************************************************************************************************************ * * Before attempting to compile this routine, make sure you are already comfortable modifying Arduino Code and FastLED code in particular. In addition, you * should already be able to download, install and use 3rd party libraries. If you are a beginner, this is NOT the code you're looking for. * * ******************************************************************************************************************************************************** * * * Introduction * * This is a significant re-write of my previous aalight program and provides the following: * * - Uses an Arduino microcontroller. * - Uses the FastLED display library. * - Supports multiple display sequences, most with support for multiple settings. * - Supports IR (Infra Red) communications for control of the display sequences. * - Supports keyboard communications for control of the display sequences. * - Supports a button for 3 functions. * - Can support APA102 and WS2801 with IR communications. * - Can support WS2812 if NOT using keyboard or IR communications. * - Can save information in EEPROM. * * * Most of these effects assign colours via palettes as opposed to direct CRGB or CHSV assignments. This allows you to swap out colours without having to modify the * underlying effects code. In addition, each of the effects contain very little code (the longest is about 12 lines) and do not employ nested loops or blocking delays. * * * * 1.02 Update * * - Modify 'Set Strand ACTIVE/INACTIVE so that it doesn't halt the display of any of the Arduino's. * * 1.01 Update * * - Small updates/changes. * - Fix StrandID code. * * * 1.00 Updates/changes from aalight: * * - Improve the brightness controls. * - Removed most of the pixel counting or lengthy routines. * - Converted all but the rainbow march sequences for palette support. * - Removed push button and keyboard support. Just focusing on IR support (for 4 pin strands only). * - Removing some IR keypresses, but adding some cool new ones. * - Combine mc demo modes and demo_modeA into a single set of demos. * - Fixed mode rotation along with maximum number of modes for the demo. * - Add eeprom starting mode support. * - Add support for multiple Arduino's, each driving a strand of LED's. This is done with a strandID variable. * - Add eeprom length of strand support (for each strand). * - Add glitter with an IR button press. * - Add palette transitioning. * - Cleanup/localize the variables as much as reasonably possible. * - Review/fix timing of each routine. * - Add ALL required variables for each display mode. * - Add ability to activate ALL of your strands at once (B4, B4). * - Program the random/semi-random palette selection and support fix/on the fly changes. * - Add the real routines with palettes. * - Fix demo mode timing, and increase from 5 to 10 seconds. * - Fixed routine timing issues with EVERY_N_MILLIS. * - Review routines for possible inclusion/removal. * - Final QA test, with an emphasis of "I'm so done with this". * * * Possible Future upgrades: * * - Set a common timebase for multiple Arduino's so they can be 'in sync'. * * * * * Normal operation: * * - Configure and compile seirlight for your type of strand, and pins used (WS2812's don't work with IR and are very unreliable with Keyboard). * - Use the keyboard or IR controller to modify and save the strand length (up to 100) to support your actual strand. * - Set the demorun variable to 0 and compile seirlight, so that the strand does not startup in demo mode. * - As a security measure, set strandActive to 0 and recompile the sketch. Your strand is now inactive until selected with the buttons below, i.e. B1, then A1 are the defaults. * - If you want to support multiple strands, set the strandId for each to match the output of the various buttons on the IR controller (except for B1). * * You'll need to select your strand before it will display anything, which is a nice security feature if someone steals your display. * * * * Hardware Setup * * - The LED data line is connected to pin 12 (changeable). * - The LED clock line is connected to pin 11 (changeable). * - The button currently uses pin 6. * - For IR functionality, connect the data output of a TSOP34838 IR receiver to pin D2 (other TSOP pins are 5V and Gnd). * - If you use WS2812 LED's, then the IR will NOT work while the keyboard is unreliable. See https://github.com/FastLED/FastLED/wiki/Interrupt-problems * - This supports up to 23 strands with up to 100 LED's each currently. You can increase this value by changing MAX_LEDS. * * * EEPROM Functionality * * - We can save the startup display mode in EEPROM. * - We can save the strand length in EEPROM, however the MAXIMUM strand length is pre-defined. We just use lesser value for the array. * * * Multiple Arduino/strand support * * - We can support multiple strands with a strandID. * - We do not save the demo flag in EEPROM. That's modified at compile time. * - Only the IR control supports multiple strands. Keyboard does not. * * Libraries Required * * - FastLED library from https://github.com/FastLED/FastLED * - Nico Hood's IRL library from https://github.com/NicoHood/IRLremote * * * Button Operation * * Click Stop demo mode and advance to the next display mode. * Double-click Stop demo mode and set to mode 0. * Long hold Stop demo mode and write current mode to EEPROM as startup mode. * * * IR Operation * * I'm using a 24 button IR remote like the ones provided with 5V LED strands from China. If you use a different one, you'll need to map * the codes to the modes in the irtest(); routine. I've provided irtest.ino to test this out with. The chart below summarizes the commands. * Button location uses characters as the row, and numbers are the columns, so C2 is the 3rd row, 2nd column. * * * Command IR Button location * -------- ------------------ * Increase brightness A1 * Decrease brightness A2 * Set mode 0 (black) A3 Disables the demo mode. * Toggle demo mode (millis based) A4 It cycles through the routines based on the millis() counter. * * Select Arduino B1 Then press A1 through F4. A1 is the first one. Press B4 twice to activate ALL Arduino's. Corresponds to strandId value. * Decrease strand length B2 The # of LED's programmed are white. * Increase strand length B3 The # of LED's programmed are white. * Save strand length to EEPROM B4 Press this once you have your strand length. * * Enable/disable glitter D1 Toggles glitter. * Decrease display mode D2 Also disables demo mode. * Increase display mode D3 Also disables demo mode. * Save Current mode to EEPROM D4 This will be the startup mode. * * E1 * Direction reverse E2 * Direction forward E3 * E4 * * No palette change F1 Current palette stays fixed. * Random Palette 4 similar colours F2 On the fly palette changes every 5 seconds. * Random Palette 4 F3 On the fly palette changes every 5 seconds. * Random Palette 16 F4 On the fly palette changes every 5 seconds. * * * * Keyboard Operation * * Once you have compiled the source code, you can open up the monitor and enter keyboard commands. Keyboard commands in the monitor mode include: * * * Key Description Arguments Notes * --- ----------- --------- ----------------- * a Set all to one colour by hue 0-255 * b Set brightness 0-255 * c clear strip (set mode 0) n/a * d Set delay variable 0-255 10 is a good value. * e Set display mode previous/next 0/1 Previous = 0, Next = 1. * f Set fixed palette mode (0 to max) 0-255 It's actually modded with gGradientPaletteCount * g Glitter toggle n/a Toggles on/off. * h Set hue variable 0-255 Doesn't do much as most routines no longer use HSV, but rather use palettes. It's here if you need it. * i Similar palette hue 0-255 Set a palette with colours similar to the colour selected. * l Set strip length & write EEPROM 1-255 * m Set display mode 0-255 It's actually modded with maxMode * n Direction toggle n/a Toggles direction for SOME of the routines, like Matrix and one_sin. * p Play mode (fix, seq, shuf) 0-2 * q Return version number n/a * s Set saturation variable 0-255 Doesn't do much as most routines no longer use HSV, but rather use palettes. * t Select palette mode 0 - 3 * u Set sequence duration 1-255 * w Write current mode to EEPROM n/a * * Keyboard Examples: * * m5 // Select mode 5 (with or without spaces separating the command and the argument) * h 80 // Select a hue of 80, which will change the hue of a few modes * * */ /*------------------------------------------------------------------------------------------ --------------------------------------- Start of variables --------------------------------- ------------------------------------------------------------------------------------------*/ #define qsubd(x, b) ((x>b)?wavebright:0) // A digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value. #define qsuba(x, b) ((x>b)?x-b:0) // Unsigned subtraction macro. if result <0, then => 0. #define SEIRLIGHT_VERSION 102 #define buttonPin 6 // input pin to use as a digital input #include "jsbutton.h" // Nice button routine by Jeff Saltzman and is already included here. #include "FastLED.h" // https://github.com/FastLED/FastLED #include "IRLremote.h" // https://github.com/NicoHood/IRLremote #include "EEPROM.h" // This is included with base install #if FASTLED_VERSION < 3001000 #error "Requires FastLED 3.1 or later; check github for latest code." #endif // choose a valid PinInterrupt pin of your Arduino board #define pinIR 2 // I'm using pin D2 #define IRL_BLOCKING true // Serial definition #define SERIAL_BAUDRATE 57600 // Or 115200. #define SERIAL_TIMEOUT 5 // Serial variables byte inbyte; // Serial input byte int thisarg; // Serial input argument // Fixed definitions cannot change on the fly. #define LED_DT 12 // Serial data pin for all strands #define LED_CK 11 // Serial clock pin for WS2801 or APA102 #define COLOR_ORDER BGR // It's GRB for WS2812 #define LED_TYPE APA102 // Alternatively WS2801, or WS2812 #define MAX_LEDS 100 // Maximum number of LED's defined (at compile time). // Initialize changeable global variables. uint8_t NUM_LEDS; // Number of LED's we're actually using, and we can change this only the fly for the strand length. uint8_t max_bright = 255; // Overall brightness definition. It can be changed on the fly. struct CRGB leds[MAX_LEDS]; // Initialize our LED array. CRGBPalette16 currentPalette; // Use palettes instead of direct CHSV or CRGB assignments CRGBPalette16 targetPalette; // Also support smooth palette transitioning TBlendType currentBlending; // NOBLEND or LINEARBLEND // EEPROM location definitions. #define STARTMODE 0 #define STRANDLEN 1 const uint32_t STRANDID = 65280; // This is the same as button A1 and is the id of THIS strand. Change to a different button press as required. bool strandActive = 0; // 0=inactive, 1=active. Must be activated by button press of B1, then A1 (or the appropriate button). bool strandFlag = 0; // Flag to let us know if we're changing the active strand. uint8_t ledMode; // Starting mode is typically 0. uint8_t demorun = 0; // 0 = regular mode, 1 = demo mode, 2 = shuffle mode. uint8_t maxMode = 38; // Maximum number of modes. uint8_t demotime = 10; // Set the length of the demo timer. // temporary variables to save latest IR input uint8_t IRProtocol = 0; uint16_t IRAddress = 0; uint32_t IRCommand = 0; // Generic/shared routine variables ---------------------------------------------------------------------- uint8_t allfreq = 32; // You can change the frequency, thus overall width of bars. uint8_t bgclr = 0; // Generic background colour uint8_t bgbri = 0; // Generic background brightness bool glitter = 0; // Glitter flag uint8_t palchg; // 0=no change, 1=similar, 2=random uint8_t startindex = 0; uint8_t thisbeat; // Standard beat uint8_t thisbright = 0; // Standard brightness uint8_t thiscutoff = 192; // You can change the cutoff value to display this wave. Lower value = longer wave. int thisdelay = 0; // Standard delay uint8_t thisdiff = 1; // Standard palette jump bool thisdir = 0; // Standard direction uint8_t thisfade = 224; // Standard fade rate uint8_t thishue = 0; // Standard hue uint8_t thisindex = 0; // Standard palette index uint8_t thisinc = 1; // Standard incrementer int thisphase = 0; // Standard phase change uint8_t thisrot = 1; // You can change how quickly the hue rotates for this wave. Currently 0. uint8_t thissat = 255; // Standard saturation int8_t thisspeed = 4; // Standard speed change uint8_t wavebright = 255; // You can change the brightness of the waves/bars rolling across the screen. uint8_t xd[MAX_LEDS]; // arrays for the 2d coordinates of any led uint8_t yd[MAX_LEDS]; long summ=0; extern const TProgmemRGBGradientPalettePtr gGradientPalettes[]; // These are for the fixed palettes in gradient_palettes.h extern const uint8_t gGradientPaletteCount; // Total number of fixed palettes to display. uint8_t gCurrentPaletteNumber = 0; // Current palette number from the 'playlist' of color palettes uint8_t currentPatternIndex = 0; // Index number of which pattern is current // Display functions ----------------------------------------------------------------------- // Support functions #include "addglitter.h" #include "make_palettes.h" // Display routines #include "circnoise_pal_1.h" #include "circnoise_pal_2.h" #include "circnoise_pal_3.h" #include "circnoise_pal_4.h" #include "confetti_pal.h" #include "gradient_palettes.h" #include "juggle_pal.h" #include "matrix_pal.h" #include "noise16_pal.h" #include "noise8_pal.h" #include "one_sin_pal.h" #include "rainbow_march.h" #include "serendipitous_pal.h" #include "three_sin_pal.h" #include "two_sin.h" /*------------------------------------------------------------------------------------------ --------------------------------------- Start of code -------------------------------------- ------------------------------------------------------------------------------------------*/ void setup() { Serial.begin(SERIAL_BAUDRATE); // SETUP HARDWARE SERIAL (USB) Serial.setTimeout(SERIAL_TIMEOUT); delay(1000); checkButton(); delay(1000); // Soft startup to ease the flow of electrons. attachInterrupt(digitalPinToInterrupt(pinIR), IRLinterrupt, CHANGE); // IR definition LEDS.setBrightness(max_bright); // Set the generic maximum brightness value. LEDS.addLeds(leds, MAX_LEDS); // APA102 or WS2801 definition // LEDS.addLeds(leds, MAX_LEDS); // WS2812 definition set_max_power_in_volts_and_milliamps(5, 1000); //5V, 1000mA random16_set_seed(4832); // Awesome randomizer of awesomeness random16_add_entropy(analogRead(2)); int ranstart = random16(); Serial.println("---SETUP COMPLETE---"); ledMode = EEPROM.read(STARTMODE); // Location 0 is the starting mode NUM_LEDS = EEPROM.read(STRANDLEN); if(NUM_LEDS >MAX_LEDS) NUM_LEDS = MAX_LEDS; // Location 1 is the number of LED's //strandId = EEPROM.read(STRANDID); // Which strand are we, anyways? currentPalette = CRGBPalette16(CRGB::Black); targetPalette = RainbowColors_p; currentBlending = LINEARBLEND; // This is for Stefan Petrick's Circular Noise routines for (uint8_t i = 0; i < NUM_LEDS; i++) { // precalculate the lookup-tables: uint8_t angle = (i * 256) / NUM_LEDS; // on which position on the circle is the led? xd[i] = cos8( angle ); // corresponding x position in the matrix yd[i] = sin8( angle ); // corresponding y position in the matrix } strobe_mode(ledMode, 1); // Initialize the first sequence } // setup() //------------------MAIN LOOP--------------------------------------------------------------- void loop() { getirl(); // Read a command from the IR LED and process command as required. readbutton(); // Get button input. readkeyboard(); // Get keyboard input. demo_check(); // If we're in demo mode, check the timer to see if we need to increase the strobe_mode value. EVERY_N_MILLISECONDS(50) { // Smooth palette transitioning runs continuously. uint8_t maxChanges = 24; nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); } EVERY_N_SECONDS(5) { // If selected, change the target palette to a random one every 5 seconds. if (palchg == 1) SetupSimilar4Palette(); if (palchg == 2) SetupRandom4Palette(); if (palchg == 3) SetupRandom16Palette(); } EVERY_N_MILLIS_I(thistimer, thisdelay) { // Sets the original delay time. thistimer.setPeriod(thisdelay); // This is how you update the delay value on the fly. strobe_mode(ledMode, 0); // Strobe to display the current sequence, but don't initialize the variables, so mc=0; } if(glitter) addglitter(10); // If the glitter flag is set, let's add some. FastLED.show(); // Power managed display of LED's. } // loop() //-------------------OTHER ROUTINES---------------------------------------------------------- void strobe_mode(uint8_t newMode, bool mc){ // mc stands for 'Mode Change', where mc = 0 is strobe the routine, while mc = 1 is change the routine if(mc) { fill_solid(leds,NUM_LEDS,CRGB(0,0,0)); // Clean up the array for the first time through. Don't show display though, so you may have a smooth transition. Serial.print("Mode: "); Serial.println(ledMode); } switch (newMode) { // First time through a new mode, so let's initialize the variables for a given display. case 0: if(mc) {fill_solid(leds,NUM_LEDS,CRGB(0,0,0));} break; // All off, not animated. case 1: if(mc) {fill_solid(leds, NUM_LEDS,CRGB(255,255,255));} break; // All on, not animated. case 2: if(mc) {thisdelay=10; allfreq=2; thisspeed=1; thatspeed=1; thishue=0; thathue=128; thisdir=0; thisrot=1; thatrot=1; thiscutoff=128; thatcutoff=192;} two_sin(); break; case 3: if(mc) {thisdelay=20; targetPalette=RainbowColors_p; allfreq=4; bgclr=0; bgbri=0; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 4: if(mc) {thisdelay=10; targetPalette = PartyColors_p; palchg=2;} noise8_pal(); break; case 5: if(mc) {thisdelay=10; allfreq=4; thisspeed=-1; thatspeed=0; thishue=64; thathue=192; thisdir=0; thisrot=0; thatrot=0; thiscutoff=64; thatcutoff=192;} two_sin(); break; case 6: if(mc) {thisdelay=20; targetPalette=RainbowColors_p; allfreq=10; bgclr=64; bgbri=4; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 7: if(mc) {thisdelay=10; numdots=2; targetPalette=PartyColors_p; thisfade=16; thisbeat=8; thisbright=255; thisdiff=64;} juggle_pal(); break; case 8: if(mc) {thisdelay=40; targetPalette = LavaColors_p; thisindex=128; thisdir=1; thisrot=0; thisbright=255; bgclr=200; bgbri=6;} matrix_pal(); break; case 9: if(mc) {thisdelay=10; allfreq=6; thisspeed=2; thatspeed=3; thishue=96; thathue=224; thisdir=1; thisrot=0; thatrot=0; thiscutoff=64; thatcutoff=64;} two_sin(); break; case 10: if(mc) {thisdelay=20; targetPalette=RainbowColors_p; allfreq=16; bgclr=0; bgbri=0; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 11: if(mc) {thisdelay=50; mul1=5; mul2=8; mul3=7;} three_sin_pal(); break; case 12: if(mc) {thisdelay=10; targetPalette=ForestColors_p;} serendipitous_pal(); break; case 13: if(mc) {thisdelay=20; targetPalette=LavaColors_p; allfreq=8; bgclr=0; bgbri=4; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 14: if(mc) {thisdelay=10; allfreq=20; thisspeed=2; thatspeed=-1; thishue=24; thathue=180; thisdir=1; thisrot=0; thatrot=1; thiscutoff=64; thatcutoff=128;} two_sin(); break; case 15: if(mc) {thisdelay=50; targetPalette = PartyColors_p; thisindex=64; thisdir=0; thisrot=1; thisbright=255; bgclr=100; bgbri=10;} matrix_pal(); break; case 16: if(mc) {thisdelay=10; targetPalette = OceanColors_p; palchg=1;} noise8_pal(); break; case 17: if(mc) {thisdelay=10; targetPalette=PartyColors_p;} circnoise_pal_2(); break; case 18: if(mc) {thisdelay=20; allfreq=10; thisspeed=1; thatspeed=-2; thishue=48; thathue=160; thisdir=0; thisrot=1; thatrot=-1; thiscutoff=128; thatcutoff=192;} two_sin(); break; case 19: if(mc) {thisdelay=50; mul1=6; mul2=9; mul3=11;} three_sin_pal(); break; case 20: if(mc) {thisdelay=10; thisdir=1; thisrot=1; thisdiff=1;} rainbow_march(); break; case 21: if(mc) {thisdelay=10; thisdir=1; thisrot=2; thisdiff=10;} rainbow_march(); break; case 22: if(mc) {thisdelay=20; hxyinc = random16(1,15); octaves=random16(1,3); hue_octaves=random16(1,5); hue_scale=random16(10, 50); x=random16(); xscale=random16(); hxy= random16(); hue_time=random16(); hue_speed=random16(1,3); x_speed=random16(1,30);} noise16_pal(); break; case 23: if(mc) {thisdelay=20; targetPalette=OceanColors_p; allfreq=6; bgclr=0; bgbri=0; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 24: if(mc) {thisdelay=10; targetPalette=OceanColors_p;} circnoise_pal_4(); break; case 25: if(mc) {thisdelay=20; targetPalette = PartyColors_p; thisinc=1; thishue=192; thissat=255; thisfade=2; thisdiff=32; thisbright=255;} confetti_pal(); break; case 26: if(mc) {thisdelay=10; thisspeed=2; thatspeed=3; thishue=96; thathue=224; thisdir=1; thisrot=1; thatrot=2; thiscutoff=128; thatcutoff=64;} two_sin(); break; case 27: if(mc) {thisdelay=30; targetPalette = ForestColors_p; thisindex=192; thisdir=0; thisrot=0; thisbright=255; bgclr=50; bgbri=0;} matrix_pal(); break; case 28: if(mc) {thisdelay=20; targetPalette=RainbowColors_p; allfreq=20; bgclr=0; bgbri=0; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=224; thisrot=0; thisspeed=4; wavebright=255;} one_sin_pal(); break; case 29: if(mc) {thisdelay=20; targetPalette = LavaColors_p; thisinc=2; thishue=128; thisfade=8; thisdiff=64; thisbright=255;} confetti_pal(); break; case 30: if(mc) {thisdelay=10; targetPalette=PartyColors_p;} circnoise_pal_3(); break; case 31: if(mc) {thisdelay=10; numdots=4; targetPalette=OceanColors_p; thisfade=32; thisbeat=12; thisbright=255; thisdiff=20;} juggle_pal(); break; case 32: if(mc) {thisdelay=30; SetupSimilar4Palette(); allfreq=4; bgclr=64; bgbri=4; thisbright=255; startindex=64; thisinc=2; thiscutoff=224; thisphase=0; thiscutoff=128; thisrot=1; thisspeed=8; wavebright=255;} one_sin_pal(); break; case 33: if(mc) {thisdelay=50; mul1=3; mul2=4; mul3=5;} three_sin_pal(); break; case 34: if(mc) {thisdelay=10; thisdir=-1; thisrot=1; thisdiff=5;} rainbow_march(); break; case 35: if(mc) {thisdelay=10; targetPalette=PartyColors_p;} circnoise_pal_1(); break; case 36: if(mc) {thisdelay=20; targetPalette = ForestColors_p; thisinc=1; thishue=random8(255); thisfade=1; thisbright=255;} confetti_pal(); break; case 37: if(mc) {thisdelay=20; octaves=1; hue_octaves=2; hxy=6000; x=5000; xscale=3000; hue_scale=50; hue_speed=15; x_speed=100;} noise16_pal(); break; case 38: if(mc) {thisdelay=10; targetPalette = LavaColors_p; palchg=0;} noise8_pal(); break; } // switch newMode } // strobe_mode() void demo_check(){ if(demorun) { // Is the demo flag set? If so, let's cycle through them. uint8_t secondHand = (millis() / 1000) % (maxMode*demotime); // Adjust for total time of the loop, based on total number of available modes. static uint8_t lastSecond = 99; // Static variable, means it's only defined once. This is our 'debounce' variable. if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment. lastSecond = secondHand; if(secondHand%demotime==0) { // Every 10 seconds. if(demorun == 2) ledMode = random8(0,maxMode); else { ledMode = secondHand/demotime; } strobe_mode(ledMode,1); // Does NOT reset to 0. } // if secondHand } // if lastSecond } // if demorun } // demo_check() // Turtles all the way down. //----------------- IR Receiver, Keyboard and Button Command Processing --------------------------------------------- void getirl() { // This is the IR function that gets the value and selects/performs command. if (IRProtocol) { if(IRCommand == 64260 || strandFlag == 1) {set_strand();} if (strandActive==1 || IRCommand == 63495) { Serial.print("Command: "); Serial.println(IRCommand); switch(IRCommand) { case 65280: max_bright=min(max_bright*2,255); LEDS.setBrightness(max_bright); break; //a1 - Increase max bright case 65025: max_bright=max(max_bright/2,1); LEDS.setBrightness(max_bright); break; //a2 - Decrease max bright case 64770: demorun = 0; ledMode = 0; strobe_mode(ledMode,1); break; //a3 - Change to mode 0 case 64515: demorun = !demorun; if(demorun) {Serial.println("Demo mode");} else {Serial.println("Not demo mode");} break; //a4 - Toggle demo mode // case 64260: set_strand(); break; //b1 - Write the current # of LED's case 64005: demorun = 0; ledMode = 0; NUM_LEDS--; Serial.print("NUM_LEDS: "); Serial.println(NUM_LEDS); fill_solid(leds,MAX_LEDS,CRGB(0,0,0)); fill_solid(leds,NUM_LEDS,CRGB(255,255,255)); break; //b2 - Decrease # of LED's case 63750: demorun = 0; ledMode = 0; NUM_LEDS++; Serial.print("NUM_LEDS: "); Serial.println(NUM_LEDS); fill_solid(leds,MAX_LEDS,CRGB(0,0,0)); fill_solid(leds,NUM_LEDS,CRGB(255,255,255)); break; //b3 - Increase # of LED's case 63495: EEPROM.write(STRANDLEN,NUM_LEDS); Serial.print("Writing IR: "); Serial.print(NUM_LEDS); Serial.println(" LEDs"); break; //b4 - Here is where we enable or disable a strand from receiving commands case 63240: strobe_mode(9,1); break; //c1 - case 62985: thisdelay++; break; //c2 - thisdelay++; case 62730: thisdelay--; break; //c3 - thisdelay--; case 62475: strobe_mode(12,1); break; //c4 case 62220: glitter = !glitter; Serial.println("Glitter baby!"); break; //d1 - Glitter case 61965: demorun = 0; ledMode=(ledMode-1); if (ledMode==255) ledMode=maxMode; strobe_mode(ledMode,1); break; //d2 - strobe_mode(ledMode--); case 61710: demorun = 0; ledMode=(ledMode+1)%(maxMode+1); strobe_mode(ledMode,1); break; //d3 - strobe_mode(ledMode++); case 61455: EEPROM.write(STARTMODE,ledMode); Serial.print("Writing IR: "); Serial.println(ledMode); break; //d4 - Save startup mode case 61200: strobe_mode(17,1); break; //e1 - case 60945: thisdir = 1; break; //e2 - thisdir = 1; case 60690: thisdir = 0; break; //e3 - thisdir = 0; case 60435: strobe_mode(20,1); break; //e4 case 60180: palchg = 0; Serial.println("Fixed Palette"); break; //f1 - No palette change case 59925: palchg = 1; Serial.println("Similar 4 Palette"); break; //f2 - Similar 4 palette case 59670: palchg = 2; Serial.println("Random 4 Palette"); break; //f3 - Random 4 palette case 59415: palchg = 3; Serial.println("Random 16 Palette"); break; //f4 - Random 16 palette default: break; // We could do something by default } // switch } // strandActive IRProtocol = 0; // reset IRProtocol variable to not read the same value twice. } // if IRLavailable() } // getirl() void IREvent(uint8_t protocol, uint16_t address, uint32_t command) { if (IRL_BLOCKING && !IRProtocol) { IRProtocol = protocol; // update the values to the newest valid input IRAddress = address; IRCommand = command; } } // IREvent() void set_strand() { // Setting the active strand. if(IRCommand == 64260) IRProtocol = 0; // Command is to set strand to let's clear the Protocol flag. strandFlag = 1; // We need this state flag in order to be able to continue to run the routine while changing active/inactive. Serial.print("Strand is: "); if (IRProtocol) { // We have a command and the strandFlag is 1 and it's not the Set Active flag command. Serial.println(IRCommand); strandFlag = 0; // We know we're finally setting the strand to be ACTIVE/INACTIVE, so we'll clear that state flag. if (IRCommand == STRANDID) { strandActive = 1; Serial.println("ACTIVE"); } else { strandActive = 0; Serial.println("INACTIVE"); } IRProtocol = 0; // Let's clear the the IRProtocol flag and be ready for another command. } } // set_strand() void readkeyboard() { // Process serial commands while (Serial.available() > 0) { inbyte = Serial.read(); // Read the command if (inbyte != 10) { // Don't print out the separate carriage return. Serial.print("# "); Serial.print(char(inbyte)); Serial.print(" "); } switch(inbyte) { case 97: // "a" - SET ALL TO ONE colour BY hue = 0 - 255 demorun = 0; ledMode = 0; thisarg = Serial.parseInt(); thisarg = constrain(thisarg,0,255); Serial.println(thisarg); fill_solid(leds, NUM_LEDS, CHSV(thisarg, 255, 255)); break; case 98: // "b" - SET MAX BRIGHTNESS to # max_bright = Serial.parseInt(); max_bright = constrain(max_bright,0,255); Serial.println(max_bright); LEDS.setBrightness(max_bright); break; case 99: // "c" - CLEAR STRIP Serial.println(" "); demorun = 0; ledMode = 0; strobe_mode(ledMode, 1); break; case 100: // "d" - SET DELAY VAR to # thisarg = Serial.parseInt(); thisdelay = constrain(thisarg,0,255); Serial.println(thisdelay); break; case 101: // "e" - SET PREVIOUS / NEXT mode thisarg = Serial.parseInt(); if (thisarg) { demorun = 0; ledMode=(ledMode+1)%(maxMode+1); } else { demorun = 0; ledMode=(ledMode-1); if (ledMode==255) ledMode=maxMode; } strobe_mode(ledMode,1); break; case 102: // "f - Set a fixed palette demorun = 0; palchg = 0; thisarg = Serial.parseInt(); gCurrentPaletteNumber = thisarg % gGradientPaletteCount; targetPalette = gGradientPalettes[gCurrentPaletteNumber]; Serial.println(gCurrentPaletteNumber); break; case 103: // "g" - TOGGLE glitter glitter = !glitter; Serial.println(" "); break; case 104: // "h" - SET HUE VAR to # thisarg = Serial.parseInt(); thishue = constrain(thisarg,0,255); Serial.println(thishue); break; case 105: // "i" - Set Similar Palette with hue selection palchg = 0; thisarg = Serial.parseInt(); thishue = constrain(thisarg,0,255); Serial.println(thishue); SetupMySimilar4Palette(); break; case 108: // "l" - Set strip length & save thisarg = Serial.parseInt(); NUM_LEDS = constrain(thisarg,1,MAX_LEDS); Serial.println(NUM_LEDS); EEPROM.write(STRANDLEN, NUM_LEDS); break; case 109: // "m" - SET MODE to # demorun = 0; ledMode = Serial.parseInt(); ledMode = constrain(ledMode,0,maxMode); Serial.println(ledMode); strobe_mode(ledMode, 1); break; case 110: // "n" - TOGGLE direction Serial.println(" "); thisdir = !thisdir; break; case 112: // "p" - Play mode is either fixed, sequential or shuffle demorun = Serial.parseInt(); demorun = constrain(demorun,0,2); Serial.println(demorun); break; case 113: // "q" - Get version number Serial.println(SEIRLIGHT_VERSION); break; case 115: // "s" SET SATURATION VAR to # thisarg = Serial.parseInt(); thissat = constrain(thisarg,0,255); Serial.println(thissat); break; case 116: // "t" - Select Palette mode thisarg = Serial.parseInt(); palchg = constrain(thisarg,0,3); Serial.println(palchg); break; case 117: // "u" - Sequence duration thisarg = Serial.parseInt(); demotime = constrain(thisarg,1,255); Serial.println(demotime); break; case 119: // "w" - Write current mode to EEPROM EEPROM.write(STARTMODE,ledMode); Serial.print("Writing keyboard: "); Serial.println(ledMode); break; } // switch inbyte } // while Serial.available } // readkeyboard() void readbutton() { // Read the button and perform action uint8_t b = checkButton(); if (b == 1) { // Just a click event to advance the mode demorun = 0; ledMode=(ledMode+1)%(maxMode+1); strobe_mode(ledMode,1); Serial.print("Advance "); Serial.println(ledMode); } if (b == 2) { // A double-click event to reset to 0 demorun = 0; ledMode = 0; strobe_mode(ledMode, 1); Serial.println("Reset"); } if (b == 3) { // A hold event to write current mode to EEPROM demorun = 0; EEPROM.write(STARTMODE,ledMode); Serial.print("Writing Button: "); Serial.println(ledMode); } } // readbutton()