Welcome to Synthiam!

The easiest way to program the most powerful robots. Use technologies by leading industry experts. ARC is a free-to-use robot programming software that makes servo automation, computer vision, autonomous navigation, and artificial intelligence easy.

Get Started
Asked — Edited
Resolved Resolved by RobertL184!

Help Connecting A Neopixel Ring

Hello all,

Has anyone used a NeoPixel Ring before. I can't figure out how to wire it or connect it to EZB. Here is a link to the NeoPixel Ring site it has a data sheet.
http://www.adafruit.com/product/1586

I have look at the I2C but not sure what address or how it is wired.

Thank you.


ARC Pro

Upgrade to ARC Pro

Harnessing the power of ARC Pro, your robot can be more than just a simple automated machine.

#54  
Hi @ all

i tryed the Code/script from Robert!

An i like it really much!

Everything works, but only the "Scanner"/"Knight rider" functions has some problems.

SendSerial( D18,9600,"S,255,0,0,20" )

If i change to some scripts and then back to the Scanner Script, often this Script not start, so the Neopixel Ring will be still black!


Boris
#55  
send a ("C0,0,0") to turn off the ring before sending another command.
It might be ("C,0,0,0"), i cant remember off the top of my head.
#56  
Hello David,

i check your tipp with sending a "turn light off" command, but the same situation with the scanner fx. All other Commands like Wipe, Rainbow, Color, Fade works 100% perfekt without sending a "light off" command, only the Scanner Command not works everytime.


Now i sending this code:

Code:


SendSerial(1. d0, 9600, "C0,0,0")
sleep(100)
SendSerial(1. d0, 9600, "S,255,0,0,40



and now its works like that:

one red pixel is turning on for one second and then tunring off. Thats it. I can repeat this 10 times, all time the same.


To correct this problem i must send some other commands like a "fade" or "wipe" and then again sending the "scanner" command and then he works.

If you don´t know, nevermind, all other commands works to 100%, i only wondering why only the scanner command no works. I think in the Arduino Code must be the mistake/error


Boris
#57  
@rentaprinta I originally put the arduino code together from examples on the adafruit site. (There are references in the posts.) I didn't have a neopixel ring to test it and still don't. It is quite possible that there is a mistake/error in the code. It seemed to solve the problem the original poster of this string of messages needed a fix for. So the poster was happy and I was glad I could help.
#58  
@RobertL184


Sorry for the question: So the best solution is , not to use the "scanner" fx or do you know a method or somebody what/who can fix the error?


Boris
#59  
@renta, I'm not sure what the Scanner FX looks like. Can you describe it? Maybe I have it in my Arduino sketch.
#60  
Hi Bob!

The Scanner FX is a red dot/pixel what starts on the left site and turn to the right and back to the left and so on.

Image the "Knight Rider" Light but not as a stripe - now in a circle.

Sometime the red light starts and make the moving, but sometime the red light goes on for one second and then goes off and thats it.

Like i said. all other oves like the Wipe;Fade;Rainbow,Color works fine! Only the Scanner makes problems!


Boris
#61  
@Renta, I hope this is the "Scanner FX you're looking for. I think we are using the same Arduino sketch, if not then it probably won't work - I could send you mine.

Try this, this will run indefinitely or until another command is sent,

Code:


SendSerial(1.D18, 9600, "W250,0,0,250,0,0")
SendSerial(1.D18, 9600, "C0,0,0")
SendSerial(1.D18, 9600, "S250,0,0,250,0,0")

If you want it run for a set period of time, Try this example, this will run for 60 seconds, then stop.

Code:


SendSerial(1.D18, 9600, "W250,0,0,250,0,0")
SendSerial(1.D18, 9600, "C0,0,0")
SendSerial(1.D18, 9600, "S250,0,0,250,0,0")
sleep(60000)
SendSerial(1.D18, 9600, "C0,0,0")


**Change the port to your setting**
#62  
@RobertL184
Hi Robert,
I tried your code for multitasking with a neopixel ring and no matter what input I use (C, R, F or T....) the pixels stay dark! I know the HW setup and connections are all correct. Am I missing something or there is something missing from the code?
In order to successfully compile the code I added

Code:

void Ring1Complete();

right above the neoPatterns
Also, added

Code:

Ring1.setBrightness(50);

to set overal brightness

And my final question is:
I have added a potentiometer to Arduino multi-tasking code part-3 which is working fine. The pot is for controlling the brightness, however I would like to learn how to remove serial input from your code and make it go through all the animations steps within the loop. I now I can use the strandtest to achieve my goal, but then due to delay() I have to wait for the entire loop to complete before seeing the new brightness setting (through potentiometer).

Thanks,
Ron
#64  
@RobertL184
Thank you for your quick reply. I'm sorry if I was not clear with question.
I have the pot working with the Adafruit multi-tasking part-3 and it's responsive.
I would like to get your code working for my project and the issue I am running into is that all LEDs are dark and I have combed through the code and I was not able to find the culprit.

BTW - I added my potentiometer code to your code and monitored it via serial UI and it's working.
I would like to know if there is anything missing from the code causing the ring to stay dark. If not, then I am doing something wrong.

Thanks
#65  
If nothing with my code seems to make the neopixels work it may be that the neopixel data pin is different than what you have wire up.

The mulitasking code has a strand on pins 5,6, and 7

NeoPatterns Ring1(24, 5, NEO_GRB + NEO_KHZ800, &Ring1Complete);
NeoPatterns Ring2(16, 6, NEO_GRB + NEO_KHZ800, &Ring2Complete);
NeoPatterns Stick(16, 7, NEO_GRB + NEO_KHZ800, &StickComplete);

My code has the strand on pin 6

NeoPatterns Ring1(16, 6, NEO_GRB + NEO_KHZ800, &Ring1Complete);

So the first thing to check is that the NeoPattern Ring1 is being called with the correct pin number to match your wiring.

The second thing to note is that my code was hacked together to allow the EZ-B to control the neopixel strip. To get the arduino to light up the string you want to have the EZ-B send the arduino a command.

Like "F0,0,255,0,0,0,50,25,0" to have it do a fade.

The command for the EZ-B to do this is SendSerial(d0, 9600, "F0,0,255,0,0,0,50,25,0") assuming of course that the arduino is wired up to get serial data from the "d0" pin.

To try is you can use the serial monitor in the arduino IDE to send the serial string to the arduino.

If you don't want any serial control at all. The multitasking code should work for you.
#66  
Here is a version of my code with the larson scanner fixed.

Code:


/* real time Serial Controlled Neopixel Ring -- Code not tested yet
/
/ Serial Commands
/ Cr1,g1,b1 - Set whole Ring to same color specified by r1,g1,b1
/ Rt,d - Rainbow with interval t and direction d
/ Tr1,g1,b1,r2,g2,b2,t,d - Theater Chase between color r1,g1,b1 and color r2,g2,b2 with interval t and direction d
/ Wr1,g1,b1,t,d - Color Wipe in color r1,g1,b1 with interval t and direction d
/ Fr1,g1,b1,r2,g2,b2,s,t,d - Fade between color r1,g1,b1 and color r2,g2,b2 in s steps with interval t and direction d
/ Sr1,g1,b1,t - Scanner with color specified by r1,g1,b1 and interval t
/ Pp,r1,g1,b1 - Set individual pixel p to color specified by r1,g1,b1
/
/ p = pixel number
/ r1 = 1st color red values 0 to 255
/ g1 = 1st color greern values 0 to 255
/ b1 = 1st color blue values 0 to 255
/ r2 = 2nd color red values 0 to 255
/ g2 = 2nd color greern values 0 to 255
/ b2 = 2nd color blue values 0 to 255
/ s = number of steps
/ t = interval time values 0 to 255
/ d = direction 0 = Forward 1 = Backward
*/

#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum pattern { NONE, 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;
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;
}
}
//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// 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);
}
}
};
void Ring1Complete();

