#include <FastLED.h>
#define LED_TYPE WS2811
#define NUM_LEDS_A 24
#define NUM_LEDS_B 24
#define NUM_LEDS_C 24
#define NUM_LEDS_D 24
#define NUM_LEDS_E 24
#define LED_PIN_A 3
#define LED_PIN_B 4
#define LED_PIN_C 5
#define LED_PIN_D 6
#define LED_PIN_E 7
#define COLOR_ORDER RGB
CRGB source1_A[NUM_LEDS_A];
CRGB source2_A[NUM_LEDS_A];
CRGB source1_B[NUM_LEDS_B];
CRGB source2_B[NUM_LEDS_B];
CRGB source1_C[NUM_LEDS_C];
CRGB source2_C[NUM_LEDS_C];
CRGB source1_D[NUM_LEDS_D];
CRGB source2_D[NUM_LEDS_D];
CRGB source1_E[NUM_LEDS_E];
CRGB source2_E[NUM_LEDS_E];
CRGB output_A[NUM_LEDS_A];
CRGB output_B[NUM_LEDS_B];
CRGB output_C[NUM_LEDS_C];
CRGB output_D[NUM_LEDS_D];
CRGB output_E[NUM_LEDS_E];
uint8_t blendAmount = 0;
uint8_t patternCounter = 0;
uint8_t source1Pattern = 0;
uint8_t source2Pattern = 1;
bool useSource1 = false;
bool receivedA = false; // Flag to indicate whether 'A' has been received
bool newData = false;
bool recvInProgress = false;
const byte numChars = 74;
char receivedChars[numChars]; // an array to store the received data
char tempChars[numChars];
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
#define MAX_ARRAY_SIZE 16
int colournumberArray[MAX_ARRAY_SIZE];
CRGBPalette16 currentPalette;
CRGBPalette16 randomPalette;
TBlendType currentBlending;
uint8_t gCurrentPatternNumber = 4; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
bool animate = true;
void setup() {
SetupTotallyRandomPalette();
FastLED.addLeds<LED_TYPE, LED_PIN_A, COLOR_ORDER>(output_A, NUM_LEDS_A);
FastLED.addLeds<LED_TYPE, LED_PIN_B, COLOR_ORDER>(output_B, NUM_LEDS_B);
FastLED.addLeds<LED_TYPE, LED_PIN_C, COLOR_ORDER>(output_C, NUM_LEDS_C);
FastLED.addLeds<LED_TYPE, LED_PIN_D, COLOR_ORDER>(output_D, NUM_LEDS_D);
FastLED.addLeds<LED_TYPE, LED_PIN_E, COLOR_ORDER>(output_E, NUM_LEDS_E);
FastLED.setMaxPowerInVoltsAndMilliamps(12,3000);
FastLED.setBrightness(96);
//Serial.begin(57600);
Serial.begin(115200);
Serial.println("Arduino is ready");
//currentPalette = RainbowColors_p;
currentBlending = NOBLEND;
nextPattern(gCurrentPatternNumber);
}
void loop() {
//Serial.println(recvInProgress);
recvWithStartEndMarkers();
if (newData == true) {
Serial.println("ready to parse");
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
Serial.println(tempChars);
parseData();
gCurrentPatternNumber = integerFromPC;
gHue = colournumberArray[0];
newData = false;
nextPattern(gCurrentPatternNumber);
}
if (!recvInProgress) {
//Serial.println("fastledprocessing");
EVERY_N_MILLISECONDS(10) {
//gHue++;
blend(source1_A, source2_A, output_A, NUM_LEDS_A, blendAmount);
blend(source1_B, source2_B, output_B, NUM_LEDS_B, blendAmount);
blend(source1_C, source2_C, output_C, NUM_LEDS_C, blendAmount);
blend(source1_D, source2_D, output_D, NUM_LEDS_D, blendAmount);
blend(source1_E, source2_E, output_E, NUM_LEDS_E, blendAmount);
if (useSource1) {
if (blendAmount < 255) blendAmount++; // Blend 'up' to source 2
} else {
if (blendAmount > 0) blendAmount--; // Blend 'down' to source 1
}
//Serial.print(blendAmount);
//Serial.print(" ");
//if(useSource1) Serial.println(260);
//else Serial.println(270);
}
//EVERY_N_SECONDS(120) {
nextPattern(gCurrentPatternNumber);
//}
runPattern(source1Pattern, source1_A, NUM_LEDS_A); // Run all patterns on both sources and strips simultaneously
runPattern(source2Pattern, source2_A, NUM_LEDS_A);
runPattern(source1Pattern, source1_B, NUM_LEDS_B);
runPattern(source2Pattern, source2_B, NUM_LEDS_B);
runPattern(source1Pattern, source1_C, NUM_LEDS_C);
runPattern(source2Pattern, source2_C, NUM_LEDS_C);
runPattern(source1Pattern, source1_D, NUM_LEDS_D);
runPattern(source2Pattern, source2_D, NUM_LEDS_D);
runPattern(source1Pattern, source1_E, NUM_LEDS_E);
runPattern(source2Pattern, source2_E, NUM_LEDS_E);
FastLED.show();
//Serial.println("ran show");
FastLED.delay(100); //100
}
}
void nextPattern( uint8_t patternCounter ) {
//patternCounter = (patternCounter + 1) % 3; // Change the number after the % to the number of patterns you have
if (useSource1) source1Pattern = patternCounter; // Determine which source array for new pattern
else source2Pattern = patternCounter;
useSource1 = !useSource1;
}
void runPattern(uint8_t pattern, CRGB *LEDArray, int NUM_LEDS) {
//Serial.println("running pattern");
switch (pattern) {
case 0:
//bounce(LEDArray, NUM_LEDS);
simplePattern();
//Serial.println("simple pattern");
break;
case 1:
//cyclon(LEDArray, NUM_LEDS);
purpleandgreen();
//Serial.println("purplegreen");
break;
case 2:
//random palette
currentPalette = randomPalette;
break;
case 3:
//fillfromcustomPalette();
//Serial.println("custom");
break;
case 4:
//Serial.println("rainbow");
rainbow(LEDArray, NUM_LEDS);
break;
case 5:
//Serial.println("rainbow");
setupXmasPalette();
break;
}
//Serial.println("fill leds");
if (pattern != 4) {
FillLEDsFromPaletteColors( gHue, LEDArray, NUM_LEDS );
}
}
//serial comms
void recvWithStartEndMarkers() {
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
//Serial.println("receiving");
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
//last character
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
Serial.println("got all data");
ndx = 0;
newData = true;
Serial.flush();
}
}
else if (rc == startMarker) {
recvInProgress = true;
Serial.println("recd startmarker");
}
//Serial.println("done receiving");
}
}
void parseData() { // split the data into its parts
Serial.println("parsing");
char * strtokIndx; // this is used by strtok() as an index
//Serial.println("line: " + tempChars);
strtokIndx = strtok(tempChars,":"); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
//Serial.println(messageFromPC);
strtokIndx = strtok(NULL, ":"); // this continues where the previous call left off
//Serial.println("integer from pc pre atoi: " + atoi(strtokIndx));
integerFromPC = atoi(strtokIndx); // convert this part to an integer
//Serial.println(" integer from pc: " + integerFromPC);
//start processing colour string
strtokIndx = strtok(NULL, ":");
String arrayToken = String(strtokIndx);
//Serial.println("Array Token: " + arrayToken);
// Extract the array
//strtokIndx = strtok(NULL, ",");
int i = 0;
char *arrayTokenPtr = strtok(arrayToken.begin(), ",");
while (arrayTokenPtr != NULL && i < MAX_ARRAY_SIZE) {
colournumberArray[i++] = atoi(arrayTokenPtr);
arrayTokenPtr = strtok(NULL, ",");
}
Serial.print("Extracted Numbers: ");
for (int j = 0; j < i; ++j) {
Serial.print(colournumberArray[j]);
if (j < i - 1) {
Serial.print(", ");
}
}
Serial.print("/n");
customPalette(); //calls function to input values to palette
//recvInProgress = false;
//Serial.println("set false in parseData");
/*if (strtokIndx != NULL) {
String arrayToken = String(strtokIndx);
Serial.println("Array Token: " + arrayToken);
// Parse the array string and fill the numberArray
int i = 0;
char *arrayTokenPtr = strtok(arrayToken.begin(), ",");
while (arrayTokenPtr != NULL && i < MAX_ARRAY_SIZE) {
colournumberArray[i++] = atoi(arrayTokenPtr);
arrayTokenPtr = strtok(NULL, ",");
}
// Print the extracted numbers
Serial.print("Extracted Numbers: ");
for (int j = 0; j < i; ++j) {
Serial.print(colournumberArray[j]);
if (j < i - 1) {
Serial.print(", ");
}
}
*/
//floatFromPC = atof(strtokIndx); // convert this part to a float
//}
}
//============
void showParsedData() {
//Serial.print("Message ");
//Serial.println(messageFromPC);
//Serial.print("Integer ");
//Serial.println(integerFromPC);
//Serial.print("Float ");
//Serial.println(floatFromPC);
}
// This function fills the palette from serial array
void customPalette()
{
for( int i = 0; i < 16; ++i) {
if (colournumberArray[i] == 300) { //white
currentPalette[i] = CHSV( 0, 0, 255);
} else if (colournumberArray[i] == 400) { //black
currentPalette[i] = CHSV( 0, 0, 0);
} else {
currentPalette[i] = CHSV( colournumberArray[i], 255, 255);
}
}
}
// This function fills the palette with totally random colors.
void SetupTotallyRandomPalette()
{
for( int i = 0; i < 16; ++i) {
randomPalette[i] = CHSV( random8(), 255, 255);
}
}
//------- Put your patterns below -------//
void bounce(CRGB *LEDarray, int NUM_LEDS){
//Bounce
static uint8_t hue = 0;
fadeToBlackBy( LEDarray, NUM_LEDS, 20);
int pos = beatsin16( 10, 0, NUM_LEDS - 1);
LEDarray[pos] += CHSV(hue++, 255, 192);
}
void cyclon(CRGB *LEDarray, int NUM_LEDS) {
uint16_t posBeat = beatsin16(7, 0, NUM_LEDS - 1, 0, 0);
uint16_t posBeat2 = beatsin16(15, 0, NUM_LEDS - 1, 0, 0);
uint16_t posBeat3 = beatsin16(7, 0, NUM_LEDS - 1, 0, 32767);
uint16_t posBeat4 = beatsin16(15, 0, NUM_LEDS - 1, 0, 32767);
// Wave for LED color
uint8_t colBeat = beatsin8(2, 0, 255, 0, 0);
LEDarray[(posBeat + posBeat2) / 2] = CHSV(colBeat, 255, 255);
LEDarray[(posBeat3 + posBeat4) / 2] = CHSV(colBeat, 255, 255);
fadeToBlackBy(LEDarray, NUM_LEDS, 50);
}
void rainbow(CRGB *LEDarray, int NUM_LEDS) {
static uint8_t hue = 0;
fill_rainbow(LEDarray, NUM_LEDS, hue, 255 / NUM_LEDS);
EVERY_N_MILLISECONDS(10){
hue++;
}
currentBlending = LINEARBLEND;
}
void simplePattern()
{
currentPalette = CloudColors_p;
currentBlending = LINEARBLEND;
//FillLEDsFromPaletteColors( gHue );
//Serial.println("set coloudcolours");
}
// This function sets up a palette of purple and green stripes.
void SetupPurpleAndGreenPalette()
{
CRGB purple = CHSV( HUE_PURPLE, 255, 255);
CRGB green = CHSV( HUE_GREEN, 255, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
green, green, purple, green,
purple, purple, purple, green,
green, green, green, purple,
purple, purple, green, purple );
currentBlending = LINEARBLEND;
//FillLEDsFromPaletteColors( gHue );
//Serial.println("set purpleandgreen");
}
void purpleandgreen()
{
SetupPurpleAndGreenPalette();
//FillLEDsFromPaletteColors( gHue );
}
void setupXmasPalette()
{
CRGB green = CHSV( HUE_GREEN, 255, 255);
CRGB blue = CHSV( HUE_BLUE, 255, 255);
CRGB red = CHSV( HUE_RED, 255, 255);
CRGB white = CHSV( 0, 0, 255);
currentPalette = CRGBPalette16(
green, blue, red, green,
white, blue, red, green,
blue, blue, red, green,
red, blue, red, green );
currentBlending = NOBLEND;
}
void FillLEDsFromPaletteColors( uint8_t colorIndex, CRGB *LEDarray, int NUM_LEDS )
{
uint8_t brightness = 96;
//Serial.println("filling leds");
//Serial.println(currentBlending);
//Serial.println(colorIndex);
//Serial.println(currentPalette);
for( int i = 0; i < NUM_LEDS; ++i) {
LEDarray[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 1;//3
}
}