0

Adding New Patterns to Bill Earl's Multitasking Pt3 Neopixel
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Adding New Patterns to Bill Earl's Multitasking Pt3 Neopixel

by adavegetable on Thu Nov 12, 2015 6:33 pm

Bill Earl has an excellent tutorial - Multi-tasking the Arduino - Part 3 that runs multiple patterns simultaneously on multiple sets of Neopixels. How can we add new routines/patterns to this excellent program?

For Christmas, I would like to use this "Candy Cane" pattern:
Code: Select all | TOGGLE FULL SIZE
#define Brightness 10 //Set brightness to 1/10th
#define Full (255/Brightness)

/*  CandyCane CHASING COLOR STRIPES 
//   Create scrolling RED & WHITE - candy cane - stripes.
//   Try adjusting the width in pixels for various results.
//   Value "sets" should evenly divide into strand length
//  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
*/
void CandyCane  (int sets,int width,int wait) {
  int L;
  for(int j=0;j<(sets*width);j++) {
    for(int i=0;i< strip.numPixels();i++) {
      L=strip.numPixels()-i-1;
      if ( ((i+j) % (width*2) )<width)
        strip.setPixelColor(L,Full,0,0); // SET COLOR TO RED
      else
        strip.setPixelColor(L,Full,Full,Full); // SET COLOR TO WHITE
    };
    strip.show();
    delay(wait); // DELAY BETWEEN WIPES
  };
};
 


I tried to modify this snippet for use with Bill's program - but I get lot's of compile errors. Bill did a great job of explaining his script - but a nice addition would be a "step-by-step" for transforming an existing pattern - that uses [Delay] - into one that becomes an instantiated class like the others he has transformed, like his versions of Scanner and ColorWipe. Bill does a great job of explaining - but I'm just running at 10% brightness on understanding his methods.
Last edited by adavegetable on Thu Nov 12, 2015 7:51 pm, edited 1 time in total.

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adafruit_support_bill on Thu Nov 12, 2015 7:51 pm

For Christmas, I would like to use this "Candy Cane" pattern:

Your pattern is similar to the TheatreChase pattern. The breakdown would be similar.
https://learn.adafruit.com/multi-taskin ... ater-chase

I tried to modify this snippet for use with Bill's program - but I get lot's of compile errors.

It's hard to diagnose a problem without being able to see either the code or the errors.

adafruit_support_bill
 
Posts: 81892
Joined: Sat Feb 07, 2009 10:11 am

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Thu Nov 12, 2015 8:13 pm

Thanks for the amazingly rapid response! Sorry, I should have included the snippet, as I tried to modify it. Thanks for any corrections and/or advice.

Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE, CANDYCANE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - derived from the Adafruit_NeoPixel class
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates
    unsigned long lastUpdate; // last update of position

    uint32_t Color1, Color2;  // What colors are in use
    uint16_t TotalSteps;  // total number of steps in the pattern
    uint16_t Index;  // current step within the pattern

    void (*OnComplete)();  // Callback on completion of pattern

    // Constructor - calls base-class constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // time to update
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          case CANDYCANE:
            CandyCaneUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index and reset at the end
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++;
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the comlpetion callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index;
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the comlpetion callback
          }
        }
      }
    }

    // Reverse pattern direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }


#define Brightness 10 //Set brightness to 1/10th
#define Full (255/Brightness)

// Initialize for a CANDYCANE
/*  CandyCane CHASING COLOR STRIPES
//   Create scrolling RED & WHITE - candy cane - stripes.
//   Try adjusting the width in pixels for various results.
//   Value "sets" should evenly divide into strand length
//  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
//  EXAMPLE USAGE: stick.CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
*/

    // Initialize for a RainbowCycle
    void CandyCane(uint8_t interval, direction dir = FORWARD)
{
  ActivePattern = CANDYCANE;
  Interval = interval;
  TotalSteps = numPixels();
  Index = 0;
}

// Update the CandyCane Pattern
void CandyCaneUpdate()
{
  int L;
  int width=8;
  int sets=30;
  for (int j = 0; j < (sets * width); j++) {
    for (int i = 0; i < strip.numPixels(); i++) {
      L = numPixels() - i - 1;
      if ( ((i + j) % (width * 2) ) < width)
        setPixelColor(L, Full, 0, 0); // SET COLOR TO RED
      else
        setPixelColor(L, Full, Full, Full); // SET COLOR TO WHITE
    };
    show();
    Increment();
  }


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};


//  Define some NeoPatterns for the two rings and the String3
//  as well as some completion routines
//  NeoPatterns Instantiate Name(number of LEDs, LED pin, Serial Order & Frequency, Something Else);
NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

#define Count 50
#define Pin 11
Adafruit_NeoPixel strip = Adafruit_NeoPixel(Count, Pin, NEO_GRB + NEO_KHZ800);

// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  // Kick off a pattern
  String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  String3.CandyCane(30, 8, 50); //30 sets, 8 pixels wide, 50us delay
}

// Main loop
void loop()
{
  // Update the rings.
  String1.Update();
  String2.Update();

  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 pressed
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    // Set String3 to all red
    String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 pressed
  {
    // Switch to alternating color wipes on Rings1 and 2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    // And update tbe String3
    String3.Update();
  }
  else // Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;
    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);
    // And update tbe String3
    String3.Update();
  }
}

//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Retrn to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Retrn to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  // Random color change for next scan
  String3.Color1 = String3.Wheel(random(255));
}


adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adafruit_support_bill on Thu Nov 12, 2015 8:34 pm

And what are the compiler errors you are seeing? These are usually fairly specific and point you to the exact line number and character position where the error was detected.

adafruit_support_bill
 
Posts: 81892
Joined: Sat Feb 07, 2009 10:11 am

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Thu Nov 12, 2015 11:45 pm

Code: Select all | TOGGLE FULL SIZE
Arduino: 1.6.3 (Windows 7), Board: "Arduino Leonardo"

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:340:21: error: expected identifier before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:340:21: error: expected ',' or '...' before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:341:21: error: expected identifier before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:341:21: error: expected ',' or '...' before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:342:21: error: expected identifier before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:342:21: error: expected ',' or '...' before numeric constant

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:450:1: error: expected '}' at end of input

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::CandyCaneUpdate()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:152:5: error: a function-definition is not allowed here before '{' token

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:162:5: error: a function-definition is not allowed here before '{' token

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:334:1: error: expected '}' at end of input

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::setup()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:357:10: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:358:10: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:359:10: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:362:10: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:362:31: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:362:59: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:363:10: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:364:10: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:364:27: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:366:10: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::loop()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:373:10: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:374:10: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:380:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:381:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:383:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:385:12: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:385:29: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:390:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:391:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:392:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:392:33: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:394:12: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:399:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:400:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:401:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:402:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:403:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

In file included from C:\Users\jsmirnio\Documents\Arduino\libraries\Adafruit_NeoPixel/Adafruit_NeoPixel.h:23:0,

                 from Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:1:

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:403:39: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

D:\Arduino\arduino-1.6.3\hardware\arduino\avr\cores\arduino/Arduino.h:84:24: note: in definition of macro 'min'

 #define min(a,b) ((a)<(b)?(a):(b))

                        ^

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:403:39: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

D:\Arduino\arduino-1.6.3\hardware\arduino\avr\cores\arduino/Arduino.h:84:32: note: in definition of macro 'min'

 #define min(a,b) ((a)<(b)?(a):(b))

                                ^

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:405:12: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::String1Complete()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:419:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:420:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:420:29: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:421:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:425:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::String2Complete()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:435:12: error: '((NeoPatterns*)this)->NeoPatterns::String1' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:436:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:436:29: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:437:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:441:12: error: '((NeoPatterns*)this)->NeoPatterns::String2' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: In member function 'void NeoPatterns::String3Complete()':

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:449:10: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:449:27: error: '((NeoPatterns*)this)->NeoPatterns::String3' does not have class type

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino: At global scope:

