Neopixel Tree


#1

About This Project

This is a project for a holiday neopixel tree that is controlled by cayenne. It uses two MCUs, one to maintain a healthy cayenne connection (a ESP8266-01), and the other to drive the neopixels (SAMD Dev board). The MCUs communicate by I2C. It took me forever to get the I2C working… Kept thinking it was hardware issues because the data rarely came across correctly. Turns out it was one little piece of code that sets the I2C clock stretching limit. With that it works.

When I change a value on the cayenne dashboard, it sends a Wire library interrupt (which is blocking meaning it stops any other code) that resets the dev board (to break the many, many neopixel loops) and then sends the new data from cayenne to the dev board and runs the specified neopixel pattern. The slave code has some extra pieces that arn’t used currently… mainly tests for different patterns.

Neopixels need max of ±.73 volts on the data line from the power source which is 5v. The SAMD Dev board and the ESP run at 3.3v so I needed a special logic level shifter to correctly relay the data to the neopixels. I got the Adafruit 74AHCT125 shifter and the neopixels work good with it.

The reason I went with a SAMD board is because I’m going to add a neopixel ring for the star on the tree and this board supports multitasking so both can run at once. The tree needs more ornaments too lol.

What’s Connected

900 neopixels, a ESP8266-01, a Sparkfun SAMD Dev board, a Adafruit 74AHCT125 level shifter, two inline fuses, and a 60amp DC 5v power supply.

Scheduling

I use this to turn off the tree at night.

Dashboard Screenshots

Photos of the Project

Video

Master - ESP8266 code:

#include <Arduino.h>
// #define CAYENNE_DEBUG Serial
// #define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266.h>
#include <Wire.h>


extern "C" {
#include "user_interface.h"
}

///// neo pix

char ssid[] = "IoT";
char wifiPassword[] = "pass";


char username[] = "";
char password[] = "";
char clientID[] = "";


// const int txPin = D5;
// const int sdaPin = D2;
// const int sclPin = D1;
// const int txPin = 1;
const int sdaPin = 0;
const int sclPin = 2;
const int slaveAddress = 0x0D;

byte result;
byte program = 4;
byte prevProgram = 4;
byte prevrandomProgram = 0;
byte randomProgram = 0;
byte wait = 200;
byte prevWait = 200;

unsigned long time1 = 0;

void setup()
{
	// pinMode(txPin, OUTPUT);

	system_update_cpu_freq(160);
	system_phy_set_max_tpw(82);
	wifi_set_opmode(0x01);

	// Serial.begin(9600);

	Wire.begin(sdaPin,sclPin);
	Wire.setClockStretchLimit(40000);



	Cayenne.begin(username, password, clientID, ssid, wifiPassword);
	Cayenne.virtualWrite(2, randomProgram, "digital_actuator", "d");
	Cayenne.virtualWrite(1, program, "analog_actuator", "null");
	Cayenne.virtualWrite(3, wait, "analog_actuator", "null");
	Cayenne.virtualWrite(20, 0, "digital_sensor", "d");
}

void loop()
{
	Cayenne.loop();

	if (program != prevProgram || prevrandomProgram != randomProgram || prevWait != wait)
	  {
		  Wire.requestFrom(slaveAddress,1);
		  delay(2000);

		  byte count = 0;
		  do
		    {
			    Wire.beginTransmission(slaveAddress);
			    Wire.write(program);
			    Wire.write(randomProgram);
			    Wire.write(wait);
			    result = Wire.endTransmission();

			    count++;

			    if (count > 10)
			      {
				      ESP.restart();
			      }

			    delay(1000);
		    } while(result != 0);

		  prevProgram = program;
		  prevrandomProgram = randomProgram;
		  prevWait = wait;
	  }


	if (millis() - time1 > 5000)
	  {
		  int rssi = wifi_station_get_rssi();
		  Cayenne.virtualWrite(0, rssi, "rssi", "dbm");
		  time1 = millis();
	  }
}



CAYENNE_IN(1)
{
	program = getValue.asInt();
}

