Hi,
I am using a MSP430 and Energia to drive two neopixel sticks with eight LEDS on each. I am running into a weird error. I am a creating a class for each stick which will provide different animations. I am using a struct to hold the colour values. I am unable to get the two neopixel sticks to display different animations. What is weird is that if I remove the rainbow portion of the code, along with the structs it uses, I can get two different animations to display. When I add code back in line by line, I lose the multiple animations when adding the rainbow struct back in. I have a feeling that I am possibly not using structs the correctly, could there be a memory overflow that I am not aware of somehow? I have posted the code below, in the hopes that someone with more knowledge could shed some light on this.
Edit. I am able to get different animations on each neopixel stick, but only on four leds per stick. Am I running out of memory?
Thanks
Jason
#include <WS2811Driver.h>
// Pattern types supported:
enum pattern { NONE, BREATHE, RAINBOW };
enum direction { UP, DOWN };
boolean FadeDone = false;
typedef struct Colours
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint16_t hue; // 0-360
uint8_t sat; // 0 is pure white light
uint8_t val; // Brightness
} ;
class animateStrip : public WS2811Driver
{
//*************************************************************************
// Class Initialisation
//*************************************************************************
public:
pattern CurrentPattern; // Which pattern is running
direction Direction;
unsigned long Interval; // Delay time
unsigned long LastUpdate; // Time of last update
Colours RGB;
Colours rainbowStart_RGB;
Colours rainbowCurr_RGB;
Colours rainbowEnd_RGB;
uint8_t TotalSteps; // Steps in the animation
uint8_t Index;
void (*OnComplete)();
animateStrip(uint8_t pixels, uint8_t pin, uint8_t type, void (*callback)()):WS2811Driver(pixels, pin, type)
{
OnComplete = callback;
}
//*************************************************************************
// Update and state tracking functions
//*************************************************************************
void Update()
{
if((millis() - LastUpdate) > Interval) // time to update
{
LastUpdate = millis();
switch(CurrentPattern)
{
case BREATHE:
BreatheUpdate();
break;
case RAINBOW:
RainbowUpdate();
break;
}
}
}
void Increment()
{
if (Direction == UP)
{
Index++;
if (Index >= TotalSteps)
{
Index = 0;
FadeDone = true;
if (OnComplete != NULL)
{
OnComplete(); // call the comlpetion callback
}
}
}
else // Direction == DOWN
{
--Index;
if (Index <= 0)
{
Index = TotalSteps-1;
FadeDone = true;
if (OnComplete != NULL)
{
OnComplete(); // call the comlpetion callback
}
}
}
}
// Reverse pattern direction
void Reverse()
{
if (Direction == UP)
{
Direction = DOWN;
Index = TotalSteps-1;
}
else
{
Direction = UP;
Index = 0;
}
}
//*************************************************************************
// Animation functions
//*************************************************************************
void Breathe(uint16_t delayTime, uint8_t Colour) // Initialise for a fade in
{
CurrentPattern = BREATHE;
Interval = delayTime;
TotalSteps = 255;
Index = 0;
RGB.hue = 0;
RGB.sat = 255;
RGB.val = 255;
}
// Do the actual fade in
void BreatheUpdate()
{
if (Index == 0) { RGB.hue = random(0,360); } // Add a random colour
setBrightness(Index);
RGB = HSVtoRGB2(RGB);
ColorSet(RGB);
Increment();
if (Index == 254) { Reverse(); }
}
void Rainbow(uint16_t steps, uint16_t delayTime)
{
CurrentPattern = RAINBOW;
Interval = delayTime;
TotalSteps = steps;
Index = 0;
rainbowStart_RGB.hue = random(0, 360);
rainbowStart_RGB.val = 255;
rainbowStart_RGB.sat = 255;
rainbowEnd_RGB.hue = 0;//random(0,360);
rainbowEnd_RGB.sat = 255;
rainbowEnd_RGB.val = 255;
rainbowStart_RGB = HSVtoRGB2(rainbowStart_RGB);
rainbowEnd_RGB = HSVtoRGB2(rainbowEnd_RGB);
}
void RainbowUpdate()
{
rainbowCurr_RGB.red = ((rainbowStart_RGB.red * (TotalSteps - Index)) + (rainbowEnd_RGB.red * Index))
/ TotalSteps;
rainbowCurr_RGB.green = ((rainbowStart_RGB.green * (TotalSteps - Index)) + (rainbowEnd_RGB.green * Index))
/ TotalSteps;
rainbowCurr_RGB.blue = ((rainbowStart_RGB.blue * (TotalSteps - Index)) + (rainbowEnd_RGB.blue * Index))
/ TotalSteps;
rainbowCurr_RGB.sat = 255;
rainbowCurr_RGB.val = 255;
ColorSet(rainbowCurr_RGB);
show();
Increment();
if (FadeDone)
{
rainbowStart_RGB = rainbowCurr_RGB;
rainbowEnd_RGB.hue = random(0,360);
rainbowEnd_RGB = HSVtoRGB2(rainbowEnd_RGB);
FadeDone = false;
}
}
//*************************************************************************
// Helper functions
//*************************************************************************
void ColorSet(Colours thisRGB)
// Sets all pixels to the same colour
{
for (int i = 0; i < numPixels(); i++)
{
setPixelColor(i, thisRGB.red, thisRGB.green, thisRGB.blue);
}
show();
}
Colours HSVtoRGB2(Colours rgb)
{
// hue: 0-359, sat: 0-255, val (lightness): 0-255
int r, g, b, base;
base = ((255 - rgb.sat) * rgb.val)>>8;
switch(rgb.hue/60) {
case 0:
r = rgb.val;
g = (((rgb.val-base)*rgb.hue)/60)+base;
b = base;
break;
case 1:
r = (((rgb.val-base)*(60-(rgb.hue%60)))/60)+base;
g = rgb.val;
b = base;
break;
case 2:
r = base;
g = rgb.val;
b = (((rgb.val-base)*(rgb.hue%60))/60)+base;
break;
case 3:
r = base;
g = (((rgb.val-base)*(60-(rgb.hue%60)))/60)+base;
b = rgb.val;
break;
case 4:
r = (((rgb.val-base)*(rgb.hue%60))/60)+base;
g = base;
b = rgb.val;
break;
case 5:
r = rgb.val;
g = base;
b = (((rgb.val-base)*(60-(rgb.hue%60)))/60)+base;
break;
}
rgb.red=r;
rgb.green=g;
rgb.blue=b;
return rgb;
}
// End of class
};
//*************************************************************************
// Setup and main functions
//*************************************************************************
animateStrip stick1(8, P1_4, NEO_GRB, &StickCompleteNOP);
animateStrip stick2(8, P2_4, NEO_GRB, &StickCompleteNOP);
void setup() {
stick1.begin();
stick2.begin();
stick1.Rainbow(20, 20);
stick2.Breathe(10, 10);
//Serial.begin(9600);
//Serial.println("Setup OK");
}
void loop() {
//Serial.println("Loop");
stick1.Update();
stick2.Update();
}
//*************************************************************************
// Completion functions
//*************************************************************************
void StickCompleteNOP()
{
return;
}