Arduino_Neopixel_Multitasking_Multiple_Strips_Candy_Cane_v1.ino:450:1: error: expected unqualified-id at end of input

Error compiling.

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Fri Nov 13, 2015 12:37 am

Thanks for your encouragement to understand the errors ... this version compiles w/o errors;
Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - derived from the Adafruit_NeoPixel class
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates
    unsigned long lastUpdate; // last update of position

    uint32_t Color1, Color2;  // What colors are in use
    uint16_t TotalSteps;  // total number of steps in the pattern
    uint16_t Index;  // current step within the pattern

    void (*OnComplete)();  // Callback on completion of pattern

    // Constructor - calls base-class constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // time to update
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          case CANDY_CANE:
            CandyCaneUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index and reset at the end
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++;
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the completion callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index;
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the completion callback
          }
        }
      }
    }

    // Reverse pattern direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }

    // Initialize for CandyCane
    /*  CandyCane CHASING COLOR STRIPES
    //   Create scrolling RED & WHITE - candy cane - stripes.
    //   Try adjusting the width in pixels for various results.
    //   Value "sets" should evenly divide into strand length
    //  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
    */
#define Brightness 10 //Set brightness to 1/10th
#define Full (255/Brightness)
    void CandyCane(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = CANDY_CANE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    void CandyCaneUpdate  ()
    {
      int L;
      int sets=30;
      int width=8;
//      int wait;
      for (int j = 0; j < (sets * width); j++) {
        for (int i = 0; i < numPixels(); i++) {
          L = numPixels() - i - 1;
          if ( ((i + j) % (width * 2) ) < width)
            setPixelColor(L, Full, 0, 0); // SET COLOR TO RED
          else
            setPixelColor(L, Full, Full, Full); // SET COLOR TO WHITE
        };
        show();
        Increment();
      };
    };


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};

//  Define some NeoPatterns for the two rings and the String3
//  as well as some completion routines
//  NeoPatterns Instantiate Name(number of LEDs, LED pin, Serial Order & Frequency, Something Else);
NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  // Kick off a pattern
  String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  //  String3.TheaterChase(String3.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String3.CandyCane(String1.Color(255, 0, 0), String1.Color(255, 255, 255), 100);
}

// Main loop
void loop()
{
  // Update the rings.
  String1.Update();
  String2.Update();

  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 pressed
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    // Set String3 to all red
    String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 pressed
  {
    // Switch to alternating color wipes on Rings1 and 2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    // And update tbe String3
    String3.Update();
  }
  else // Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;
    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);
    // And update tbe String3
    String3.Update();
  }
}

//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Retrn to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Return to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  // Random color change for next scan
  String3.Color1 = String3.Wheel(random(255));
}

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adafruit_support_bill on Fri Nov 13, 2015 6:45 am

. this version compiles w/o errors;

Great! Does it work as expected?

adafruit_support_bill
 
Posts: 81892
Joined: Sat Feb 07, 2009 10:11 am

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Fri Nov 13, 2015 8:23 am

You have inspired me to dig deeper! Here is a new version, which compiles w/o error AND it functions as expected!
Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - derived from the Adafruit_NeoPixel class
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates
    unsigned long lastUpdate; // last update of position

    uint32_t Color1, Color2;  // What colors are in use
    uint16_t TotalSteps;  // total number of steps in the pattern
    uint16_t Index;  // current step within the pattern

    void (*OnComplete)();  // Callback on completion of pattern

    // Constructor - calls base-class constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // time to update
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case CANDY_CANE:
            CandyCaneUpdate();
            break;
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index and reset at the end
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++;
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the completion callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index;
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // call the completion callback
          }
        }
      }
    }

    // Reverse pattern direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }

    // Initialize for CandyCane
    /*  CandyCane CHASING COLOR STRIPES
    //   Create scrolling RED & WHITE - candy cane - stripes.
    //   Try adjusting the width in pixels for various results.
    //   Value "sets" should evenly divide into strand length
    //  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
    */
   
#define Brightness 2 //Set brightness to 1/10th
#define Full (255/Brightness)

    void CandyCane(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = CANDY_CANE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    void CandyCaneUpdate()
    {
      int L;
      int offset = 0;
      int sets = 30;
      int width = 8;

        for (int j = 0; j < numPixels(); j++){
            L = numPixels()-j-1;  // Which Pixel;
            if ( ((Index + j) % (width * 2) ) < width) {
              setPixelColor(L, Full, 0, 0); // SET PIXEL COLOR TO RED
            } else {
              setPixelColor(L, Full, Full, Full); // SET PIXEL COLOR TO WHITE
            }

      }; // End of Setting Pixel Color;
      show();
        //       delay(50);  // For Debugging;
      Increment(); // Increment the Index (Next frame);
    }; // End of Function;


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};

//  Define some NeoPatterns used for any of the three Strings
//  as well as some completion routines
//  NeoPatterns Instantiate Name(number of LEDs, LED pin, Serial Order & Frequency, Something Else);
NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  // Kick off a pattern
  String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  //  String3.TheaterChase(String3.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String3.CandyCane(String3.Color(125, 0, 0), String3.Color(125, 125, 125), 200);
}

// Main loop
void loop()
{
  // Update the Strings.
  String1.Update();
  String2.Update();
  String3.Update();
 
  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 pressed
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    // Set String3 to all red
    String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 pressed
  {
    // Switch to alternating color wipes on Rings1 and 2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    // And update tbe String3
    String3.Update();
  }
  else // Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;
    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);
    // And update tbe String3
    String3.Update();
  }
}

//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Retrn to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Return to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  // Random color change for next scan
  String3.Color1 = String3.Wheel(random(255));
}

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adafruit_support_bill on Fri Nov 13, 2015 8:35 am

Even better! Thanks for posting your results.

adafruit_support_bill
 
Posts: 81892
Joined: Sat Feb 07, 2009 10:11 am

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Fri Nov 20, 2015 12:10 pm

Here is the latest version - the stripes can be any color and the flow of the stripes reverses.
Code: Select all | TOGGLE FULL SIZE
#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - Derived from the Adafruit_NeoPixel class
// PUBLIC Variables and Functions are available everywhere - otherwise, ERRORS!
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates - essentially, the FRAME RATE
    unsigned long lastUpdate; // Last Update of position

    uint32_t Color1, Color2;  // What Colors are in use
    uint16_t TotalSteps;  // Total Number of Steps in the Pattern
    uint16_t Index;  // Current Step Within the Pattern - Which FRAME

    uint32_t Stripe1, Stripe2;  // What Colors are in use
    int Width; // Width for CandyCane
    int Offset; // Offset for Pattern Start
    int Sets; // Number of Repetitions of This Pattern

    void (*OnComplete)();  // Callback on Completion of Pattern

    // Constructor - Calls base-class Constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // Time to Update?
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case CANDY_CANE:
            CandyCaneUpdate();
            break;
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index Variable and Reset at the End of the Pattern (Number of Steps)
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++; // Increment the INDEX
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index; // Decrement the INDEX
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
    }

    // Reverse the Pattern Direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }

    // Initialize the CandyCane Pattern
    /*  CandyCane CHASING COLOR STRIPES
    //   Create scrolling RED & WHITE - candy cane - stripes.
    //   Try adjusting the width in pixels for various results.
    //   Value "sets" should evenly divide into strand length
    //  EXAMPLE USAGE: CandyCane(30,8,50, (250,0,0), (127,127,127)); //30 sets, 8 pixels wide, 50us delay, Red, White;
    */

#define Brightness 2 //Set brightness to 1/2
#define Full (255/Brightness)

    void CandyCane(int sets, int width, uint8_t interval, uint32_t stripe1, uint32_t stripe2, direction dir = FORWARD)
    {
      ActivePattern = CANDY_CANE; // Names of this Pattern for other functions
      Interval = interval; // Speed of the Pattern
      TotalSteps = numPixels(); // Number of steps for this Pattern
      Stripe1 = stripe1; // Stripe Color1
      Stripe2 = stripe2; // Stripe Color2
      Index = 0;
      Direction = dir;
      int offset = 0; // Offset to start anywhere
      int Sets = sets; // Number of sets for the pattern
      int Width = width; // Width of the alternating Stripes
    }

    void CandyCaneUpdate()
    {
      int L;
      Width = 4;

      // Loop for Setting Pixel L Color;
      for (int i = 0; i < numPixels(); i++) {
        L = numPixels() - i - 1; // Which Pixel to Update;

        if ( ((Index + i) % ((Width * 2)) ) < (Width) ) {
          //setPixelColor(L, Full, 0, 0); // SET PIXEL L COLOR TO RED
          setPixelColor(L, Stripe1); // SET PIXEL L COLOR TO RED
        } else {
          //setPixelColor(L, Full, Full, Full); // SET PIXEL L COLOR TO WHITE
          setPixelColor(L, Stripe2); // SET PIXEL L COLOR TO WHITE
        }

      }; // End of Setting Pixel Color;
      show();
      //       delay(50);  // For Debugging;
      if (Index == (numPixels() - 1)) {
        if (Direction == FORWARD) {
          Direction = REVERSE;
        } else if (Direction == REVERSE) {
          Direction = FORWARD;
        }
      }
      Increment(); // Increment the Index for the Next Frame;
    }; // End of Function;


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (Used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};

//  Define some NeoPatterns used for any of the three Strings
//  as well as some completion routines
//  NeoPatterns Instantiate String by Name(number of LEDs, LED pin, Serial OUT COLOR Order & Frequency, Something Else);
NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

/*  STARTUP ROUTINES GO HERE  */
// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP); // Setup Button #1
  pinMode(9, INPUT_PULLUP); // Setup Button #2

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  // Kick off a pattern for each String
  String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  //  String3.TheaterChase(String3.Color(255, 255, 0), String3.Color(0, 0, 50), 100);
  String3.CandyCane(30, 4, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127));
}

/*  MAIN PROGRAM LOOP - RUN ENDLESSLY  */
// Main loop
void loop()
{
  // Update the Strings on Every Loop.
  String1.Update();
  String2.Update();
  String3.Update();

  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 Pressed;
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    //   Set String3 to all red
    //   String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 Pressed;
  {
    // Switch to alternating color wipes on Strings1 and 2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    //   And update String3
    //   String3.Update();
  }
  else // Nothing Pressed - Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;

    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);

    // And update String3;
    //   String3.ActivePattern = CANDY_CANE;
    //   String3.Update();
  }
}

//------------------------------------------------------------
// Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Return to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Return to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  //   Random color change for next scan
  //   String3.Color1 = String3.Wheel(random(255));
}

// END OF PROGRAM;

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Sat Nov 21, 2015 8:50 pm

Adding Patterns to Bill Earl's Multitasking Pt3 Neopixel - the Candy Cane pattern now modified to control the number of repetitions, reverse directions, and then Reset to start the cycle all over again.
Code: Select all | TOGGLE FULL SIZE
/*
Run Multiple Neopixel WS2812 Patterns Simultaneously
Modified from Bill Earl's  Adafruit Multitasking Tutorial (which is excellent!)
Includes a Candy Cane Pattern that reverses, Runs a Controlled Number of Repetitions,
then Changes Colors, then Resets to start over again
*/
#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - Derived from the Adafruit_NeoPixel class
// PUBLIC Variables and Functions are available everywhere - otherwise, ERRORS!
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates - essentially, the FRAME RATE
    unsigned long lastUpdate; // Last Update of position

    uint32_t Color1, Color2;  // What Colors are in use
    uint16_t TotalSteps;  // Total Number of Steps in the Pattern
    uint16_t Index;  // Current Step Within the Pattern - Which FRAME

    uint32_t Stripe1, Stripe2;  // What Colors are in use for Candy Cane Patterns
    int Width; // Width for Candy Cane Stripes in Pixels
    int Offset; // Offset for Pattern Start
    int Sets; // Number of Repetitions of This Pattern
    int SetCount; // Count Repetitions of Current Pattern Set

    void (*OnComplete)();  // Callback on Completion of Pattern

    // Constructor - Calls base-class Constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // Time to Update?
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case CANDY_CANE:
            CandyCaneUpdate();
            break;
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index Variable and Reset at the End of the Pattern (Number of Steps)
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++; // Increment the INDEX
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index; // Decrement the INDEX
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
    }

    // Reverse the Pattern Direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }

    // Initialize the CandyCane Pattern
    /*  CandyCane CHASING COLOR STRIPES
    //   Create scrolling RED & WHITE - candy cane - stripes.
    //   Try adjusting the width in pixels for various results.
    //   Value "sets" should evenly divide into strand length
    //  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
    */

#define Brightness 2 //Set brightness to 1/2
#define Full (255/Brightness)

    void CandyCane(int sets, int width, uint8_t interval, uint32_t stripe1, uint32_t stripe2, direction dir = FORWARD)
    {
      ActivePattern = CANDY_CANE; // Names of this Pattern for other functions
      Interval = interval; // Speed of the Pattern
      TotalSteps = numPixels(); // Number of steps for this Pattern
      Stripe1 = stripe1; // Stripe Color1
      Stripe2 = stripe2; // Stripe Color2
      Index = 0;
      Direction = dir;
      Offset = 0; // Offset to start anywhere
      Sets = sets; // Number of sets for the pattern
      Width = width; // Width of the alternating Stripes
    }

    void CandyCaneUpdate()
    {
      int L;

      // Loop for Setting Pixel L Color;
      for (int i = 0; i < numPixels(); i++) {
        L = numPixels() - i - 1; // Which Pixel to Update;

        if ( ((Index + i) % ((Width * 2)) ) < (Width) ) {
          //setPixelColor(L, Full, 0, 0); // SET PIXEL L COLOR TO RED
          setPixelColor(L, Stripe1); // SET PIXEL L COLOR TO RED
        } else {
          //setPixelColor(L, Full, Full, Full); // SET PIXEL L COLOR TO WHITE
          setPixelColor(L, Stripe2); // SET PIXEL L COLOR TO WHITE
        }

      }; // End of Setting Pixel Color;
      show();
      //       delay(50);  // For Debugging;
      if (Index == (numPixels() - 1)) {
        if (Direction == FORWARD) {
          Direction = REVERSE;
        } else if (Direction == REVERSE) {
          Direction = FORWARD;
        }
      }
      Increment(); // Increment the Index for the Next Frame;
    }; // End of Function;


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (Used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};

//  Define some NeoPatterns used for any of the three Strings
//  as well as some completion routines
//  NeoPatterns Instantiate String by Name(number of LEDs, LED pin, Serial OUT COLOR Order & Frequency, Something Else);
NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

/*  STARTUP ROUTINES GO HERE  */
// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP); // Setup Button #1
  pinMode(9, INPUT_PULLUP); // Setup Button #2

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  // Kick off a pattern for each String
  String1.TheaterChase(String1.Color(255, 255, 0), String1.Color(0, 0, 50), 100);
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  //  String3.TheaterChase(String3.Color(255, 255, 0), String3.Color(0, 0, 50), 100);
  String3.CandyCane(5, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127));
}

/*  MAIN PROGRAM LOOP - RUN ENDLESSLY  */
// Main loop
void loop()
{
  // Update the Strings on Every Loop.
  String1.Update();
  String2.Update();
  String3.Update();

  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 Pressed;
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    //   Set String3 to all red
    //   String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 Pressed;
  {
    // Switch to alternating color wipes on Strings1 and 2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    //   And update String3
    //   String3.Update();
  }
  else // Nothing Pressed - Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;

    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);

    // And update String3;
    //   String3.ActivePattern = CANDY_CANE;
    //   String3.Update();
  }
}

//------------------------------------------------------------
// Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Return to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Return to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  if (String3.SetCount < String3.Sets) {
    //   Set a New Random Color for the next Set
    String3.Stripe1 = String3.Wheel(random(255));
    String3.Stripe2 = (0, 0, 0);
    String3.SetCount ++;
  } else {
   //  Reset to Default Candy Cane Colors 
    String3.SetCount = 0;
    String3.CandyCane(5, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127)); // Reset Back to Red/White;
  }
}
// END OF PROGRAM;

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Mon Dec 07, 2015 8:37 pm

Here is a video of the Multitasking Candy Cane program running on an Arduino TinkerKit (Leonardo clone) driving three separate 50 LED WS2812b strips. By lowering the intensity of all of the pixels (built in to the script) the entire display is powered by a 2.4A USB tablet charger.https://www.youtube.com/watch?v=kdW8WcS7ETA
Here is the program (Arduino sketch): http://pastebin.com/ww7eN4Hu

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Wed Oct 26, 2016 6:29 pm

New Direction - Improved Pattern Switcher for Leonardo running WS2811/2812 60 LED Neopixel strip - includes Cylon_Eye and twelve other patterns. With the intensity controlled in software, this runs on a 2.6 amp USB charger. The button will cycle through the patterns - leave it alone, they cycle randomly.

Code: Select all | TOGGLE FULL SIZE

/* ============================================================================================================================

Sketch uses 11,946 bytes (41%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After Adding  [ strip.setBrightness(64);] to setup();
Sketch uses 12,086 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After Adding YELLOW & PURPLE to Mark Program Steps
Sketch uses 12,102 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After Adding Arduino LED_PIN 13
Sketch uses 12,126 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After Adding chk_BTN return to the RainbowCycle functions
Sketch uses 12,194 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After Adding chk_BTN return to the TheaterChase functions
Sketch uses 12,208 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After MOVING the chk_BTN to Inside the neopixel color loops [THIS WORKS ! MUST MODIFY ALL PATTERN FUNCTIONS]
Sketch uses 12,210 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After MOVING the chk_BTN to Inside the neopixel color loops [THIS WORKS ! MODIFIED SCANNER PATTERN FUNCTIONS]
Sketch uses 12,234 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After MOVING the chk_BTN to TOP of Each LOOP or FUNCTION
Sketch uses 12,220 bytes (42%) of program storage space. Maximum is 28,672 bytes.
Global variables use 194 bytes (7%) of dynamic memory, leaving 2,366 bytes for local variables. Maximum is 2,560 bytes.

After ADDING the CylonEye Functions
Sketch uses 14,018 bytes (48%) of program storage space. Maximum is 28,672 bytes.
Global variables use 202 bytes (7%) of dynamic memory, leaving 2,358 bytes for local variables. Maximum is 2,560 bytes.

After ADDING chk_BTN to the CylonEye Functions
Sketch uses 14,062 bytes (49%) of program storage space. Maximum is 28,672 bytes.
Global variables use 202 bytes (7%) of dynamic memory, leaving 2,358 bytes for local variables. Maximum is 2,560 bytes.
============================================================================================================================== */

/*
 WS2811/WS2812 Neopixel pattern switcher for ATtiny85 (and Arduino)
 Requires Adafruit NeoPixel Library
 WS2811 Signal, Digital Pin 4
 Button, Digital Pin 0
 GPL v3
*/

/*
shin:random pattern selector
*/

// Arduino pin number. Pin 13 will blink the on-board LED.
#define LED_PIN (13)


#include <Adafruit_NeoPixel.h>
#define Brightness 10 //Set brightness to 1/10th of maximum
#define Full (255/Brightness)


// Define
#define NUM_LEDS 60   //  60 LED per strip
#define DATA_PIN 6   //  OUTPUT pin on Leonardo
#define BTN_PIN A2   //  INPUT pin on Leonardo for BUTTON Switch
#define BTN_DELAY 250 //  Delay for Debounce on Input Switch
#define NUM_PATTERNS 13 // Number of Patterns Available
#define CTR_THRESH 16 //

// Init Vars
uint8_t j = 0;
uint8_t pattern = 1;
uint8_t buttonState = 0;
uint8_t lastPix = 0;
uint8_t myPix = 0;
uint8_t direction = 1;
uint8_t counter = 0;
uint8_t colors[3];
uint32_t setColor = 0;
unsigned long mark;

//Settings:
//#define PIN 6 //The Pin out your Neopixel DIN strip/stick is connected to (Default is 6)
//#define TPIXEL 60 //The total amount of pixel's/led's in your connected strip/stick (Default is 60)
int wait_T = 40; //This is the delay between moving back and forth and per pixel
int PixelCount = 60; //Set this to the AMOUNT of Led's/Pixels you have or want to use on your strip And It can be used to tell where to Stop then return the eye at in the strip
int Pixel_Start_End = 0; //Set this to where you want it to Start/End at
boolean UsingBar = true; //Set this to true If you are using the 8x1 Neopixel Bar Or you want to only use 3 leds for the scanner.

// Start Strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);

/* ========================================= SETUP - RUNS ONCE ===================================== */
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(LED_PIN, OUTPUT);

  //pinMode(BTN_PIN, INPUT);
  randomSeed(BTN_PIN);

  strip.setBrightness(64);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  CylonEye ();
}

/* ========================================= MAIN PROGRAM LOOP ===================================== */
void loop() {
  // chk_BTN(digitalRead(BTN_PIN));
  // if button pressed, advance, set mark
  // METHOD TO CHECK BUTTON - ACTS LIKE A FUNCTION

  int rand = random(1, 13); // 1to12
  // if pattern greater than #pattern reset
  // if (pattern > NUM_PATTERNS) { pattern = 1; }
  if (rand > NUM_PATTERNS) {
    pattern = 1;
  }

  // choose a pattern
  // pickPattern(pattern);
  pickPattern(rand);

  // Set Direction for Pattern
  if (direction == 1) {
    j++;
  } else {
    j--;
  }

  if (j > 254) {
    direction = 0;
  }
  if (j < 1) {
    direction = 1;
  }

}

/* Check Input Button State */
boolean chk_BTN(int buttonState) {
  if (buttonState != LOW && (millis() - mark) > BTN_DELAY) {
    // BUTTON IS NORMALLY LOW - ACTIVE WHEN HIGH
    digitalWrite(LED_PIN, HIGH);   // Display Button Status - Turn 'ON' LED (HIGH is the voltage level)
    j = 0;
    mark = millis();
    pattern++;
    return true;
  }
  else {
    digitalWrite(LED_PIN, LOW);   // turn the LED on (HIGH is the voltage level)
    return false;
  }
}

/* pick a pattern */
void pickPattern(uint8_t var) {
  switch (var) {
    case 1:
      // scanner, color and delay - RGB
      scanner(strip.Color(200, 0, 0), 50);
      scanner(strip.Color(0, 200, 0), 50);
      scanner(strip.Color(0, 0, 200), 50);
      break;

    case 2:
      // color wipe random RGB
      colorWipe(strip.Color(random(255), random(255), random(255)), 50);
      break;

    case 3:
      // color wave - Hue/Sat/Bright
      // hue low (0-359), high (0-359),rate,extra delay
      wavey(200, 240, 0.06, 0);
      break;

    case 4:
      // rainbow firefly, 1px at random
      colorFirefly(60);
      counter++;
      break;

    case 5:
      // rainbow solid
      rainbow(10);
      counter++;
      break;

    case 6:
      // bounce in and out
      // tail len, counter, delay
      bounceInOut(4, counter, 20);
      counter++;
      break;

    case 7:
      // color wipe from center
      colorWipeCenter(strip.Color(255, 0, 0), 100);
      colorWipeCenter(strip.Color(255, 64, 0), 100);
      break;

    case 8:
      // solid color
      colorFast(strip.Color(255, 255, 255), 0);
      break;

    case 9:
      // fade even or odd
      // 0-359 Hue value, even/odd, delay
      fadeEveOdd(200, 0, 20);
      fadeEveOdd(300, 1, 20);
      break;

    case 10:
      // show rainbow
      rainbowCycle(10);
      break;

    case 11:
      // show rainbow
      theaterChaseRainbow(50);
      break;

    case 12:
      rainbowCycle2(20);
      break;

    case 13:
      CylonEye();
      break;
  }
}


void colorFirefly(int wait) {
  if (myPix != lastPix) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    if (counter < CTR_THRESH) {
      float colorV = sin((6.28 / 30) * (float)(counter)) * 255;
      HSVtoRGB((359 / CTR_THRESH)*counter, 255, colorV, colors);
      strip.setPixelColor(myPix, colors[0], colors[1], colors[2]);
      strip.show();
      delay(wait);

    } else {
      lastPix = myPix;
      counter = 0;
      colorFast(0, 0);
    }
  } else {
    myPix = random(0, strip.numPixels());
  }
}

// Fill the dots one after the other with a color
// Modified from Neopixel sketch to Break on Button Press

void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// color wipe from center
void colorWipeCenter(uint32_t c, uint8_t wait) {
  uint8_t mid = strip.numPixels() / 2;
  strip.setPixelColor(mid, c);
  for (uint16_t i = 0; i <= strip.numPixels() / 2; i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    strip.setPixelColor(mid + i, c);
    strip.setPixelColor(mid - i, c);
    strip.show();
    delay(wait);
  }
}

// fast version
void colorFast(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    strip.setPixelColor(i, c);
  }
  strip.show();
  delay(wait);


}

// Rainbow Cycle, modified from Neopixel sketch to Break on Button Press
void rainbowCycle(uint8_t wait) {
  uint16_t i;
  //  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
  for (i = 0; i < strip.numPixels(); i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    delay(wait);

    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
  }
  if (chk_BTN(digitalRead(BTN_PIN))) {
    return;
  }
  strip.show();
}

void rainbow(uint8_t wait) {
  uint16_t i;
  //for(j=0; j<256; j++) {
  for (i = 0; i < strip.numPixels(); i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    strip.setPixelColor(i, Wheel((i + j) & 255));
  }
  if (chk_BTN(digitalRead(BTN_PIN))) {
    return;
  }
  strip.show();
  delay(wait);
}

// Scanner
void scanner(uint32_t c, uint8_t wait) {
  for (int i = 0; i < strip.numPixels(); i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    colorFast(0, 0);
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
  for (int i = strip.numPixels(); i > 0; i--) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    colorFast(0, 0);
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// Scanner to Midpoint
void bounceInOut(uint8_t num, uint8_t start, uint8_t wait) {
  colorFast(0, 0);
  uint8_t color = 200;
  for (int q = 0; q < num; q++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    if (strip.numPixels() - start >= 0 && start < NUM_LEDS) {

      strip.setPixelColor(start + q, strip.Color(0, color, 0));
      strip.setPixelColor(strip.numPixels() - start - q, strip.Color(0, color, 0));
    }
    color = round(color / 2.0);
    strip.show();
    delay(wait);
  }
  if (counter > strip.numPixels()) {
    counter = 0;
  }
}

void fadeEveOdd(int c1, byte rem, uint8_t wait) {
  for (int j = 0; j < CTR_THRESH; j++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    for (int i = 0; i < strip.numPixels(); i++) {
      if (i % 2 == rem) {
        HSVtoRGB(c1, 255, (255 / CTR_THRESH)*j, colors);
        strip.setPixelColor(i, colors[0], colors[1], colors[2]);
      }
    }

    strip.show();
    delay(wait);
  }
  for (int j = CTR_THRESH; j >= 0; j--) {
    for (int i = 0; i < strip.numPixels(); i++) {
      if (chk_BTN(digitalRead(BTN_PIN))) {
        break;
      }
      if (i % 2 == rem) {
        HSVtoRGB(c1, 255, (255 / CTR_THRESH)*j, colors);
        strip.setPixelColor(i, colors[0], colors[1], colors[2]);
      }
    }
    strip.show();
    delay(wait);

  }
}

// Twinkle Random Number of Pixels
void twinkleRand(int num, uint32_t c, uint32_t bg, int wait) {
  // set background
  colorFast(bg, 0);
  // for each num
  for (int i = 0; i < num; i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    delay(wait);
    strip.setPixelColor(random(strip.numPixels()), c);
  }
  strip.show();
  delay(wait);
}

// Sine Wave, low (0-359),high (0-359), rate of change, wait
void wavey(int low, int high, float rt, uint8_t wait) {
  scanner(strip.Color(100, 100, 0), 50); // YELLOW;
  float in, out;
  int diff = high - low;
  int step = diff / strip.numPixels();
  for (in = 0; in < 6.283; in = in + rt) {
    for (int i = 0; i < strip.numPixels(); i++) {
      out = sin(in + i * (6.283 / strip.numPixels())) * diff + low;
      HSVtoRGB(out, 255, 255, colors);
      strip.setPixelColor(i, colors[0], colors[1], colors[2]);
    }
    strip.show();
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    delay(wait);

  }
}

// Sine wave, Intensity
void waveIntensity(float rt, uint8_t wait) {

  scanner(strip.Color(100, 0, 100), 50); // DARKPURPLE;
  float in, level;
  for (in = 0; in < 6.283; in = in + rt) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    for (int i = 0; i < strip.numPixels(); i++) {
      // sine wave, 3 offset waves make a rainbow!
      level = sin(i + in) * 127 + 128;
      // set color level
      strip.setPixelColor(i, (int)level, 0, 0);
    }
    if (chk_BTN(digitalRead(BTN_PIN))) {
      break;
    }
    strip.show();
    delay(wait);

  }
}

// helpers

uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

// HSV to RGB colors
// hue: 0-359, sat: 0-255, val (lightness): 0-255
// adapted from http://funkboxing.com/wordpress/?p=1366
void HSVtoRGB(int hue, int sat, int val, uint8_t * colors) {
  int r, g, b, base;
  if (sat == 0) { // Achromatic color (gray).
    colors[0] = val;
    colors[1] = val;
    colors[2] = val;
  } else {
    base = ((255 - sat) * val) >> 8;
    switch (hue / 60) {
      case 0:
        colors[0] = val;
        colors[1] = (((val - base) * hue) / 60) + base;
        colors[2] = base;
        break;
      case 1:
        colors[0] = (((val - base) * (60 - (hue % 60))) / 60) + base;
        colors[1] = val;
        colors[2] = base;
        break;
      case 2:
        colors[0] = base;
        colors[1] = val;
        colors[2] = (((val - base) * (hue % 60)) / 60) + base;
        break;
      case 3:
        colors[0] = base;
        colors[1] = (((val - base) * (60 - (hue % 60))) / 60) + base;
        colors[2] = val;
        break;
      case 4:
        colors[0] = (((val - base) * (hue % 60)) / 60) + base;
        colors[1] = base;
        colors[2] = val;
        break;
      case 5:
        colors[0] = val;
        colors[1] = base;
        colors[2] = (((val - base) * (60 - (hue % 60))) / 60) + base;
        break;
    }

  }
}

//Theatre-style Crawling Lights with Rainbow Effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }

      strip.show();
      delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle2(uint8_t wait) {

  uint16_t i, j;

  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}


/* CYLON EYE PATTERN  */
void CylonEye () {

  for (int l = 0; l < 2; l++) {
    //Example: CylonEyeUp(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeUp(strip.Color(175, 0, 0), strip.Color(25, 0, 0), strip.Color(10, 0, 0), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
    //Example: CylonEyeDown(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeDown(strip.Color(175, 0, 0), strip.Color(25, 0, 0), strip.Color(10, 0, 0), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
  }
  for (int l = 0; l < 2; l++) {
    //Example: CylonEyeUp(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeUp(strip.Color(0, 175, 0), strip.Color(0, 25, 0), strip.Color(0, 10, 0), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
    //Example: CylonEyeDown(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeDown(strip.Color(0, 175, 0), strip.Color(0, 25, 0), strip.Color(0, 10, 0), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
  }
  for (int l = 0; l < 2; l++) {
    //Example: CylonEyeUp(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeUp(strip.Color(0, 0, 175), strip.Color(0, 0, 25), strip.Color(0, 0, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
    //Example: CylonEyeDown(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeDown(strip.Color(0, 0, 175), strip.Color(0, 0, 25), strip.Color(0, 0, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
  }
  for (int l = 0; l < 2; l++) {
    //Example: CylonEyeUp(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeUp(strip.Color(175, 0, 0), strip.Color(0, 25, 0), strip.Color(0, 0, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
    //Example: CylonEyeDown(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeDown(strip.Color(175, 0, 0), strip.Color(0, 25, 0), strip.Color(0, 0, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
  }
  for (int l = 0; l < 2; l++) {
    //Example: CylonEyeUp(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeUp(strip.Color(175, 175, 175), strip.Color(25, 25, 25), strip.Color(10, 10, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
    //Example: CylonEyeDown(Center_Dot_Color, Second_Dot_color, Third_Dot_color, wait_T, PixelCount, Pixel_Start_End);
    CylonEyeDown(strip.Color(175, 175, 175), strip.Color(25, 25, 25), strip.Color(10, 10, 10), wait_T, PixelCount, Pixel_Start_End);
    delay(wait_T);
  }
}

void CylonEyeUp(uint32_t Co, uint32_t Ct, uint32_t Ctt, uint8_t Delay, int TotalPixels, int pStart) {
  for (int i = pStart; i < TotalPixels; i++) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    if (!UsingBar) {
      strip.setPixelColor(i + 2, Ctt);  //Third Dot Color
    }
    strip.setPixelColor(i + 1, Ct); //Second Dot Color
    strip.setPixelColor(i, Co);     //Center Dot Color
    strip.setPixelColor(i - 1, Ct); //Second Dot Color
    if (!UsingBar) {
      strip.setPixelColor(i - 2, Ctt);  //Third Dot Color
    }

    if (!UsingBar) {
      strip.setPixelColor(i - 3, strip.Color(0, 0, 0)); //Clears the dots after the 3rd color
    } else {
      strip.setPixelColor(i - 2, strip.Color(0, 0, 0)); //Clears the dots after the 2rd color
    }
    strip.show();
    //Serial.println(i); //Used For pixel Count Debugging
    delay(Delay);

  }
}


void CylonEyeDown(uint32_t Co, uint32_t Ct, uint32_t Ctt, uint8_t Delay, int TotalPixels, int pEnd) {
  for (int i = TotalPixels - 1; i > pEnd; i--) {
    if (chk_BTN(digitalRead(BTN_PIN))) {
      return;
    }
    if (!UsingBar) {
      strip.setPixelColor(i - 2, Ctt);  //Third Dot Color
    }
    strip.setPixelColor(i - 1, Ct); //Second Dot Color
    strip.setPixelColor(i, Co);    //Center Dot Color
    strip.setPixelColor(i + 1, Ct); //Second Dot Color
    if (!UsingBar) {
      strip.setPixelColor(i + 2, Ctt);  //Third Dot Color
    }

    if (!UsingBar) {
      strip.setPixelColor(i + 3, strip.Color(0, 0, 0)); //Clears the dots after the 3rd color
    } else {
      strip.setPixelColor(i + 2, strip.Color(0, 0, 0)); //Clears the dots after the 2rd color
    }
    strip.show();
    //Serial.println(i); //Used For pixel Count Debugging
    delay(Delay);
  }
}


adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Mon Nov 21, 2016 11:09 pm

New Version of the Cylon Eye/Larson Scanner - Does NOT use Delay, has variable speed and colors.

Code: Select all | TOGGLE FULL SIZE
/* =====================================================================================

MODIFIED AND REVISED BY J.G.SMIRNIOTOPOULOS

Sketch uses 3,092 bytes (9%) of program storage space. Maximum is 32,256 bytes.
Global variables use 43 bytes (2%) of dynamic memory, leaving 2,005 bytes for local variables. Maximum is 2,048 bytes.

Multiple Reps * numPixels
Sketch uses 6,874 bytes (23%) of program storage space. Maximum is 28,672 bytes.
Global variables use 185 bytes (7%) of dynamic memory, leaving 2,375 bytes for local variables. Maximum is 2,560 bytes.

Multiple (Reps+1) * N_LEDS
Sketch uses 6,862 bytes (23%) of program storage space. Maximum is 28,672 bytes.
Global variables use 185 bytes (7%) of dynamic memory, leaving 2,375 bytes for local variables. Maximum is 2,560 bytes.

Multiple (2 * Reps) * N_LEDS
Sketch uses 6,910 bytes (24%) of program storage space. Maximum is 28,672 bytes.
Global variables use 185 bytes (7%) of dynamic memory, leaving 2,375 bytes for local variables. Maximum is 2,560 bytes.

Added Starting Pixel Reset, Adjusted Out Loop to Match Pos limit Size of num_LEDS - 2
Sketch uses 6,930 bytes (24%) of program storage space. Maximum is 28,672 bytes.
Global variables use 187 bytes (7%) of dynamic memory, leaving 2,373 bytes for local variables. Maximum is 2,560 bytes.

Changed Delay to Variable
Sketch uses 6,984 bytes (24%) of program storage space. Maximum is 28,672 bytes.
Global variables use 187 bytes (7%) of dynamic memory, leaving 2,373 bytes for local variables. Maximum is 2,560 bytes.

Changed Delay to millis()
Sketch uses 7,116 bytes (24%) of program storage space. Maximum is 28,672 bytes.
Global variables use 191 bytes (7%) of dynamic memory, leaving 2,369 bytes for local variables. Maximum is 2,560 bytes.

Revised while millis() replacement for delay
Sketch uses 7,124 bytes (24%) of program storage space. Maximum is 28,672 bytes.
Global variables use 195 bytes (7%) of dynamic memory, leaving 2,365 bytes for local variables. Maximum is 2,560 bytes.

===================================================================================== */

#include <Adafruit_NeoPixel.h>

long prevTime = 0;
long interval = 1000;

// Arduino pin number. Pin 13 will blink the on-board LED.
#define LED_PIN (13)

#define N_LEDS 60 // Number of LEDS in the String or Strip
#define PIN     6 // Arduino OUTPUT Pin

int FrameRate = 25; // FRAMES PER SECOND
int wait_T = 1000 / FrameRate; // This is the delay period between Writing each FRAME to LED Strip
int Start = 0 ; // Starting Pixel for Each Sequence

unsigned long currentTime = millis(); // Get current time

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  // initialize digital pin 13 as an output.
  pinMode(LED_PIN, OUTPUT);

  strip.begin();
}

int pos = 0, dir = 1; // Position, direction of "eye"
int reps; // Number of Repetitions of Pattern Sequence