CAYENNE_IN(2)
{
	randomProgram = getValue.asInt();
}

CAYENNE_IN(3)
{
	wait = getValue.asInt();
}


CAYENNE_IN(20)
{
	byte restartChip = getValue.asInt();

	delay(500);

	if (restartChip == 1)
	  {
		  Cayenne.virtualWrite(20, 0, "digital_sensor", "d");
		  Cayenne.loop();
		  delay(1500);
		  ESP.restart();
	  }
}

Slave code - Dev Board:

#include <Arduino.h>
#include <Wire.h>
#include <NeoPixelBus.h>
#include <NeoPixelAnimator.h>

#if defined( ARDUINO_ARCH_AVR )
#include <SoftReset.h>
#endif

#if defined( ARDUINO_ARCH_SAMD )
   #define Serial SerialUSB
// #include <Scheduler.h>
#endif


const int PixelCount = 900;
const byte PixelPin = 3;
const int address = 0x0D;
const unsigned long randomInterval = 180000L;  //in millis

NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
NeoGamma<NeoGammaTableMethod> colorGamma;

RgbColor allOff(0,0,0);

float progress = 0;
int pixel = 1;
volatile byte program = 0;
volatile byte randomProgram = 0;
volatile int wait = 0;

volatile bool firstRun = true;

unsigned long time1 = 0;
unsigned long time2 = 0;

RgbColor startColor;
RgbColor previousColor;
RgbColor endingColor;
RgbColor startColor2;
RgbColor previousColor2;
RgbColor endingColor2;

void setup()
{
	// Serial.begin(9600);

	Wire.begin(address);
	Wire.onReceive(recievedData);
	Wire.onRequest(requestData);

	for (int i = 0; i < PixelCount; i++)
	  {
		  strip.SetPixelColor(i, allOff);
	  }
	strip.Show();

	// Scheduler.startLoop(loop2);
}


void loop()
{

	if (randomProgram && (millis() - time1) > randomInterval)
	  {
		  // Serial.println("random execute");
      program = random(1,13);
      time1 = millis();
	  }


	if (firstRun == true && ( millis() > 10000 ))
	  {
		  // Serial.println("firstrun");
		  program = 4;
		  wait = 200;
		  firstRun = false;
	  }

	switch (program)
	  {
	  case 1:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  wholeColorFade(wait);
		  break;
	  }

	  case 2:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  Rainbowrunning(wait);
		  break;

	  }

	  case 3:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  RainbowCircle(wait);
		  break;
	  }

	  case 4:
	  {
		  if (randomProgram)
		    {
			    wait = 200;
		    }
		  theaterChaseRainbow(wait);
		  break;
	  }

    case 5:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  rainbowRandom(wait);
		  break;
	  }

	  case 6:
	  {
		  if (randomProgram)
		    {
			    wait = 200;
		    }
		  fatRedGreenChase(wait);
		  break;
	  }

	  case 7:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  solidColorRacing(wait);
		  break;
	  }

	  case 8:
	  {
		  if (randomProgram)
		    {
			    wait = 200;
		    }
		  fatterRedGreenChase(wait);
		  break;
	  }

	  case 9:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  mirroredSolidColorRacing(wait);
		  break;
	  }

	  case 10:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  whiteRunning(wait);
		  break;
	  }

	  case 11:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  twinkle(wait);
		  break;
	  }

	  case 12:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  twinkle2(wait);
		  break;
	  }

	  case 13:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  twinkleWhite(wait);
		  break;
	  }

	  case 14:
	  {
		  if (randomProgram)
		    {
			    wait = 100;
		    }
		  twinkleWhite2(wait);
		  break;
	  }

	  case 15:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  solidColorRacingFade(wait);
		  break;
	  }

	  case 16:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  rainbowRotate(wait);
		  break;
	  }


	  case 17:
	  {
		  if (randomProgram)
		    {
			    wait = 200;
		    }
		  redGreenChase(wait);
		  break;
	  }

	  case 18:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  rainbowRotate2(wait);
		  break;
	  }

	  case 19:
	  {
		  if (randomProgram)
		    {
			    wait = 0;
		    }
		  rainbowRotate2(wait);
		  break;
	  }

	  // case 20:
	  //   randomProgram();
	  //   break;

	  default:
	  {
		  for (int i = 0; i < PixelCount; i++)
		    {
			    strip.SetPixelColor(i, allOff);
		    }
		  strip.Show();
		  break;
	  }

	  }
}





