#include "math.h"
#include "application.h"
#include <neopixel.h>
#define STATE_BLANK 1
#define STATE_START 2
#define STATE_SCENES 3
#define STATE_FIRE 4
#define SCENE_WEDDING 1
#define SCENE_HALLOWEEN 2
#define SCENE_CHRISMAS 3
int state = 1;
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN1 D2
#define PIXEL_COUNT1 168
#define PIXEL_TYPE1 WS2812B
#define PIXEL_PIN2 D0
#define PIXEL_COUNT2 96
#define PIXEL_TYPE2 SK6812RGBW
Adafruit_NeoPixel strip(PIXEL_COUNT1, PIXEL_PIN1, PIXEL_TYPE1);
Adafruit_NeoPixel ring(PIXEL_COUNT2, PIXEL_PIN2, PIXEL_TYPE2);
//fire
#define NUMBER_OF_FLAMES 24 // depends on number of neopixel triplets. 5 for 16 NeoPixel ring. 4 for 12 NeoPixel ring
#define FLAME_WIDTH 4 // How wide are the flames (in LEDs)
#define FLICKER_CHANCE 3 // increase this to increase the chances an individual flame will flicker
uint32_t rez_range = 256*3;
#define D_ false
// console buttons:
struct flame_element{
int brightness;
int step;
int max_brightness;
long rgb[3];
byte state;
} flames[NUMBER_OF_FLAMES];
int new_brightness = 0;
unsigned long rgb[3]; //reusable temporary array
uint8_t scaleD_rgb[3];
byte acc;
#define SCALERVAL 256*3
const int flamecolors[22][3] = {
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, 0, 0},
{ SCALERVAL, SCALERVAL*.4, },
{ SCALERVAL, SCALERVAL*.4, 0},
{ SCALERVAL, SCALERVAL*.4, 0},
{ SCALERVAL, SCALERVAL*.4, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, 0},
{ SCALERVAL, SCALERVAL*.3, },
{ SCALERVAL, SCALERVAL*.3, SCALERVAL}, // white
{ 0, SCALERVAL*.2, SCALERVAL}, // that one blue flame
{ SCALERVAL, SCALERVAL*.3, SCALERVAL*.5}
};
int rainbowBrightness=0;
uint8_t offset = 0; // Position of spinny eyes
uint32_t color = 0xffffff; // Start white
//double twinkleTime = 0;
uint32_t prevTime;
int sceneNum = 1;
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
ring.begin();
ring.setBrightness(50);
ring.show(); // Initialize all pixels to 'off'
Particle.function("changeState",changeState);
Particle.function("changeScene",changeScene);
randomSeed(analogRead(4));
InitFlames();
prevTime = millis();
}
void loop() {
//Switch state and update display ---------------------------------------------------
switch (state){
case STATE_BLANK:
ring.clear();
ring.show();
tree();
break;
case STATE_START:
ring.clear();
ring.show();
rainbow(20);
break;
case STATE_SCENES:
ring.clear();
ring.show();
scenes();
break;
case STATE_FIRE:
strip.clear();
strip.show();
//tree();
fire();
break;
}
}
//cloud function to switch case
int changeState (String nextState){
if (nextState.toInt() == 0 or nextState.toInt()>4 ){
state = (state + 1) % 5;
}
else{
state = nextState.toInt();
}
return state;
}
int changeScene (String nextScene){
if (nextScene.toInt() == 0 or nextScene.toInt()>3 ){
sceneNum = (sceneNum + 1) % 4;
}
else{
sceneNum = nextScene.toInt();
}
return sceneNum;
}
int ledNum (int treeNum, int height){
return (treeNum)*7+height;
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
if (rainbowBrightness<150){
strip.setBrightness(rainbowBrightness);
if (j%2 ==0){
rainbowBrightness++;
}
}
strip.show();
delay(wait);
}
}
// 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) {
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);
}
}
void tree (){
for (int i = 0; i<24; i++){
for(int j = 0; j<7; j++){
if (j<3){
strip.setPixelColor(ledNum(i,j), 255,100,22);
}
else{
strip.setPixelColor(ledNum(i,j), 50, 255,0);
}
}
}
strip.show();
}
void fire(){
for(byte flame_count=0; flame_count<NUMBER_OF_FLAMES; flame_count++) {
switch(flames[flame_count].state){
case 0: // reset
CreateNewFlame(flame_count);
break;
case 1: //increasing
new_brightness = flames[flame_count].brightness + flames[flame_count].step;
if (new_brightness > flames[flame_count].max_brightness){
UpdateFlameColor(flame_count, flames[flame_count].max_brightness);
flames[flame_count].brightness = flames[flame_count].max_brightness;
flames[flame_count].step = GetStepSize(); // pick a different speed for flame going out
flames[flame_count].state = 2;
} else {
UpdateFlameColor(flame_count, new_brightness);
flames[flame_count].brightness = new_brightness;
}
break;
case 2: //decreasing
new_brightness = flames[flame_count].brightness - flames[flame_count].step;
// chance to flicker/rekindle:
if (random(new_brightness) < FLICKER_CHANCE){
// rekindle:
flames[flame_count].state = 1; //increase again
flames[flame_count].brightness = max(GetMaxBrightness(), flames[flame_count].brightness);
flames[flame_count].step = GetStepSize();
} else {
if (new_brightness <1){
flames[flame_count].state = 0; // bottomed out - reset to next flame
flames[flame_count].brightness = 0;
UpdateFlameColor(flame_count, 0);
} else {
UpdateFlameColor(flame_count, new_brightness);
flames[flame_count].brightness = new_brightness;
}
}
break;
}
}
ring.show();
delay(50);
}
void InitFlames(){
// Sets initial states in flames array
for(byte i=0; i<NUMBER_OF_FLAMES; i++) {
flames[i].state=0;
}
}
void UpdateFlameColor(byte flame_num, int new_brightness){
//
uint32_t c = 0;
uint32_t color_channel_value;
byte rgb_channel;
new_brightness = min(new_brightness, flames[flame_num].max_brightness);
for(byte rgb_channel=0; rgb_channel<3; rgb_channel++) {
color_channel_value = flames[flame_num].rgb[rgb_channel];
color_channel_value = color_channel_value * (uint32_t)new_brightness; // keep it long
color_channel_value = color_channel_value/(uint32_t)rez_range;
rgb[rgb_channel] = max(0L,color_channel_value);
} // step through R G B
// spread possible values of 0 -768 across 3 pixels
for(byte sub_pixel=0; sub_pixel<FLAME_WIDTH; sub_pixel++) {
for(byte i=0; i<3; i++) { // rgb
acc = rgb[i]/3;
byte d = rgb[i]%3;
if (sub_pixel < d){
acc++;
}
scaleD_rgb[i] = acc;
}
c = ring.Color(scaleD_rgb[1],scaleD_rgb[0], 0 ,0);
if(scaleD_rgb[1]-scaleD_rgb[0]<5){
ring.setPixelColor(flame_num * FLAME_WIDTH + sub_pixel, c);
}
else{
ring.setPixelColor(flame_num * FLAME_WIDTH + sub_pixel, 0,0,0,100);
}
}
}
void CreateNewFlame(byte flame_num){
flames[flame_num].step = GetStepSize();
flames[flame_num].max_brightness = GetMaxBrightness();
flames[flame_num].brightness = 0;
flames[flame_num].state = 1;
byte color_index = random(22);
for(byte i=0; i<3; i++) {
flames[flame_num].rgb[i] = flamecolors[color_index][i];
}
}
int GetStepSize(){
return random(70)+1;
}
int GetMaxBrightness(){
int retVal;
// retVal = random(rez_range/4) + random(rez_range/4) + random(rez_range/4) + rez_range/4 +1; // bell curve
// retVal = random(rez_range*3/4) + rez_range/4; // flat distribution
retVal = random(rez_range/2) + rez_range/2; // brighter flat distribution
return retVal;
}
/*void twinkle(){
for(int i=0; i<PIXEL_COUNT1; i++) {
uint32_t c = 0;
if(((offset + i) & 16) < 2) c = color; // 4 pixels on...
strip.setPixelColor( i, c); // First eye
strip.setPixelColor(167-i, c); // Second eye (flipped)
}
strip.show();
offset++;
delay(50);
}*/
void scenes(){
//Switch state and update display ---------------------------------------------------
switch (sceneNum){
case SCENE_WEDDING:{
for (int i = 0; i<24; i++){
for(int j = 0; j<7; j++){
if ((i % 2) == 0){
strip.setPixelColor(ledNum(i,j), 150,140,140);
}
else{
strip.setPixelColor(ledNum(i,j), 155,100,30);
}
strip.show();
}
}
}
break;
case SCENE_HALLOWEEN:
breath();
break;
case SCENE_CHRISMAS:{
for (int i = 0; i<24; i++){
for(int j = 0; j<7; j++){
if ((i % 2) == 0){
strip.setPixelColor(ledNum(i,j), 255,0,0);
}
else{
strip.setPixelColor(ledNum(i,j), 0,255,50);
}
strip.show();
}
}
}
break;
}
}
void breath( ){
float n = 0.2;
float val = (exp(sin(millis()/1300.0*M_PI)) - 0.36787944)*108.0;
//Serial.println( val );
uint16_t i;
uint32_t c = strip.Color(n*val, val, 0);
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, c );
}
strip.show();
delay (10);
}
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .