#include <FastLED.h>
//#define TIMING 0
#define LED_PIN 2
#define NUM_LEDS 51
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define MIN_BRIGHTNESS 10
#define MAX_BRIGHTNESS 255
#define RED 0
#define GREEN 96
#define BUTTON_PIN1 3
#define SWITCH_PIN1 4
#define SWITCH_PIN2 5
struct CRGB leds[NUM_LEDS];
const uint8_t led_count[] = {51};
unsigned long previousMillis = 0UL;
// Timing logics
// Cycle period refrence: (1000UL = ~1 second)
unsigned long goofy = 300UL; //bar graph jitter
unsigned long flash_time = 15UL; //arch flash
unsigned long sticky_interval = 35UL; //overall cycle speed
unsigned long interval = sticky_interval;
unsigned long sticky_solid = 55UL; //coolown from solid time
unsigned long solid = sticky_solid;
unsigned long sticky_cooldown = 1000UL; //off time
unsigned long cooldown = sticky_cooldown;
unsigned long reset_time = 5000UL; //overheat time
unsigned long flashem;
// millis---->>
// |..(current-previous)..>..................>>|
// .....|.....................goofy.300...........|.......
// .....|...............googy-flash_time.270.|......
//
//
// millis---->>
// |..(current-previous)..>..................>>|
//
// 30...|.interval-flash_time..................................|F!|
// 1000.|.interval................................................| Solid---->
// 1400.|.interval+solid.............................................| Cool---> ***optional cooldown
// 1700.|.interval+solid+cooldown.....................................................| off---->
// 1700......................................................|i|F!|S!| Cool-------------------->|
int randNumber;
int randomMalf;
int randWand;
long malfunction = 10;
bool test_mode = false;
bool flash = true;
bool cooling = false;
bool overheat = false;
bool windDown = false;
volatile bool blast = false;
long counter = 0;
int buttonState = 0;
int switchState1 = 0;
int switchState2 = 0;
volatile int state = LOW; // To make sure variables shared between an ISR
byte brightness = 255;
void setup() {
Serial.begin(115200);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.clear();
//Serial.println(FastLED.getBrightness());
/*for(int i; i<50; i++){
float curve = (i*i*1.);
float curve2 = map(curve, 0., 5000., 255.0, 10.0);
Serial.print(curve);
Serial.print(" to ");
Serial.println(curve2);
};
delay(100000);*/
//button(s)
pinMode(BUTTON_PIN1, INPUT_PULLUP); //HIGH when open
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN1),on,FALLING);//recommended for arduino board
pinMode(SWITCH_PIN1, INPUT_PULLUP); //HIGH when open
pinMode(SWITCH_PIN2, INPUT_PULLUP); //HIGH when open
}
void on() {
//ISR function
state = !state; //toggle the state when the interrupt occurs
blast = true;
for(int r=0; r < 23; r++){
leds[r] = CRGB(0, 255, 0);
}
}
void loop() {
// Set the brightness.
FastLED.setBrightness(brightness);
//Serial.println(buttonState);
randNumber = random(37,51);
randWand = random(27, 31);
//Serial.print("-------------------------> Random: ");
//Serial.println(randNumber);
// leds[37] Top of bargraph...
// leds[50] Bottom of bargraph...
// Main for loop to control cycle time...
for (int i = 33; i < 37;) {
leds[randNumber-1] = CRGB(0, 0, 0); // Make top light of powerpack bargraph flash
FastLED.show();
unsigned long currentMillis = millis();
buttonState = digitalRead(BUTTON_PIN1);
switchState1 = digitalRead(SWITCH_PIN1);
switchState2 = digitalRead(SWITCH_PIN2);
/* //DEBUG
Serial.print(currentMillis);
Serial.print(" vs ");
Serial.print(previousMillis);
Serial.print(" = ");
Serial.println(currentMillis - previousMillis);
*/
// Run Goofy loop for bargraph(s):
if(currentMillis - previousMillis > goofy){
// Set "Static" Lights
//leds[23] = CRGB(150,0,0);
leds[24] = CRGB::White;
leds[25] = CRGB(150, 200, 0);
leds[26] = CRGB(150, 0, 0);
//leds[32] = CRGB(255, 127, 0);
// Switch & Brightness Control of overal setup....
if(switchState1==0){ // up
if(brightness>5){brightness = brightness-5;};
FastLED.setBrightness(brightness);
if(i%2 != 1){leds[32] = CRGB(0, 255, 0);} else {leds[32].nscale8(240);};
} else {leds[32] = CRGB(255, 127, 0);};
if(switchState2==0){ // up
if(brightness<255){brightness = brightness+5;};
FastLED.setBrightness(brightness);
if(i%2 != 1){leds[23] = CRGB(255, 255, 0);} else {leds[23].nscale8(240);};
} else {leds[23] = CRGB(150,0,0);};
// fuel gage logics:
// leds[37] top of fuel gague
// leds[51] bottom of fuel gague
//Serial.print("Random: ");
//Serial.println(randNumber);
for (int a = randNumber; a < 51; a++) {
//for (int a = 51; a > randNumber; a--) { // This should work????
//Serial.println(a);
leds[a] = CRGB(150, 0, 150);
//leds[random(randNumber,18)] = CRGB(250, 0, 250);
FastLED.show();
};
//employ the goofy factor...
//chase "fire" up/down the wand...
for (int a = random(0,23); a < 23; a++) {
leds[a] = CHSV(0, 0, 0);
}
int q = random(0,200);
if(q >= 23 && q <= 27 || q==34){leds[q] = CRGB(0,0,0);};
}
if(currentMillis - previousMillis > goofy-flash_time){
leds[randNumber] = CRGB(200, 255, 255);
FastLED.show();
// Make the rod glow a bit, because its cool...
if(buttonState==0){
float breath = (exp(sin((currentMillis - previousMillis)/5000.0*PI)) - 0.36787944)*108.0;
breath = map(breath, 75, 166, 0, 255);
for(int n = random(-50,3); n >= 0; n--){
leds[n] = CHSV(breath, 255, 255);
};
for(int n = random(20,60); n <= 22; n++){
leds[n] = CHSV(breath, 255, 255);
};
};
}
if(currentMillis - previousMillis > goofy){
for (int a = randWand; a < 32; a++) {
leds[a] = CRGB(255, 180, 0);
//leds[random(randNumber,18)] = CRGB(250, 0, 250);
FastLED.show();
}
}
if(currentMillis - previousMillis > goofy-flash_time){
leds[randWand] = CRGB(255, 127, 0);
FastLED.show();
}
/*if(interval-flash_time < flash_time){
flashem = flash_time;
//Serial.println("Overide flash time");
}
else{flashem = interval-flash_time;};*/
flashem = flash_time;
// Create an "arch flash" before solid color light.
if(flash == true && currentMillis - previousMillis > flash_time){
//Serial.println("Flash!");
//Serial.println(currentMillis - previousMillis);
//Serial.print("Strobe: ");
//Serial.println(i);
leds[i] = CRGB(250, 250, 255);
FastLED.show();
};
// turn on a solid color light (hot cyclotron)
if(cooling == false && currentMillis - previousMillis > interval){
//Serial.println("Solid...");
//Serial.println(currentMillis - previousMillis);
//Serial.print("Color: ");
//Serial.println(i);
int n = (random(0-100));
if(n <= 75){leds[i] = CRGB(158, 229, 255);}
else if(n > 75 && n <= 95){leds[i] = CRGB(255, 170, 0);}
else if(n > 95 && n <= 100){leds[i] = CRGB(0, 225, 0);};
leds[randNumber] = CRGB(0, 0, 0);
FastLED.show();
flash = false;
};
//after a "solid" period, begin the optional cooldown phase...
if(overheat == false && currentMillis - previousMillis > interval+solid){
// Serial.print delay hack...
Serial.print(counter);
Serial.println(" Cooling...");
//
leds[i] = CRGB::Red;
//Serial.println((currentMillis - previousMillis)*1.0);
//Serial.print("cooling: ");Serial.println(breath);
float a = 235;
//float b = (254.8+(random(70-80)/1000.));
//float c = (254.9+(random(20-50)/1000.));
float b = (251.0+counter/10.0);
float c = (253.0+counter/10.0);
float d = 240;
if(i==33){
//leds[1].nscale8(a);
leds[35].nscale8(b);
leds[36].nscale8(c);
leds[i].nscale8(d);
//Serial.print("0=");
//Serial.println(currentMillis - previousMillis);
}else if(i==34){
//leds[2].nscale8(a);
leds[36].nscale8(b);
leds[33].nscale8(c);
leds[i].nscale8(d);
//Serial.print("1=");
//Serial.println(currentMillis - previousMillis);
}else if(i==35){
//leds[3].nscale8(a);
leds[33].nscale8(b);
leds[34].nscale8(c);
leds[i].nscale8(d);
//Serial.print("2=");
//Serial.println(currentMillis - previousMillis);
}else if(i==36){
//leds[0].nscale8(a);
leds[34].nscale8(b);
leds[36].nscale8(c);
leds[i].nscale8(d);
//Serial.print("3=");
//Serial.println(currentMillis - previousMillis);
};
if(buttonState==0){ // Blast button released (off)...
for(int r=0; r < 23; r++){
leds[r].nscale8(a);
}
};
if(buttonState==1){ // Blast Button Pressed....
for(int n = 22; n >= 0; n--){
float breath = (exp(sin((currentMillis - previousMillis)/5000.0*PI)) - 0.36787944)*108.0;
//Serial.println(breath);
breath = map(breath, 75, 166, 0, 255);
leds[n] = CHSV(breath, 255, 255);
};
}
FastLED.show();
cooling = true;
};
// down time (but still warm)
if(currentMillis - previousMillis > (interval+solid+cooldown)){
//Serial.println("off...");
//Serial.println(currentMillis - previousMillis);
//Serial.print("OFF: ");
//Serial.println(i);
if(overheat == false){
//leds[i] = CRGB(10, 0, 0);
};
if(overheat == true){
//Serial.println("Overheat active!");
leds[i] = CHSV(0,255,200); // dim a smidge
//Serial.println(curve);
//Serial.println((currentMillis - previousMillis)*1.0);
//Overheat wand alert:
leds[23] = CRGB(255, 0, 255);
leds[32] = CRGB(255, 0, 255);
if(counter%2 != 1){leds[26] = CRGB(0, 255, 0);} else {leds[26] = CRGB(255, 0, 0);};
if(counter%2 != 1){leds[25] = CRGB(0, 0, 0);} else {leds[25] = CRGB(150, 200, 0);};
};
FastLED.show();
if(windDown == false && i == 36){counter++;}; //increase malfunction counter
//Serial.print("the count is: ");
//Serial.println(counter);
// reset logic and step to next LED
flash = true;
cooling = false;
if(windDown == true){
cooldown = sticky_cooldown/counter;
if(i == 36){counter--;};
if(counter <= 6){
overheat = false;
//Serial.println("Overheat CLEAR!");
//Serial.print("loops before malfunction: ");
//Serial.println(malfunction);
//Serial.println(interval+solid+cooldown);
};
};
previousMillis = currentMillis;
i++;
};
// Reset Malfunction logic and generate another randomly... Spooky!
if(counter == 1 && windDown == true){
//Serial.println(counter);
cooldown = sticky_cooldown;
windDown = false;
malfunction = random(3, 50); //Between 3 and 50 cycles (12 seconds to 4 min)
if(test_mode==true){malfunction = random(3, 5);}; //testing
//Serial.print("loops before malfunction: ");
//Serial.println(malfunction);
};
////////////// Malfunction script
if(counter >= malfunction && windDown == false){
if(buttonState == true){
leds[(random(0,23))] = CRGB(0,0,0);
};
// Wand bargraph green...
for(int n = 27; n < 32; n++){leds[n] = CRGB::LawnGreen;};
//Serial.println("MALFUNCTION!");
//Serial.println(currentMillis - previousMillis);
//int g = 0;
while((currentMillis - previousMillis) < reset_time){
//g++;
currentMillis = millis();
//Serial.print(g);
//Serial.print(" Malfunctioning...");
//Serial.print(currentMillis - previousMillis);
//Serial.print(" VS ");
//Serial.println(reset_time);
for (int i = 33; i < 37; i++) {
float breath = (exp(sin((currentMillis - previousMillis)/5000.0*PI)) - 0.36787944)*108.0;
float color = (exp(sin((currentMillis - previousMillis)/5000.0*PI)) - 0.36787944)*108.0;
//float color;
breath = map(breath, 0, 255, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
color = map(color, 0, 255, RED, GREEN);
//Serial.println(color);
leds[i] = CHSV(color, 255, breath);
//introduce *some* random sparks into cyclotron:
randomMalf = random(0,80);
if(randomMalf <= 37 && randomMalf >= 33){randomMalf=randomMalf; leds[randomMalf] = CRGB(158, 229, 255);};
// Dim the wand and bargraph
for(int n = 0; n < 23; n++){leds[n].nscale8(230);};
for(int n = 27; n < 32; n++){leds[n].nscale8(230);};
FastLED.show();
//lots of random particles into fuel meter:
for (int a = 37; a < 51; a++) {
if(randomMalf > 37 && randomMalf < 51){randomMalf=randomMalf; leds[randomMalf] = CRGB(0,10,0);};
if(randomMalf >= 0 && randomMalf < 23){randomMalf=randomMalf; leds[randomMalf] = CRGB(255,0,255);};
if(randomMalf > 27 && randomMalf < 32){randomMalf=randomMalf; leds[randomMalf] = CRGB::Lime;};
leds[a] = CRGB(255,255,255);
FastLED.show();
};
}
cooldown = sticky_cooldown/counter;
//interval = sticky_interval/counter;
//solid = sticky_solid/counter;
if(malfunction >= 7){overheat = true;};
windDown = true;
counter = malfunction;
counter++;
//previousMillis = currentMillis;
}
if(windDown==true){previousMillis = currentMillis;};
};
}; //For loop
//blackout bargraphs at the end of the loop
for (int a = 50; a >= 37; a--) {
leds[a] = CRGB::Black;
FastLED.show();
//Serial.println(i);
};
for (int a = 31; a >= 27; a--) {
leds[a] = CRGB::Black;
FastLED.show();
//Serial.println(i);
};
}