// void loop2()
// {
//      if (Wire.available())
//        {
//                program = Wire.read();
//                onOff = Wire.read();
//                wait = Wire.read();
//        }
// }


void recievedData(int numBytes)
{
	if (Wire.available())
	  {
		  program = Wire.read();
		  randomProgram = Wire.read();
		  wait = Wire.read();
	  }

    firstRun = false;
}


void requestData()
{
  #if defined( ARDUINO_ARCH_SAMD )
	NVIC_SystemReset();
  #endif


  #if defined( ARDUINO_ARCH_AVR )
	soft_restart();
  #endif
}


///////////////////////////////////////////////////

void rainbowRandom(int delayTime)
{
	for (int i = 0; i < PixelCount; i++)
	  {
		  RgbColor currentColor = RgbColor(random(255),random(255),random(255));
		  RgbColor results = colorGamma.Correct(currentColor);
		  strip.SetPixelColor(i,results);
	  }
	strip.Show();
	delay(delayTime);
}

void rainbowRotate(int delayTime)
{
	for (int i = 0; i < PixelCount; i++)
	  {
		  RgbColor currentColor = RgbColor(random(255),random(255),random(255));
		  RgbColor results = colorGamma.Correct(currentColor);
		  strip.SetPixelColor(i,results);
	  }

	strip.Show();

	for (int k = 0; k < PixelCount; k++)
	  {
		  strip.RotateRight(1);
		  strip.Show();
		  delay(delayTime);
	  }
}

void rainbowRotate2(int delayTime)
{
	for (int i = 0; i < PixelCount; i += 2)
	  {
		  byte color = random(8);
		  RgbColor red1 = colorGamma.Correct(RgbColor(150,0,0));
		  RgbColor green1 = colorGamma.Correct(RgbColor(0,150,0));
		  RgbColor blue1 = colorGamma.Correct(RgbColor(0,0,150));
		  RgbColor yellow1 = colorGamma.Correct(RgbColor(150,150,0));
		  RgbColor purple1 = colorGamma.Correct(RgbColor(150,0,150));
		  RgbColor orange1 = colorGamma.Correct(RgbColor(125,75,0));
		  RgbColor pink1 = colorGamma.Correct(RgbColor(100,0,50));
		  RgbColor cyan1 = colorGamma.Correct(RgbColor(0,100,100));

		  switch (color) {

		    case 0:
			    strip.SetPixelColor(i,red1);
			    strip.SetPixelColor(i + 1,red1);
			    break;

		    case 1:
			    strip.SetPixelColor(i,green1);
			    strip.SetPixelColor(i + 1,green1);
			    break;

		    case 2:
			    strip.SetPixelColor(i,blue1);
			    strip.SetPixelColor(i + 1,blue1);
			    break;

		    case 3:
			    strip.SetPixelColor(i,yellow1);
			    strip.SetPixelColor(i + 1,yellow1);
			    break;

		    case 5:
			    strip.SetPixelColor(i,purple1);
			    strip.SetPixelColor(i + 1,purple1);
			    break;

		    case 6:
			    strip.SetPixelColor(i,orange1);
			    strip.SetPixelColor(i + 1,orange1);
			    break;

		    case 7:
			    strip.SetPixelColor(i,pink1);
			    strip.SetPixelColor(i + 1,pink1);
			    break;

		    case 4:
			    strip.SetPixelColor(i,cyan1);
			    strip.SetPixelColor(i + 1,cyan1);
			    break;
		    }
	  }
	strip.Show();


	for (int k = 0; k < 20000; k++)
	  {
		  strip.RotateRight(1);
		  strip.Show();
		  delay(delayTime);
	  }
}

void redGreenChase(int delayTime)
{

	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);

	for (int i = 0; i < PixelCount; i = i + 2)
	  {
		  strip.SetPixelColor(i,greenColor);
		  strip.SetPixelColor(i + 1,redColor);
	  }

	strip.Show();
	delay(delayTime);
	// strip.ClearTo(allOff);

	for (int i = 0; i < PixelCount; i = i + 2)
	  {
		  strip.SetPixelColor(i + 1,greenColor);
		  strip.SetPixelColor(i,redColor);
	  }

	strip.Show();
	delay(delayTime);
}

void fatRedGreenChase(int delayTime)
{
	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);

	for (int i = 0; i < PixelCount; i = i + 6)
	  {
		  strip.SetPixelColor(i,greenColor);
		  strip.SetPixelColor(i + 1,greenColor);
		  strip.SetPixelColor(i + 2,greenColor);
		  strip.SetPixelColor(i - 1,redColor);
		  strip.SetPixelColor(i - 2,redColor);
		  strip.SetPixelColor(i - 3,redColor);
		  // strip.SetPixelColor(i,greenColor);
		  // strip.SetPixelColor(i + 1,redColor);
	  }

	strip.Show();
	delay(delayTime);
	for (int q = 0; q < 5; q++)
	  {
		  strip.RotateRight(1);
		  strip.Show();
		  delay(delayTime);
	  }
}

void fatterRedGreenChase(int delayTime)
{
	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);

	for (int i = 0; i < PixelCount; i = i + 10)
	  {
		  strip.SetPixelColor(i,greenColor);
		  strip.SetPixelColor(i + 1,greenColor);
		  strip.SetPixelColor(i + 2,greenColor);
		  strip.SetPixelColor(i + 3,greenColor);
		  strip.SetPixelColor(i + 4,greenColor);
		  strip.SetPixelColor(i + 5,greenColor);

		  strip.SetPixelColor(i - 1,redColor);
		  strip.SetPixelColor(i - 2,redColor);
		  strip.SetPixelColor(i - 3,redColor);
		  strip.SetPixelColor(i - 4,redColor);
		  strip.SetPixelColor(i - 5,redColor);
		  // strip.SetPixelColor(i,greenColor);
		  // strip.SetPixelColor(i + 1,redColor);
	  }

	strip.Show();
	for (int q = 0; q < 10; q++)
	  {
		  strip.RotateRight(1);
		  strip.Show();
		  delay(delayTime);
	  }
}

void Rainbowrunning(int delayTime)
{
	RgbColor currentColor = RgbColor(random(255),random(255),random(255));

	for (int i = 0; i < PixelCount; i++)
	  {
		  RgbColor results = colorGamma.Correct(currentColor);
		  strip.SetPixelColor(i,results);
		  strip.Show();
		  delay(delayTime);
	  }

}

void whiteRunning(int delayTime)
{
	RgbColor whiteColor = RgbColor(150,150,150);

	for (int i = 0; i < PixelCount; i = i + 20)
	  {
		  strip.SetPixelColor(i,whiteColor);
		  strip.SetPixelColor(i + 1,whiteColor);
		  strip.SetPixelColor(i + 2,whiteColor);
		  strip.SetPixelColor(i + 3,whiteColor);
		  strip.SetPixelColor(i + 4,whiteColor);
		  strip.SetPixelColor(i + 5,whiteColor);

		  strip.SetPixelColor(i - 1,allOff);
		  strip.SetPixelColor(i - 2,allOff);
		  strip.SetPixelColor(i - 3,allOff);
		  strip.SetPixelColor(i - 4,allOff);
		  strip.SetPixelColor(i - 5,allOff);
		  strip.SetPixelColor(i - 6,allOff);
		  strip.SetPixelColor(i - 7,allOff);
		  strip.SetPixelColor(i - 8,allOff);
		  strip.SetPixelColor(i - 9,allOff);
		  strip.SetPixelColor(i - 10,allOff);
	  }

	for (int q = 0; q < 20; q++)
	  {
		  strip.RotateRight(1);
		  strip.Show();
		  delay(delayTime);
	  }
}

void twinkle(int delayTime)
{
	RgbColor randomColor = RgbColor(random(255),random(255),random(255));

	strip.SetPixelColor(random(PixelCount),colorGamma.Correct(randomColor));
	strip.Show();
	delay(delayTime);
}

void twinkle2(int delayTime)
{
	RgbColor randomColor = colorGamma.Correct(RgbColor(random(255),random(255),random(255)));
	pixel = random(PixelCount);
	previousColor = strip.GetPixelColor(pixel);



	for (float i = 0.0; i < 1.0; i = i + 0.05)
	  {
		  RgbColor results = RgbColor::LinearBlend(previousColor, randomColor, i);
		  results = colorGamma.Correct(results);
		  strip.SetPixelColor(pixel, results);
		  strip.Show();
		  delay(delayTime);
	  }
}

void twinkleWhite(int delayTime)
{
	byte randomWhite = random(150);
	RgbColor whiteColor = RgbColor(randomWhite,randomWhite,randomWhite);
	pixel = random(PixelCount);
	previousColor = strip.GetPixelColor(pixel);

	delay(delayTime);

	for (float i = 0.0; i < 1.0; i = i + 0.05)
	  {
		  RgbColor results = RgbColor::LinearBlend(previousColor, whiteColor, i);

		  strip.SetPixelColor(pixel, results);
		  strip.Show();

	  }
}

void twinkleWhite2(int delayTime)
{
	RgbColor whiteColor = RgbColor(100,100,100);

	for (int i = 0; i < PixelCount; i++)
	  {
		  strip.SetPixelColor(i,whiteColor);
	  }

	int pixel1 = random(PixelCount);
	int pixel2 =  random(PixelCount);
	int pixel3 =  random(PixelCount);
	int pixel4 =  random(PixelCount);
	int pixel5 =  random(PixelCount);


	strip.SetPixelColor(pixel1,allOff);
	strip.SetPixelColor(pixel2,allOff);
	strip.SetPixelColor(pixel3,allOff);
	strip.SetPixelColor(pixel4,allOff);
	strip.SetPixelColor(pixel5,allOff);

	strip.Show();
	delay(delayTime);

	strip.SetPixelColor(pixel1,whiteColor);
	strip.SetPixelColor(pixel2,whiteColor);
	strip.SetPixelColor(pixel3,whiteColor);
	strip.SetPixelColor(pixel4,whiteColor);
	strip.SetPixelColor(pixel5,whiteColor);
}

void solidColorRacing(int delayTime)
{
	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);

	for (int i = 0; i < PixelCount; i++)
	  {
		  strip.SetPixelColor(i,greenColor);
		  strip.Show();
		  delay(delayTime);
	  }

	for (int i = 0; i < PixelCount; i++)
	  {
		  strip.SetPixelColor(i,redColor);
		  strip.Show();
		  delay(delayTime);
	  }
}

void solidColorRacingFade(int delayTime)
{
	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);
	RgbColor color;

	for (int i = 0; i < PixelCount; i++)
	  {
		  strip.SetPixelColor(i,greenColor);
		  color = strip.GetPixelColor(i);
		  color.Darken(15);
		  strip.SetPixelColor(i - 1,greenColor);
		  color = strip.GetPixelColor(i - 1);
		  color.Darken(15);
		  strip.SetPixelColor(i - 2,greenColor);
		  color = strip.GetPixelColor(i - 2);
		  color.Darken(15);
		  strip.SetPixelColor(i - 3,greenColor);
		  color = strip.GetPixelColor(i - 3);
		  color.Darken(15);
		  strip.SetPixelColor(i - 4,greenColor);
		  color = strip.GetPixelColor(i - 4);
		  color.Darken(15);
		  strip.SetPixelColor(i - 5,greenColor);
		  color = strip.GetPixelColor(i - 5);
		  color.Darken(15);
		  strip.SetPixelColor(i - 6,greenColor);
		  color = strip.GetPixelColor(i - 6);
		  color.Darken(15);
		  strip.SetPixelColor(i - 7,greenColor);
		  color = strip.GetPixelColor(i - 7);
		  color.Darken(15);
		  strip.SetPixelColor(i - 8,greenColor);
		  color = strip.GetPixelColor(-8);
		  color.Darken(15);
		  strip.SetPixelColor(i - 9,greenColor);
		  color = strip.GetPixelColor(-9);
		  color.Darken(15);

		  strip.Show();
		  delay(delayTime);
	  }
}

void mirroredSolidColorRacing(int delayTime)
{
	RgbColor greenColor = RgbColor(0,150,0);
	RgbColor redColor = RgbColor(150,0,0);
	int pixel2 = PixelCount;

	for (int i = 0; i < ( PixelCount / 2 ); i++ && pixel2--)
	  {
		  strip.SetPixelColor(i,greenColor);
		  strip.SetPixelColor(pixel2,greenColor);
		  strip.Show();
		  delay(delayTime);
	  }

	for (int i = ( PixelCount / 2 ); i > 0; i-- && pixel2++)
	  {
		  strip.SetPixelColor(i,redColor);
		  strip.SetPixelColor(pixel2,redColor);
		  strip.Show();
		  delay(delayTime);
	  }
}

void everyOther(int delayTime)
{
	for (float i = 0.0; i < 1.0; i = i + 0.01)
	  {
		  previousColor = endingColor;
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(random(255),random(255),random(255));
		  for (pixel = 0; pixel < PixelCount; pixel++)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
			    strip.Show();
			    delay(delayTime);

		    }
	  }
}

void singleRainbowChase()
{
	for (pixel = 0; pixel < PixelCount; pixel++)
	  {
		  previousColor = endingColor;
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(random(255),random(255),random(255));

		  for (float i = 0.0; i < 1.0; i = i + 0.01)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
			    strip.Show();
		    }
	  }
}

void doubleMirreredRainbowChase()
{
	int pixel2 = PixelCount;

	for (pixel = 0; pixel < PixelCount; pixel++ && pixel2--)
	  {
		  previousColor = endingColor;
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(random(255),random(255),random(255));

		  for (float i = 0.0; i < 1.0; i = i + 0.01)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
			    strip.SetPixelColor(pixel2, results);
			    strip.Show();
			    delay(2);
		    }
	  }
}

void doubleRainbowChase()
{
	int pixel2 = PixelCount;

	for (pixel = 0; pixel < PixelCount; pixel++ && pixel2--)
	  {
		  previousColor = endingColor;
		  previousColor2 = endingColor2;
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(random(255),random(255),random(255));
		  endingColor2 = RgbColor(random(255),random(255),random(255));

		  for (float i = 0.0; i < 1.0; i = i + 0.01)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    RgbColor results2 = RgbColor::LinearBlend(previousColor2, endingColor2, i);
			    results = colorGamma.Correct(results);
			    results = colorGamma.Correct(results2);
			    strip.SetPixelColor(pixel, results);
			    strip.SetPixelColor(pixel2, results2);

			    strip.Show();
		    }
	  }
}

void wholeColorFade(int delayTime)
{

	previousColor = endingColor;
	//  previousColor= strip.GetPixelColor(pixel);
	endingColor = RgbColor(random(255),random(255),random(255));

	for (float i = 0.0; i < 1.0; i = i + 0.01)
	  {
		  for (pixel = 0; pixel < PixelCount; pixel++)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
		    }
		  strip.Show();
		  delay(delayTime);
	  }
	strip.Show();
}

