Back to Parent

#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!

0