FIRST!
authorRuss Handorf <rhandorf@handorf.org>
Sat, 10 Nov 2018 04:57:34 +0000 (23:57 -0500)
committerRuss Handorf <rhandorf@handorf.org>
Sat, 10 Nov 2018 04:57:34 +0000 (23:57 -0500)
box.ino [new file with mode: 0644]

diff --git a/box.ino b/box.ino
new file mode 100644 (file)
index 0000000..f432b5f
--- /dev/null
+++ b/box.ino
@@ -0,0 +1,243 @@
+//neopixel flame effect from https://github.com/schnoggo/jack-o-candle
+//everything else, do as you wish at your own risk
+
+#include <Adafruit_NeoPixel.h>
+#ifdef __AVR__
+  #include <avr/power.h>
+#endif
+
+#define PIN 9
+#define PWM 10
+#define NUMBER_OF_FLAMES 7
+#define FLAME_WIDTH 2
+#define FLICKER_CHANCE 3
+
+int fade = 0;
+unsigned long ledstringtimer;
+unsigned long previousMillis = 0;
+
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(14, PIN, NEO_GRB + NEO_KHZ800);
+
+uint32_t rez_range = 256*3;
+#define D_ false
+
+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}
+};
+
+void setup() {
+  Serial.begin(9600);
+  ledstringtimer = millis() + 5000;
+  strip.begin();
+  strip.show(); // Initialize all pixels to 'off'
+  randomSeed(analogRead(0));
+  InitFlames();
+}
+
+void loop() {
+  fire();
+  if (((signed long)(millis() - ledstringtimer)) > 0) {
+    ledstring();
+    ledstringtimer = millis() + 3000;
+    long dice = random(1000);
+    if (dice > 900) {
+      glowgreen();
+    } else if (dice<100) {
+      glowred();
+    }
+  }
+}
+
+void ledstring() {
+  fade=random(10, 255);
+  int fadeValue=0;
+  unsigned long currentMillis = millis();
+  while (fadeValue <= fade) {
+    currentMillis = millis();
+    if (currentMillis - previousMillis >= 30) {
+      previousMillis = currentMillis;
+      fadeValue += 5;
+      analogWrite(PWM, fadeValue);
+    }
+    fire();
+  }
+  while (fadeValue > 0) {
+    currentMillis = millis();
+    if (currentMillis - previousMillis >= 30) {
+      previousMillis = currentMillis;
+      fadeValue -= 5;
+      analogWrite(PWM, fadeValue);
+    }
+    fire();
+  }
+}
+
+void glowgreen() {
+  for(uint16_t t=0; t<255; t++) {
+    for (uint16_t i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, strip.Color(0, t, 0));
+    }
+    strip.show();
+    delay(10);
+  }
+  for(uint16_t t=255; t>0; t--) {
+    for (uint16_t i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, strip.Color(0, t, 0));
+    }
+    strip.show();
+    delay(10);
+  }
+}
+
+void glowred() {
+  for(uint16_t t=0; t<255; t++) {
+    for (uint16_t i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, strip.Color(t, 0, 0));
+    }
+    strip.show();
+    delay(10);
+  }
+  for(uint16_t t=255; t>0; t--) {
+    for (uint16_t i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, strip.Color(t, 0, 0));
+    }
+    strip.show();
+    delay(10);
+  }
+}
+
+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;
+    }
+  }
+   strip.show();
+}
+
+void InitFlames(){
+  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 = strip.Color(scaleD_rgb[0],scaleD_rgb[1], scaleD_rgb[2]);
+    strip.setPixelColor(flame_num * FLAME_WIDTH + sub_pixel, c);
+  } 
+}
+
+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/2) +  rez_range/2;
+  return retVal;
+}