Declare some NeoPatterns
Before we get started, we need to declare some NeoPattern objects to control our pixels.
Using the wiring diagram from the previous page, we'll initialize a 16 and 24 pixel ring, as well as a 16 pixel strip constructed from 2 8-pixel sticks.
// Define some NeoPatterns for the two rings and the stick // and pass the adderess of the associated completion routines NeoPatterns Ring1(24, 5, NEO_GRB + NEO_KHZ800, &Ring1Complete); NeoPatterns Ring2(16, 6, NEO_GRB + NEO_KHZ800, &Ring2Complete); NeoPatterns Stick(16, 7, NEO_GRB + NEO_KHZ800, &StickComplete);
Getting The Action Started
And, as with regular NeoPixel strips, we need to call begin() to get everything initialized prior to using the strips. We'll also set up some input pins for our pushbuttons and kick off an initial pattern for each strip.
// Initialize everything and prepare to start void setup() { // Initialize all the pixelStrips Ring1.begin(); Ring2.begin(); Stick.begin(); // Enable internal pullups on the switch inputs pinMode(8, INPUT_PULLUP); pinMode(9, INPUT_PULLUP); // Kick off a pattern Ring1.TheaterChase(Ring1.Color(255,255,0), Ring1.Color(0,0,50), 100); Ring2.RainbowCycle(3); Ring2.Color1 = Ring1.Color1; Stick.Scanner(Ring1.Color(255,0,0), 55); }
Updating the Patterns
To keep things running smoothly, you just need to call the Update() function on each NeoPattern on a regular basis. Since we have eliminated the inner loops and delays from the patterns, this is simple to do in either your loop() function as we show here, or in a timer interrupt handler as shown in part 2 of this series.
The simple case would be to just call the update functions for each of the NeoPatterns you have defined.
// Main loop void loop() { // Update the rings. Ring1.Update(); Ring2.Update(); Stick.Update(); }
User Interactions
With no inner-loops, your code can remain responsive to any user interactions or external events. And you can instantly change patterns or colors based on these events.
To make things more interesting, we will take advantage of this capability and expand our loop to react to button presses on the two pushbuttons:
Pressing Button #1 (pin 8) will:
- Change the pattern on Ring1 from THEATER_CHASE to FADE
- Change the speed of the RainbowCycle on Ring2
- Turn the stick to solid RED
Pressing button #2 (pin 9) will:
- Change the pattern on Ring1 from THEATER_CHASE to COLOR_WIPE
- Change the pattern on Ring2 from THEATER_CHASE to COLOR_WIPE
When no buttons are pressed, all patterns resume normal operation.
// Main loop void loop() { // Update the rings. Ring1.Update(); Ring2.Update(); // Switch patterns on a button press: if (digitalRead(8) == LOW) // Button #1 pressed { // Switch Ring1 to FASE pattern Ring1.ActivePattern = FADE; Ring1.Interval = 20; // Speed up the rainbow on Ring2 Ring2.Interval = 0; // Set stick to all red Stick.ColorSet(Stick.Color(255, 0, 0)); } else if (digitalRead(9) == LOW) // Button #2 pressed { // Switch to alternating color wipes on Rings1 and 2 Ring1.ActivePattern = COLOR_WIPE; Ring2.ActivePattern = COLOR_WIPE; Ring2.TotalSteps = Ring2.numPixels(); // And update tbe stick Stick.Update(); } else // Back to normal operation { // Restore all pattern parameters to normal values Ring1.ActivePattern = THEATER_CHASE; Ring1.Interval = 100; Ring2.ActivePattern = RAINBOW_CYCLE; Ring2.TotalSteps = 255; Ring2.Interval = min(10, Ring2.Interval); // And update tbe stick Stick.Update(); } }
Completion Callbacks
Left alone, each pattern will repeat continuously. The optional completion callback gives you the ability to perform some action on completion of each pattern cycle.
The action performed in the completion callback can be to change some aspect of the pattern or trigger some other external event.
Ring1 Completion Callback
The Ring1 completion callback affects the operation of both Ring1 and Ring2. It looks at the state of Button #2. If it is pressed, it will:
- Speed up Ring2 by decreasing its Interval. This effectively 'wakes up' Ring2.
- Slow down Ring1 by increasing its Interval. This effectively puts Ring1 to sleep.
- Selects a radom color from the wheel for the next iteration of Ring1's pattern.
If no button is pressed, it simply reverses the direction of the normal chase pattern.
// Ring1 Completion Callback void Ring1Complete() { if (digitalRead(9) == LOW) // Button #2 pressed { // Alternate color-wipe patterns with Ring2 Ring2.Interval = 40; Ring1.Color1 = Ring1.Wheel(random(255)); Ring1.Interval = 20000; } else // Retrn to normal { Ring1.Reverse(); } }
Ring2 Completion Callback
The Ring2 completion callback is the complement to the Ring1 completion callback.
If Button #2 is pressed, it will:
- Speed up Ring1 by decreasing its Interval. This effectively 'wakes up' Ring1.
- Slow down Ring2 by increasing its Interval. This effectively puts Ring2 to sleep.
- Selects a random color from the wheel for the next iteration of Ring2's pattern.
If no button is pressed, it simply picks a random speed for the next iteration of the normal Ring2 Rainbow Cycle pattern.
// Ring 2 Completion Callback void Ring2Complete() { if (digitalRead(9) == LOW) // Button #2 pressed { // Alternate color-wipe patterns with Ring1 Ring1.Interval = 20; Ring2.Color1 = Ring2.Wheel(random(255)); Ring2.Interval = 20000; } else // Retrn to normal { Ring2.RainbowCycle(random(0,10)); } }
Stick Completion Callback
The Stick completon callback just slects a random color from the wheel for the next pass of the scanner pattern.
// Stick Completion Callback void StickComplete() { // Random color change for next scan Stick.Color1 = Stick.Wheel(random(255)); }
Text editor powered by tinymce.