void doubleMirreredOff(int delayTime)
{
	int pixel2 = PixelCount;

	for (pixel = 0; pixel < PixelCount; pixel++ && pixel2--)
	  {
		  previousColor = RgbColor(255,0,0);
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(0,0,0);

		  for (float i = 0.0; i < 1.0; i = i + 0.01)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
			    strip.SetPixelColor(pixel2, results);
			    strip.Show();
			    delay(delayTime);
		    }
	  }
}

void chase(int delayTime)
{
	RgbColor pixelColor = RgbColor(75,0,75);

	for (pixel = 0; pixel < PixelCount; pixel++)
	  {
		  pixelColor = colorGamma.Correct(pixelColor);
		  strip.SetPixelColor(pixel, pixelColor);
		  strip.SetPixelColor(pixel - 1, pixelColor);
		  strip.SetPixelColor(pixel - 2, pixelColor);
		  strip.SetPixelColor(pixel - 3, allOff);
		  strip.Show();
		  delay(delayTime);

	  }
}

void stacking()
{

	for (pixel = 0; pixel < PixelCount; pixel++)
	  {
		  previousColor = RgbColor(255,0,0);
		  //  previousColor= strip.GetPixelColor(pixel);
		  endingColor = RgbColor(0,0,0);

		  for (float i = 0.0; i < 1.0; i = i + 0.01)
		    {
			    RgbColor results = RgbColor::LinearBlend(previousColor, endingColor, i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);

			    strip.Show();
			    delay(2);
		    }
	  }

}

void RainbowCircle(int wait)
{
	for (int j = 0; j < 256; j++)
	  {
		  for (int q = 0; q < 3; q++)
		    {
			    for (uint16_t i = 0; i <= PixelCount; i++) //= i + 3
			      {
				      strip.SetPixelColor(i + q, Wheel( ( i + j ) % 255));
			      }
			    strip.Show();

			    delay(wait);

			    // for (uint16_t i = 0; i < PixelCount; i++)// = i + 3
			    //   {
			    //     strip.SetPixelColor(i + q, 0);
			    //   }
		    }
	  }
}

void theaterChaseRainbow(int wait)
{
	for (int j = 0; j < 256; j++)
	  {
		  for (int q = 0; q < 3; q++)
		    {
			    for (uint16_t i = 0; i < PixelCount; i = i + 3)
			      {
				      strip.SetPixelColor(i + q, Wheel( ( i + j ) % 255));
			      }
			    strip.Show();

			    delay(wait);

			    for (uint16_t i = 0; i < PixelCount; i = i + 3)
			      {
				      strip.SetPixelColor(i + q, 0);
			      }
		    }
	  }
}

void theaterChaseRainbow2()
{
	for (int j = 0; j < 256; j++)
	  {
		  for (int q = 0; q < 3; q++)
		    {
			    for (uint16_t i = 0; i < PixelCount; i = i + 3)
			      {
				      strip.SetPixelColor(i + q, Wheel( ( i + j ) % 255));
			      }
			    strip.Show();


			    delay(100);

			    for (uint16_t i = 0; i < PixelCount; i = i + 3)
			      {
				      strip.SetPixelColor(i + q, 0);
			      }
		    }
	  }
}

/////////////////////////////////////////

RgbColor Wheel(byte WheelPos)
{
	WheelPos = 255 - WheelPos;
	if(WheelPos < 85)  //85
	  {
		  return RgbColor(255 - WheelPos * 3, 0, WheelPos * 3);
	  }
	if(WheelPos < 170)
	  {
		  WheelPos -= 85;
		  return RgbColor(0, WheelPos * 3, 255 - WheelPos * 3);
	  }
	WheelPos -= 170;
	return RgbColor(WheelPos * 3, 255 - WheelPos * 3, 0);
}