// Define some NeoPatterns for the two rings and the stick
// as well as some completion routines
NeoPatterns Ring1(16, 6, NEO_GRB + NEO_KHZ800, &Ring1Complete);

int red1 = 0; // red value
int green1 = 34; // green value
int blue1 = 12; // blue value
int red2 = 0; // red value
int green2 = 34; // green value
int blue2 = 12; // blue value
int my_pixel = 0; // pixel number
int s = 5; // step value
int t = 10; // interval time value
int d = 0; // direction indicator 0= Forward 1 = Backward

// Initialize everything and prepare to start
void setup()
{
Serial.begin(9600);
Serial.setTimeout(10); // set serial timeout

// Initialize all the pixelStrips
Ring1.begin();
Ring1.ColorSet(Ring1.Color(0, 0, 0));
}

// Main loop
void loop()
{
int inchar;

if (Serial.available() > 0) {
inchar = Serial.read();
if ( inchar == 'C') { // string should start with C
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
Ring1.ActivePattern = NONE;
Ring1.ColorSet(Ring1.Color(red1, green1, blue1));
}
if ( inchar == 'R') { // string should start with R
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.RainbowCycle(t, FORWARD);
} else {
Ring1.RainbowCycle(t, REVERSE);
}
}
if ( inchar == 'F') { // string should start with F
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
red2 = Serial.parseInt(); // then an ASCII number for red
green2 = Serial.parseInt(); // then an ASCII number for green
blue2 = Serial.parseInt(); // then an ASCII number for blue
s = Serial.parseInt(); // then an ASCII number for steps
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, FORWARD);
} else {
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, REVERSE);
}
}
if ( inchar == 'T') { // string should start with T
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
red2 = Serial.parseInt(); // then an ASCII number for red
green2 = Serial.parseInt(); // then an ASCII number for green
blue2 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, FORWARD);
} else {
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, REVERSE);
}
}
if ( inchar == 'W') { // string should start with W
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, FORWARD);
} else {
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, REVERSE);
}
}
if ( inchar == 'S') { // string should start with S
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), 50, 0);
Ring1.ColorSet(Ring1.Color(0,0, 0));
Ring1.Scanner(Ring1.Color(red1, green1, blue1), t);
}
if ( inchar == 'P') { // string should start with P
my_pixel = Serial.parseInt(); // then an ASCII number for pixwel
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
Ring1.ActivePattern = NONE;
Ring1.setPixelColor(my_pixel, Ring1.Color(red1, green1, blue1));
Ring1.show();
}
}

// Update the ring.
Ring1.Update();
}
// Ring1 Completion Callback
void Ring1Complete()
{
if ((Ring1.ActivePattern == RAINBOW_CYCLE) || (Ring1.ActivePattern == FADE) ||
(Ring1.ActivePattern == THEATER_CHASE) || (Ring1.ActivePattern == SCANNER)){
Ring1.Reverse();
}
}



I haven't tried the updated code with CochranRobotics EZ-B Plugin.
#67  
If you really want to use my code and don't want any serial input you need to replace the main loop with something like this:

Code:


void loop()
{
red1 = 255; // for red
green1 = 0; // for green
blue1 = 0; // for blue
red2 = 0; // for second red
green2 = 255; // for second green
blue2 = 0; // for second blue
t=100;
Ring1.ActivePattern = NONE;
Ring1.ColorSet(Ring1.Color(red1, green1, blue1));
Ring1.RainbowCycle(t, FORWARD);
Ring1.RainbowCycle(t, REVERSE);
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, FORWARD);
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, REVERSE);
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, FORWARD);
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, REVERSE);
Ring1.ActivePattern = NONE;
Ring1.ColorSet(Ring1.Color(red1, green1, blue1));
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, FORWARD);
Ring1.ActivePattern = NONE;
Ring1.ColorSet(Ring1.Color(red1, green1, blue1));
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, REVERSE);
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), 50, 0);
Ring1.ColorSet(Ring1.Color(0,0, 0));
Ring1.Scanner(Ring1.Color(red1, green1, blue1), t);
}


Modify the variables:

red1, green1, blue1, red2, blue2, green2, and t for the colors and delay time you want.