void loop() {
  //cylon( reps, Main Color, Nearest Neighbor, End Neighbor, Speed);
  cylon(1, strip.Color(175, 0, 0), strip.Color(30, 0, 0), strip.Color(10, 0, 0), (wait_T / 4)); // RED Eye
  cylon(2, strip.Color(0, 175, 0), strip.Color(0, 30, 0), strip.Color(0, 10, 0), wait_T); // GREEN Eye
  cylon(3, strip.Color(0, 0, 175), strip.Color(0, 0, 30), strip.Color(0, 0, 10), (2 * wait_T)); // BLUE Eye

}

void cylon(int reps, uint32_t Co, uint32_t Ct, uint32_t Ctt, uint8_t Delay) {

  pos = Start; // RESET Position - Optional to Start Each Sequence at Same Point
  for (int r = 0; r < (2 * reps) * (N_LEDS - 2); r++) {
    int j;
    // Draw 5 pixels centered on pos.  setPixelColor() will clip any
    // pixels off the ends of the strip, we don't need to watch for that.
    strip.setPixelColor(pos - 2, Ctt); // End Neighbor
    strip.setPixelColor(pos - 1, Ct); // Nearest Neighbor
    strip.setPixelColor(pos    , Co); // Center Color
    strip.setPixelColor(pos + 1, Ct); // Nearest Neighbor
    strip.setPixelColor(pos + 2, Ctt); // End Neighbor

    strip.show(); // PAINT ALL THE PIXELS AS SET ABOVE

    //    delay(Delay); // Delay Between FRAMES - Should REPLACE THIS with millis(0)

    while (currentTime - prevTime < Delay) {
      // Do Nothing - essentially delay or wait here until time passes
      currentTime = millis(); // Get current time
    }
    if (currentTime - prevTime >= Delay) {
      prevTime = currentTime;
    }

    // Rather than being sneaky and erasing just the tail pixel,
    // it's easier to erase it all and draw a new one next time.
    for (j = -2; j <= 2; j++) strip.setPixelColor(pos + j, 0);

    // Bounce off ends of strip
    pos += dir;
    if (pos < 0) {
      pos = 1;
      dir = -dir;
      digitalWrite(LED_PIN, LOW);   // Turn 'OFF' the LED (LOW is the voltage level)
    } else if (pos >= strip.numPixels()) {
      pos = strip.numPixels() - 2;
      dir = -dir;
      digitalWrite(LED_PIN, HIGH);   // Turn 'ON' LED (HIGH is the voltage level)
    }
  }
}

adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Re: Adding New Patterns to Bill Earl's Multitasking Pt3 Neop

by adavegetable on Thu Nov 22, 2018 8:54 am

Updated Xmas Christmas Tree Mutli-tasking - modified for newer Arduino IDE - Video https://www.youtube.com/watch?v=uFzPAEqjF38
Code: Select all | TOGGLE FULL SIZE
/*
Run Multiple Neopixel WS2812 Patterns Simultaneously
Modified from Bill Earl's  Adafruit Multitasking Tutorial (which is excellent!)
Includes a Candy Cane Pattern that reverses, Runs a Controlled Number of Repetitions,
then Changes Colors, then Resets to start over again
*/

/*
Sketch uses 9,524 bytes (33%) of program storage space. Maximum is 28,672 bytes.
Global variables use 339 bytes (13%) of dynamic memory, leaving 2,221 bytes for local variables. Maximum is 2,560 bytes.
*/

/*
Compiled and Uploaded 12 November 2018
Board - Arduino Leonardo (TinkerKitLCD)
Programmer - USBTinyISP
Port - Arduino Leonardo on COM38

Sketch uses 10,322 bytes (36%) of program storage space. Maximum is 28,672 bytes.
Global variables use 354 bytes (13%) of dynamic memory, leaving 2,206 bytes for local variables. Maximum is 2,560 bytes.
*/

#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, CANDY_CANE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Patern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - Derived from the Adafruit_NeoPixel class
// PUBLIC Variables and Functions are available everywhere - otherwise, ERRORS!
class NeoPatterns : public Adafruit_NeoPixel
{
  public:

    // Member Variables:
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern

    unsigned long Interval;   // milliseconds between updates - essentially, the FRAME RATE
    unsigned long lastUpdate; // Last Update of position

    uint32_t Color1, Color2;  // What Colors are in use
    uint16_t TotalSteps;  // Total Number of Steps in the Pattern
    uint16_t Index;  // Current Step Within the Pattern - Which FRAME

    uint32_t Stripe1, Stripe2;  // What Colors are in use for Candy Cane Patterns
    int Width; // Width for Candy Cane Stripes in Pixels
    int Offset; // Offset for Pattern Start
    int Sets; // Number of Repetitions of This Pattern
    int SetCount; // Count Repetitions of Current Pattern Set

    void (*OnComplete)();  // Callback on Completion of Pattern

    // Constructor - Calls base-class Constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
      : Adafruit_NeoPixel(pixels, pin, type)
    {
      OnComplete = callback;
    }

    // Update the pattern
    void Update()
    {
      if ((millis() - lastUpdate) > Interval) // Time to Update?
      {
        lastUpdate = millis();
        switch (ActivePattern)
        {
          case CANDY_CANE:
            CandyCaneUpdate();
            break;
          case RAINBOW_CYCLE:
            RainbowCycleUpdate();
            break;
          case THEATER_CHASE:
            TheaterChaseUpdate();
            break;
          case COLOR_WIPE:
            ColorWipeUpdate();
            break;
          case SCANNER:
            ScannerUpdate();
            break;
          case FADE:
            FadeUpdate();
            break;
          default:
            break;
        }
      }
    }

