jsmirnio

Arduino Neopixel Christmas Tree 2015

Dec 20th, 2015
1,421
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     /*
  2.     Run Multiple Neopixel WS2812 Patterns Simultaneously
  3.     Modified from Bill Earl's  Adafruit Multitasking Tutorial (which is excellent!)
  4.     Includes a Candy Cane Pattern that reverses, Runs a Controlled Number of Repetitions,
  5.     then Changes Colors, then Resets to start over again
  6.     */
  7.  
  8. /* Here is a video of this program in action - https://www.youtube.com/watch?v=uFzPAEqjF38  */
  9.     #include <Adafruit_NeoPixel.h>
  10.  
  11.     // Pattern types supported:
  12.     enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
  13.     // Patern directions supported:
  14.     enum  direction { FORWARD, REVERSE };
  15.  
  16.     // NeoPattern Class - Derived from the Adafruit_NeoPixel class
  17.     // PUBLIC Variables and Functions are available everywhere - otherwise, ERRORS!
  18.     class NeoPatterns : public Adafruit_NeoPixel
  19.     {
  20.       public:
  21.  
  22.         // Member Variables:
  23.         pattern  ActivePattern;  // which pattern is running
  24.         direction Direction;     // direction to run the pattern
  25.  
  26.         unsigned long Interval;   // milliseconds between updates - essentially, the FRAME RATE
  27.         unsigned long lastUpdate; // Last Update of position
  28.  
  29.         uint32_t Color1, Color2;  // What Colors are in use
  30.         uint16_t TotalSteps;  // Total Number of Steps in the Pattern
  31.         uint16_t Index;  // Current Step Within the Pattern - Which FRAME
  32.  
  33.         uint32_t Stripe1, Stripe2;  // What Colors are in use for Candy Cane Patterns
  34.         int Width; // Width for Candy Cane Stripes in Pixels
  35.         int Offset; // Offset for Pattern Start
  36.         int Sets; // Number of Repetitions of This Pattern
  37.         int SetCount; // Count Repetitions of Current Pattern Set
  38.  
  39.         void (*OnComplete)();  // Callback on Completion of Pattern
  40.  
  41.         // Constructor - Calls base-class Constructor to initialize strip
  42.         NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
  43.           : Adafruit_NeoPixel(pixels, pin, type)
  44.         {
  45.           OnComplete = callback;
  46.         }
  47.  
  48.         // Update the pattern
  49.         void Update()
  50.         {
  51.           if ((millis() - lastUpdate) > Interval) // Time to Update?
  52.           {
  53.             lastUpdate = millis();
  54.             switch (ActivePattern)
  55.             {
  56.               case CANDY_CANE:
  57.                 CandyCaneUpdate();
  58.                 break;
  59.               case RAINBOW_CYCLE:
  60.                 RainbowCycleUpdate();
  61.                 break;
  62.               case THEATER_CHASE:
  63.                 TheaterChaseUpdate();
  64.                 break;
  65.               case COLOR_WIPE:
  66.                 ColorWipeUpdate();
  67.                 break;
  68.               case SCANNER:
  69.                 ScannerUpdate();
  70.                 break;
  71.               case FADE:
  72.                 FadeUpdate();
  73.                 break;
  74.               default:
  75.                 break;
  76.             }
  77.           }
  78.         }
  79.  
  80.         // Increment the Index Variable and Reset at the End of the Pattern (Number of Steps)
  81.         void Increment()
  82.         {
  83.           if (Direction == FORWARD)
  84.           {
  85.             Index++; // Increment the INDEX
  86.             if (Index >= TotalSteps)
  87.             {
  88.               Index = 0;
  89.               if (OnComplete != NULL)
  90.               {
  91.                 OnComplete(); // Call the Completion Callback
  92.               }
  93.             }
  94.           }
  95.           else // Direction == REVERSE
  96.           {
  97.             --Index; // Decrement the INDEX
  98.             if (Index <= 0)
  99.             {
  100.               Index = TotalSteps - 1;
  101.               if (OnComplete != NULL)
  102.               {
  103.                 OnComplete(); // Call the Completion Callback
  104.               }
  105.             }
  106.           }
  107.         }
  108.  
  109.         // Reverse the Pattern Direction
  110.         void Reverse()
  111.         {
  112.           if (Direction == FORWARD)
  113.           {
  114.             Direction = REVERSE;
  115.             Index = TotalSteps - 1;
  116.           }
  117.           else
  118.           {
  119.             Direction = FORWARD;
  120.             Index = 0;
  121.           }
  122.         }
  123.  
  124.         // Initialize the CandyCane Pattern
  125.         /*  CandyCane CHASING COLOR STRIPES
  126.         //   Create scrolling RED & WHITE - candy cane - stripes.
  127.         //   Try adjusting the width in pixels for various results.
  128.         //   Value "sets" should evenly divide into strand length
  129.         //  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
  130.         */
  131.  
  132.     #define Brightness 2 //Set brightness to 1/2
  133.     #define Full (255/Brightness)
  134.  
  135.         void CandyCane(int sets, int width, uint8_t interval, uint32_t stripe1, uint32_t stripe2, direction dir = FORWARD)
  136.         {
  137.           ActivePattern = CANDY_CANE; // Names of this Pattern for other functions
  138.           Interval = interval; // Speed of the Pattern
  139.           TotalSteps = numPixels(); // Number of steps for this Pattern
  140.           Stripe1 = stripe1; // Stripe Color1
  141.           Stripe2 = stripe2; // Stripe Color2
  142.           Index = 0;
  143.           Direction = dir;
  144.           Offset = 0; // Offset to start anywhere
  145.           Sets = sets; // Number of sets for the pattern
  146.           Width = width; // Width of the alternating Stripes
  147.         }
  148.  
  149.         void CandyCaneUpdate()
  150.         {
  151.           int L;
  152.  
  153.           // Loop for Setting Pixel L Color;
  154.           for (int i = 0; i < numPixels(); i++) {
  155.             L = numPixels() - i - 1; // Which Pixel to Update;
  156.  
  157.             if ( ((Index + i) % ((Width * 2)) ) < (Width) ) {
  158.               //setPixelColor(L, Full, 0, 0); // SET PIXEL L COLOR TO RED
  159.               setPixelColor(L, Stripe1); // SET PIXEL L COLOR TO RED
  160.             } else {
  161.               //setPixelColor(L, Full, Full, Full); // SET PIXEL L COLOR TO WHITE
  162.               setPixelColor(L, Stripe2); // SET PIXEL L COLOR TO WHITE
  163.             }
  164.  
  165.           }; // End of Setting Pixel Color;
  166.           show();
  167.           //       delay(50);  // For Debugging;
  168.           if (Index == (numPixels() - 1)) {
  169.             if (Direction == FORWARD) {
  170.               Direction = REVERSE;
  171.             } else if (Direction == REVERSE) {
  172.               Direction = FORWARD;
  173.             }
  174.           }
  175.           Increment(); // Increment the Index for the Next Frame;
  176.         }; // End of Function;
  177.  
  178.  
  179.         // Initialize for a RainbowCycle
  180.         void RainbowCycle(uint8_t interval, direction dir = FORWARD)
  181.         {
  182.           ActivePattern = RAINBOW_CYCLE;
  183.           Interval = interval;
  184.           TotalSteps = 255;
  185.           Index = 0;
  186.           Direction = dir;
  187.         }
  188.  
  189.         // Update the Rainbow Cycle Pattern
  190.         void RainbowCycleUpdate()
  191.         {
  192.           for (int i = 0; i < numPixels(); i++)
  193.           {
  194.             setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
  195.           }
  196.           show();
  197.           Increment();
  198.         }
  199.  
  200.         // Initialize for a Theater Chase
  201.         void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
  202.         {
  203.           ActivePattern = THEATER_CHASE;
  204.           Interval = interval;
  205.           TotalSteps = numPixels();
  206.           Color1 = color1;
  207.           Color2 = color2;
  208.           Index = 0;
  209.           Direction = dir;
  210.         }
  211.  
  212.         // Update the Theater Chase Pattern
  213.         void TheaterChaseUpdate()
  214.         {
  215.           for (int i = 0; i < numPixels(); i++)
  216.           {
  217.             if ((i + Index) % 3 == 0)
  218.             {
  219.               setPixelColor(i, Color1);
  220.             }
  221.             else
  222.             {
  223.               setPixelColor(i, Color2);
  224.             }
  225.           }
  226.           show();
  227.           Increment();
  228.         }
  229.  
  230.         // Initialize for a ColorWipe
  231.         void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
  232.         {
  233.           ActivePattern = COLOR_WIPE;
  234.           Interval = interval;
  235.           TotalSteps = numPixels();
  236.           Color1 = color;
  237.           Index = 0;
  238.           Direction = dir;
  239.         }
  240.  
  241.         // Update the Color Wipe Pattern
  242.         void ColorWipeUpdate()
  243.         {
  244.           setPixelColor(Index, Color1);
  245.           show();
  246.           Increment();
  247.         }
  248.  
  249.         // Initialize for a SCANNNER
  250.         void Scanner(uint32_t color1, uint8_t interval)
  251.         {
  252.           ActivePattern = SCANNER;
  253.           Interval = interval;
  254.           TotalSteps = (numPixels() - 1) * 2;
  255.           Color1 = color1;
  256.           Index = 0;
  257.         }
  258.  
  259.         // Update the Scanner Pattern
  260.         void ScannerUpdate()
  261.         {
  262.           for (int i = 0; i < numPixels(); i++)
  263.           {
  264.             if (i == Index)  // Scan Pixel to the right
  265.             {
  266.               setPixelColor(i, Color1);
  267.             }
  268.             else if (i == TotalSteps - Index) // Scan Pixel to the left
  269.             {
  270.               setPixelColor(i, Color1);
  271.             }
  272.             else // Fading tail
  273.             {
  274.               setPixelColor(i, DimColor(getPixelColor(i)));
  275.             }
  276.           }
  277.           show();
  278.           Increment();
  279.         }
  280.  
  281.         // Initialize for a Fade
  282.         void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
  283.         {
  284.           ActivePattern = FADE;
  285.           Interval = interval;
  286.           TotalSteps = steps;
  287.           Color1 = color1;
  288.           Color2 = color2;
  289.           Index = 0;
  290.           Direction = dir;
  291.         }
  292.  
  293.         // Update the Fade Pattern
  294.         void FadeUpdate()
  295.         {
  296.           // Calculate linear interpolation between Color1 and Color2
  297.           // Optimise order of operations to minimize truncation error
  298.           uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
  299.           uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
  300.           uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
  301.  
  302.           ColorSet(Color(red, green, blue));
  303.           show();
  304.           Increment();
  305.         }
  306.  
  307.         // Calculate 50% dimmed version of a color (Used by ScannerUpdate)
  308.         uint32_t DimColor(uint32_t color)
  309.         {
  310.           // Shift R, G and B components one bit to the right
  311.           uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
  312.           return dimColor;
  313.         }
  314.  
  315.         // Set all pixels to a color (synchronously)
  316.         void ColorSet(uint32_t color)
  317.         {
  318.           for (int i = 0; i < numPixels(); i++)
  319.           {
  320.             setPixelColor(i, color);
  321.           }
  322.           show();
  323.         }
  324.  
  325.         // Returns the Red component of a 32-bit color
  326.         uint8_t Red(uint32_t color)
  327.         {
  328.           return (color >> 16) & 0xFF;
  329.         }
  330.  
  331.         // Returns the Green component of a 32-bit color
  332.         uint8_t Green(uint32_t color)
  333.         {
  334.           return (color >> 8) & 0xFF;
  335.         }
  336.  
  337.         // Returns the Blue component of a 32-bit color
  338.         uint8_t Blue(uint32_t color)
  339.         {
  340.           return color & 0xFF;
  341.         }
  342.  
  343.         // Input a value 0 to 255 to get a color value.
  344.         // The colours are a transition r - g - b - back to r.
  345.         uint32_t Wheel(byte WheelPos)
  346.         {
  347.           WheelPos = 255 - WheelPos;
  348.           if (WheelPos < 85)
  349.           {
  350.             return Color(255 - WheelPos * 3, 0, WheelPos * 3);
  351.           }
  352.           else if (WheelPos < 170)
  353.           {
  354.             WheelPos -= 85;
  355.             return Color(0, WheelPos * 3, 255 - WheelPos * 3);
  356.           }
  357.           else
  358.           {
  359.             WheelPos -= 170;
  360.             return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  361.           }
  362.         }
  363.     };
  364.  
  365.     //  Define some NeoPatterns used for any of the three Strings
  366.     //  as well as some completion routines
  367.     //  NeoPatterns Instantiate String by Name(number of LEDs, LED pin, Serial OUT COLOR Order & Frequency, Something Else);
  368.     NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
  369.     NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
  370.     NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);
  371.  
  372.     /*  STARTUP ROUTINES GO HERE  */
  373.     // Initialize everything and prepare to start
  374.     void setup()
  375.     {
  376.       Serial.begin(115200);
  377.  
  378.       pinMode(8, INPUT_PULLUP); // Setup Button #1
  379.       pinMode(9, INPUT_PULLUP); // Setup Button #2
  380.  
  381.       // Initialize all the pixelStrips
  382.       String1.begin();
  383.       String2.begin();
  384.       String3.begin();
  385.  
  386.       // Kick off a pattern for each String
  387.       String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  388.       String2.RainbowCycle(3);
  389.       String2.Color1 = String1.Color1;
  390.       //  String3.Scanner(String1.Color(255, 0, 0), 55);
  391.       //  String3.TheaterChase(String3.Color(255, 255, 0), String3.Color(0, 0, 50), 100);
  392.       String3.CandyCane(5, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127));
  393.     }
  394.  
  395.     /*  MAIN PROGRAM LOOP - RUN ENDLESSLY  */
  396.     // Main loop
  397.     void loop()
  398.     {
  399.       // Update the Strings on Every Loop.
  400.       String1.Update();
  401.       String2.Update();
  402.       String3.Update();
  403.  
  404.       // Switch patterns on a button press:
  405.       if (digitalRead(8) == LOW) // Button #1 Pressed;
  406.       {
  407.         // Switch String1 to FASE pattern
  408.         String1.ActivePattern = FADE;
  409.         String1.Interval = 20;
  410.         // Speed up the rainbow on String2
  411.         String2.Interval = 0;
  412.         //   Set String3 to all red
  413.         //   String3.ColorSet(String3.Color(255, 0, 0));
  414.       }
  415.       else if (digitalRead(9) == LOW) // Button #2 Pressed;
  416.       {
  417.         // Switch to alternating color wipes on Strings1 and 2
  418.         String1.ActivePattern = COLOR_WIPE;
  419.         String2.ActivePattern = COLOR_WIPE;
  420.         String2.TotalSteps = String2.numPixels();
  421.         //   And update String3
  422.         //   String3.Update();
  423.       }
  424.       else // Nothing Pressed - Back to normal operation
  425.       {
  426.         // Restore all pattern parameters to normal values
  427.         String1.ActivePattern = THEATER_CHASE;
  428.         String1.Interval = 100;
  429.  
  430.         String2.ActivePattern = RAINBOW_CYCLE;
  431.         String2.TotalSteps = 255;
  432.         String2.Interval = min(10, String2.Interval);
  433.  
  434.         // And update String3;
  435.         //   String3.ActivePattern = CANDY_CANE;
  436.         //   String3.Update();
  437.       }
  438.     }
  439.  
  440.     //------------------------------------------------------------
  441.     // Completion Routines - get called on completion of a pattern
  442.     //------------------------------------------------------------
  443.  
  444.     // String1 Completion Callback
  445.     void String1Complete()
  446.     {
  447.       if (digitalRead(9) == LOW)  // Button #2 pressed
  448.       {
  449.         // Alternate color-wipe patterns with String2
  450.         String2.Interval = 40;
  451.         String1.Color1 = String1.Wheel(random(255));
  452.         String1.Interval = 20000;
  453.       }
  454.       else  // Return to normal
  455.       {
  456.         String1.Reverse();
  457.       }
  458.     }
  459.  
  460.     // Ring 2 Completion Callback
  461.     void String2Complete()
  462.     {
  463.       if (digitalRead(9) == LOW)  // Button #2 pressed
  464.       {
  465.         // Alternate color-wipe patterns with String1
  466.         String1.Interval = 20;
  467.         String2.Color1 = String2.Wheel(random(255));
  468.         String2.Interval = 20000;
  469.       }
  470.       else  // Return to normal
  471.       {
  472.         String2.RainbowCycle(random(0, 10));
  473.       }
  474.     }
  475.  
  476.     // String3 Completion Callback
  477.     void String3Complete()
  478.     {
  479.       if (String3.SetCount < String3.Sets) {
  480.         //   Set a New Random Color for the next Set
  481.         String3.Stripe1 = String3.Wheel(random(255));
  482.         String3.Stripe2 = (0, 0, 0);
  483.         String3.SetCount ++;
  484.       } else {
  485.        //  Reset to Default Candy Cane Colors
  486.         String3.SetCount = 0;
  487.         String3.CandyCane(5, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127)); // Reset Back to Red/White;
  488.       }
  489.     }
  490.     // END OF PROGRAM;
RAW Paste Data