I haven't complied the code above so don't know as it will work without some debugging.

You didn't mention where you put the code to read you potentiometer and set the Brightness in the multitasking code, but you could most likely put it in the same place in my code. It is based on the multitasking code.

Remember setting the strand brightness reduces the number of colors available for the entire strand. The same effect can be had for most of the routines my simply changing the red1, green1, blue1, red2, blue2, green2 variable to smaller values. The exception to this is the rainbow routine which uses all of the colors. For that one routine the Brightness setting would work best.
#68  
@RobertL184

Robert,
Thank you for all your feedback and I will re-check the Arduino pin connection, but I am certain that is not the cause. When I change the

Code:

Ring1.ColorSet(Ring1.Color(0, 0, 0)); to Ring1.ColorSet(Ring1.Color(20, 0, 0));
the ring lights up. Also, I put few println in the code for sanity check and I see the output is the SUI.

Below is the code I added to yours and Arduino multi-tasking part-3 for the potentiometer and I know it works with the latter. The ints are placed under the NeoPatterns line and the rest is placed within the loop. I have Ring1,Ring2 and Stick for the Arduino multi-tasking and only Ring1 for your code.

Code:

void Ring1Complete();

int potPin = A0; // Potentiometer input
int potVal = 0; // Potentiometer value
int ringBrightness = 0; // Brightness of LEDs
int lastpot = 0; // last potentiometer reading to compair with

// Main loop
void loop()
{
potVal = analogRead(potPin);
if ( potVal != lastpot ) {
lastpot = potVal;
ringBrightness = map(potVal, 0, 1023, 0, 250);
Ring1.setBrightness(ringBrightness);
}


I will let you once I get everything working.
#69  
I've been trying to load the code from post # 37 and I get a bunch of error messages. It worked when it was first posted but I can get it to load now.
Could someone try loading it and see if it works.
Maybe it's my system, I don't know.

Thanks
#70  
To download this version of the Arduino IDE ==> (previous versions link)

I think it was 1.6.4 that I used back then but it has been a while since I have looked.

I think what is happening is that you have to use a previous version of the Arduino IDE in order to compile the code from that long ago. I think the link above will take you to the version that you would have to use. The later post should work with a more current version of the IDE.
#71  
From my plugin that uses this code...

"The code below works with Arduino IDE 1.6.3 with the 1.0.3 version of the Adafruit NeoPixel library,"
#72  
Thanks Dave. I installed Arduino IDE 1.6.3 and the sketch loaded OK and works good.
#73  
This sketch fixes a minor bug that existed in the last code published by RobertL184. It works with Arduino 1.8.3 and the NeoPixel library v1.1.1

If you want to change the pin that the arduino is connecting to the NeoPixel on, change the 2nd parameter in line 321. If you want to change the number of NeoPixles in the ring or device, change the first parameter in line 321.

Example

Code:


NeoPatterns Ring1(24, 6, NEO_GRB + NEO_KHZ800, &Ring1Complete);

is for a 24 pixel NeoPixel that has its input pin connected to pin 6 on the Arduino.

Code:


/* real time Serial Controlled Neopixel Ring -- Code not tested yet
/
/ Serial Commands
/ Cr1,g1,b1 - Set whole Ring to same color specified by r1,g1,b1
/ Rt,d - Rainbow with interval t and direction d
/ Tr1,g1,b1,r2,g2,b2,t,d - Theater Chase between color r1,g1,b1 and color r2,g2,b2 with interval t and direction d
/ Wr1,g1,b1,t,d - Color Wipe in color r1,g1,b1 with interval t and direction d
/ Fr1,g1,b1,r2,g2,b2,s,t,d - Fade between color r1,g1,b1 and color r2,g2,b2 in s steps with interval t and direction d
/ Sr1,g1,b1,t - Scanner with color specified by r1,g1,b1 and interval t
/ Pp,r1,g1,b1 - Set individual pixel p to color specified by r1,g1,b1
/
/ p = pixel number
/ r1 = 1st color red values 0 to 255
/ g1 = 1st color greern values 0 to 255
/ b1 = 1st color blue values 0 to 255
/ r2 = 2nd color red values 0 to 255
/ g2 = 2nd color greern values 0 to 255
/ b2 = 2nd color blue values 0 to 255
/ s = number of steps
/ t = interval time values 0 to 255
/ d = direction 0 = Forward 1 = Backward
*/

#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum pattern { NONE, 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;
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;
}
}
//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------

