Advertisement
medpixman

Arduino Neopixel Christmas Tree 2018

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