Using NeoPatterns

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));
}
Last updated on 2015-05-04 at 04.27.27 PM Published on 2015-03-02 at 12.29.14 PM