// 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);
}
}
};
void Ring1Complete();

// Define some NeoPatterns for the two rings and the stick
// as well as some completion routines
NeoPatterns Ring1(24, 6, NEO_GRB + NEO_KHZ800, &Ring1Complete);

int red1 = 0; // red value
int green1 = 34; // green value
int blue1 = 12; // blue value
int red2 = 0; // red value
int green2 = 34; // green value
int blue2 = 12; // blue value
int my_pixel = 0; // pixel number
int s = 5; // step value
int t = 10; // interval time value
int d = 0; // direction indicator 0= Forward 1 = Backward

// Initialize everything and prepare to start
void setup()
{
Serial.begin(9600);
Serial.setTimeout(10); // set serial timeout

// Initialize all the pixelStrips
Ring1.begin();
Ring1.ColorSet(Ring1.Color(0, 0, 0));
}

// Main loop
void loop()
{
int inchar;

if (Serial.available() > 0) {
inchar = Serial.read();
if ( inchar == 'C') { // string should start with C
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
Ring1.ActivePattern = NONE;
Ring1.ColorSet(Ring1.Color(red1, green1, blue1));
}
if ( inchar == 'R') { // string should start with R
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.RainbowCycle(t, FORWARD);
} else {
Ring1.RainbowCycle(t, REVERSE);
}
}
if ( inchar == 'F') { // string should start with F
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
red2 = Serial.parseInt(); // then an ASCII number for red
green2 = Serial.parseInt(); // then an ASCII number for green
blue2 = Serial.parseInt(); // then an ASCII number for blue
s = Serial.parseInt(); // then an ASCII number for steps
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, FORWARD);
} else {
Ring1.Fade(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), s, t, REVERSE);
}
}
if ( inchar == 'T') { // string should start with T
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
red2 = Serial.parseInt(); // then an ASCII number for red
green2 = Serial.parseInt(); // then an ASCII number for green
blue2 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, FORWARD);
} else {
Ring1.TheaterChase(Ring1.Color(red1, green1, blue1), Ring1.Color(red2, green2, blue2), t, REVERSE);
}
}
if ( inchar == 'W') { // string should start with W
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
d = Serial.parseInt(); // then an ASCII number for direction
if (d ==0) {
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, FORWARD);
} else {
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), t, REVERSE);
}
}
if ( inchar == 'S') { // string should start with S
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
t = Serial.parseInt(); // then an ASCII number for interval
Ring1.ColorWipe(Ring1.Color(red1, green1, blue1), 50, FORWARD);
Ring1.ColorSet(Ring1.Color(0,0, 0));
Ring1.Scanner(Ring1.Color(red1, green1, blue1), t);
}
if ( inchar == 'P') { // string should start with P
my_pixel = Serial.parseInt(); // then an ASCII number for pixwel
red1 = Serial.parseInt(); // then an ASCII number for red
green1 = Serial.parseInt(); // then an ASCII number for green
blue1 = Serial.parseInt(); // then an ASCII number for blue
Ring1.ActivePattern = NONE;
Ring1.setPixelColor(my_pixel, Ring1.Color(red1, green1, blue1));
Ring1.show();
}
}

// Update the ring.
Ring1.Update();
}
// Ring1 Completion Callback
void Ring1Complete()
{
if ((Ring1.ActivePattern == RAINBOW_CYCLE) || (Ring1.ActivePattern == FADE) ||
(Ring1.ActivePattern == THEATER_CHASE) || (Ring1.ActivePattern == SCANNER)){
Ring1.Reverse();
}
}


This will work with the plugin still. The commands don't change so there is no modification to the plugin.