    // Increment the Index Variable and Reset at the End of the Pattern (Number of Steps)
    void Increment()
    {
      if (Direction == FORWARD)
      {
        Index++; // Increment the INDEX
        if (Index >= TotalSteps)
        {
          Index = 0;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
      else // Direction == REVERSE
      {
        --Index; // Decrement the INDEX
        if (Index <= 0)
        {
          Index = TotalSteps - 1;
          if (OnComplete != NULL)
          {
            OnComplete(); // Call the Completion Callback
          }
        }
      }
    }

    // Reverse the Pattern Direction
    void Reverse()
    {
      if (Direction == FORWARD)
      {
        Direction = REVERSE;
        Index = TotalSteps - 1;
      }
      else
      {
        Direction = FORWARD;
        Index = 0;
      }
    }

    // Initialize the CandyCane Pattern
    /*  CandyCane CHASING COLOR STRIPES
    //   Create scrolling RED & WHITE - candy cane - stripes.
    //   Try adjusting the width in pixels for various results.
    //   Value "sets" should evenly divide into strand length
    //  EXAMPLE USAGE: CandyCane(30,8,50); //30 sets, 8 pixels wide, 50us delay
    */

#define Brightness 2 //Set brightness to fraction of FULL ON
#define Full (255/Brightness)

    void CandyCane(int sets, int width, uint8_t interval, uint32_t stripe1, uint32_t stripe2, direction dir = FORWARD)
    {
      ActivePattern = CANDY_CANE; // Names of this Pattern for other functions
      Interval = interval; // Speed of the Pattern
      TotalSteps = numPixels(); // Number of steps for this Pattern
      Stripe1 = stripe1; // Stripe Color1
      Stripe2 = stripe2; // Stripe Color2
      Index = 0;
      Direction = dir;
      Offset = 0; // Offset to start anywhere
      Sets = sets; // Number of sets for the pattern
      Width = width; // Width of the alternating Stripes
    }

    void CandyCaneUpdate()
    {
      int L;

      // Loop for Setting Pixel L Color;
      for (int i = 0; i < numPixels(); i++) {
        L = numPixels() - i - 1; // Which Pixel to Update;

        if ( ((Index + i) % ((Width * 2)) ) < (Width) ) {
          //setPixelColor(L, Full, 0, 0); // SET PIXEL L COLOR TO RED
          setPixelColor(L, Stripe1); // SET PIXEL L COLOR TO RED
        } else {
          //setPixelColor(L, Full, Full, Full); // SET PIXEL L COLOR TO WHITE
          setPixelColor(L, Stripe2); // SET PIXEL L COLOR TO WHITE
        }

      }; // End of Setting Pixel Color;
      show();
      //       delay(50);  // For Debugging;
      if (Index == (numPixels() - 1)) {
        if (Direction == FORWARD) {
          Direction = REVERSE;
        } else if (Direction == REVERSE) {
          Direction = FORWARD;
        }
      }
      Increment(); // Increment the Index for the Next Frame;
    }; // End of Function;


    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = RAINBOW_CYCLE;
      Interval = interval;
      TotalSteps = 255;
      Index = 0;
      Direction = dir;
    }

    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
      }
      show();
      Increment();
    }

    // Initialize for a Theater Chase
    void TheaterChase(uint32_t color1, uint32_t color2, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = THEATER_CHASE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if ((i + Index) % 3 == 0)
        {
          setPixelColor(i, Color1);
        }
        else
        {
          setPixelColor(i, Color2);
        }
      }
      show();
      Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = COLOR_WIPE;
      Interval = interval;
      TotalSteps = numPixels();
      Color1 = color;
      Index = 0;
      Direction = dir;
    }

    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
      setPixelColor(Index, Color1);
      show();
      Increment();
    }

    // Initialize for a SCANNNER
    void Scanner(uint32_t color1, uint8_t interval)
    {
      ActivePattern = SCANNER;
      Interval = interval;
      TotalSteps = (numPixels() - 1) * 2;
      Color1 = color1;
      Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    {
      for (int i = 0; i < numPixels(); i++)
      {
        if (i == Index)  // Scan Pixel to the right
        {
          setPixelColor(i, Color1);
        }
        else if (i == TotalSteps - Index) // Scan Pixel to the left
        {
          setPixelColor(i, Color1);
        }
        else // Fading tail
        {
          setPixelColor(i, DimColor(getPixelColor(i)));
        }
      }
      show();
      Increment();
    }

    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
      ActivePattern = FADE;
      Interval = interval;
      TotalSteps = steps;
      Color1 = color1;
      Color2 = color2;
      Index = 0;
      Direction = dir;
    }

    // Update the Fade Pattern
    void FadeUpdate()
    {
      // Calculate linear interpolation between Color1 and Color2
      // Optimise order of operations to minimize truncation error
      uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
      uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
      uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;

      ColorSet(Color(red, green, blue));
      show();
      Increment();
    }

    // Calculate 50% dimmed version of a color (Used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
      // Shift R, G and B components one bit to the right
      uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
      return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
      for (int i = 0; i < numPixels(); i++)
      {
        setPixelColor(i, color);
      }
      show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
      return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
      return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
      return color & 0xFF;
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85)
      {
        return Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      else if (WheelPos < 170)
      {
        WheelPos -= 85;
        return Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      else
      {
        WheelPos -= 170;
        return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      }
    }
};

//  Define some NeoPatterns used for any of the three Strings
//  as well as some completion routines
//  NeoPatterns Instantiate String by Name(number of LEDs, LED pin, Serial OUT COLOR Order & Frequency, Something Else);

/* 17NOV18 added these void declarations to fix "not declared in this scope" error msg */
void String1Complete();
void String2Complete();
void String3Complete();



NeoPatterns String1(50, 6, NEO_GRB + NEO_KHZ800, &String1Complete);
NeoPatterns String2(50, 5, NEO_GRB + NEO_KHZ800, &String2Complete);
NeoPatterns String3(50, 11, NEO_GRB + NEO_KHZ800, &String3Complete);

/*  STARTUP ROUTINES GO HERE  */
// Initialize everything and prepare to start
void setup()
{
  Serial.begin(115200);

  pinMode(8, INPUT_PULLUP); // Setup Button #1 on INPUT PIN #8
  pinMode(9, INPUT_PULLUP); // Setup Button #2 on INPUT PIN #9

  // Initialize all the pixelStrips
  String1.begin();
  String2.begin();
  String3.begin();

  //  Set Overall Intensity for the Entire String
  String1.setBrightness(50); // Set OVERALL BRIGHTNESS TO 20% (50/256)
  String2.setBrightness(50); // Set OVERALL BRIGHTNESS TO 20% (50/256)
  String3.setBrightness(50); // Set OVERALL BRIGHTNESS TO 20% (50/256)

  // Kick off a pattern for each String
  String1.TheaterChase(String1.Color(100, 0, 0), String1.Color(0, 75, 0), 100); //RED & GREEN
  String2.RainbowCycle(3);
  String2.Color1 = String1.Color1;
  //  String3.Scanner(String1.Color(255, 0, 0), 55);
  //  String3.TheaterChase(String3.Color(255, 255, 0), String3.Color(0, 0, 50), 100);
  String3.CandyCane(20, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127));
}

/*  MAIN PROGRAM LOOP - RUN ENDLESSLY  */
// Main loop
void loop()
{
  // Update the Strings on Every Loop.
  String1.Update();
  String2.Update();
  String3.Update();

  // Switch patterns on a button press:
  if (digitalRead(8) == LOW) // Button #1 Pressed;
  {
    // Switch String1 to FASE pattern
    String1.ActivePattern = FADE;
    String1.Interval = 20;
    // Speed up the rainbow on String2
    String2.Interval = 0;
    //   Set String3 to all red
    //   String3.ColorSet(String3.Color(255, 0, 0));
  }
  else if (digitalRead(9) == LOW) // Button #2 Pressed;
  {
    // Switch to alternating color wipes on String1 and String2
    String1.ActivePattern = COLOR_WIPE;
    String2.ActivePattern = COLOR_WIPE;
    String2.TotalSteps = String2.numPixels();
    //   And update String3
    //   String3.Update();
  }
  else // Nothing Pressed - Back to normal operation
  {
    // Restore all pattern parameters to normal values
    String1.ActivePattern = THEATER_CHASE;
    String1.Interval = 100;

    String2.ActivePattern = RAINBOW_CYCLE;
    String2.TotalSteps = 255;
    String2.Interval = min(10, String2.Interval);

    // And update String3;
    //   String3.ActivePattern = CANDY_CANE;
    //   String3.Update();
  }
}

//------------------------------------------------------------
// Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// String1 Completion Callback
void String1Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String2
    String2.Interval = 40;
    String1.Color1 = String1.Wheel(random(255));
    String1.Interval = 20000;
  }
  else  // Return to normal
  {
    String1.Reverse();
  }
}

// Ring 2 Completion Callback
void String2Complete()
{
  if (digitalRead(9) == LOW)  // Button #2 pressed
  {
    // Alternate color-wipe patterns with String1
    String1.Interval = 20;
    String2.Color1 = String2.Wheel(random(255));
    String2.Interval = 20000;
  }
  else  // Return to normal
  {
    String2.RainbowCycle(random(0, 10));
  }
}

// String3 Completion Callback
void String3Complete()
{
  if (String3.SetCount < String3.Sets) {
    //   Set a New Random Color for the next Set
    String3.Stripe1 = String3.Wheel(random(255));
    String3.Stripe2 = (0, 0, 0);
    String3.SetCount ++;
  } else {
    //  Reset to Default Candy Cane Colors
    String3.SetCount = 0;
    String3.CandyCane(5, 5, 100, String3.Color(127, 0, 0), String3.Color(127, 127, 127)); // Reset Back to Red/White;
  }
}
// END OF PROGRAM;


adavegetable
 
Posts: 18
Joined: Mon Jan 20, 2014 2:47 pm

Please be positive and constructive with your questions and comments.