void test2()
{
	RgbColor color;
	byte delayTime = 140;

	for (byte i = 0; i < ( PixelCount + 3 ); i++)
	  {
		  strip.SetPixelColor(i, RgbColor (0,50,75));

		  color = strip.GetPixelColor(i);
		  color.Darken(25);
		  strip.SetPixelColor(i - 1, color);
		  color.Darken(25);
		  strip.SetPixelColor(i - 2, color);
		  color.Darken(25);
		  strip.SetPixelColor(i - 3, color);


		  strip.Show();

		  if (i < ( ( PixelCount - 3 ) / 2 ))
		    {
			    delayTime -= 10;
			    delay(delayTime);
		    }
		  else
		    {
			    delayTime += 10;
			    delay(delayTime);
		    }
	  }

	delayTime = 140;

	for (int i = 24; i > -3; i--)
	  {
		  strip.SetPixelColor(i, RgbColor (0,50,75));

		  color = strip.GetPixelColor(i);
		  color.Darken(25);
		  strip.SetPixelColor(i + 1, color);
		  color.Darken(25);
		  strip.SetPixelColor(i + 2, color);
		  color.Darken(25);
		  strip.SetPixelColor(i + 3, color);


		  strip.Show();

		  if (i < ( ( PixelCount + 3 ) / 2 ))
		    {
			    delayTime += 10;
			    delay(delayTime);
		    }
		  else
		    {
			    delayTime -= 10;
			    delay(delayTime);
		    }
	  }

}


void test3()
{
	RgbColor colorPixel[PixelCount] = RgbColor(random(255),random(255),random(255));
	RgbColor endColorPixel[PixelCount] = RgbColor(random(255),random(255),random(255));

	for (float i = 0.0; i < 1.0; i = i + 0.01)
	  {
		  for (pixel = 0; pixel < PixelCount; pixel++)
		    {
			    RgbColor results = RgbColor::LinearBlend(colorPixel[pixel], endColorPixel[pixel], i);
			    results = colorGamma.Correct(results);
			    strip.SetPixelColor(pixel, results);
			    strip.Show();
		    }
	  }

	// pixelChange(pixel, timeChange, RgbColor endingColorPixel);

	previousColor = strip.GetPixelColor(pixel);

}


void test4()
{
	RgbColor endColorPixel[PixelCount];
	RgbColor colorPixel[PixelCount];
	float speed[PixelCount];

	for (int q = 0; q < PixelCount; q++)
	  {
		  colorPixel[q] = RgbColor(random(255),random(255),random(255));
		  endColorPixel[q] = RgbColor(random(255),random(255),random(255));
		  speed[q] = random(0.99);
	  }



	for (int i = 0; i < PixelCount; i++)
	  {

		  pixelChange(i, speed[i], endColorPixel[i]);
	  }
}



void pixelChange(int numPixel, float speed, RgbColor endingColorPixel)
{
	for (float i = 0.0; i < 1.0; i = i + speed)
	  {
		  RgbColor results = RgbColor::LinearBlend(( strip.GetPixelColor(numPixel) ), endingColorPixel, i);
		  results = colorGamma.Correct(results);
		  strip.SetPixelColor(numPixel, results);
		  strip.Show();
	  }
}

#2

900 neopixels :open_mouth: Well now I have Christmas tree envy. Cool stuff!

P.S.
Just saw this contest yesterday if you wanted to submit this there.

~Benny


#3

nice project @vapor83


#4

Another idea…share a live webcam of the tree and share your project so we can use Cayenne dashboard to control your tree :christmas_tree: :alien:

~Benny


#5

Great project!


#6

what kind of neopixel did you use?


#7

THAT IS AWESOME! I bet those neopixels cost you a small fortune :hushed:


#8

They were not too bad. $22 per 300 on a roll so just under 70. Power supply was leftover from a failed project so that helped cost. I prob would have spent close to that on regular lights anyway.


#9

They are 5m, WS2812B, 60 LEDs/meter, coated IP65(waterproof)

https://www.aliexpress.com/item/1m-4m-5m-WS2812B-Smart-led-pixel-strip-Black-White-PCB-30-60-144-leds-m/2036819167.html


#10

and what kind of card sparkfun?


#11

Sparkfun SAMD Dev board

I used a Adafruit 74AHCT125 level shifter because its a 3.3v board and neopixels run at 5. The dev board playsnice with the esp since they both run at 3.3v.