//JLockwood 2023
//for the childrens bedrooms/hall
//libraries to include
#include <FastLED.h>
//end
//settings that can be changed
#define DATA_PIN 7
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 575
//#define BRIGHTNESS 125
#define FRAMES_PER_SECOND 120
//end
//declare constants
const int button1Pin = 5; //button to change the color/pattern
const int button2Pin = 6; //button to change the brightness
#define BUTTON 9
//comet code
const int LEDSpeed = 20; //Speed of the LED animation effect. Make sure not to exceed the maxLEDSpeed value.
//end comet code
//end
//variables
int colorState = 1; //variable for reading button 1 status
int BRIGHTNESS = 5;
//int brightState = 0; //variable for reading button 2 status
//comet code
int maxLEDSpeed = 50; //Identifies the maximum speed of the LED animation sequence
int LEDposition=0; //Identifies the LED position in the strip that the comet is currently at. The maximum position is NUM_LEDS-1 (eg. 143)
int oldPosition=0; //Holds the previous position of the comet.
byte hue = 0; //Stores the Leading LED's hue value (colour)
byte sat = 255; //Stores the Leading LED's saturation value
byte tailHue = 0; //Stores the Comet tail hue value
int tailLength = 8; //determines the length of the tail.
byte hueRange = 20; //Colour variation of the tail (greater values have greater variation
byte intensity = 200; //The default brightness of the leading LED
byte tailbrightness= intensity / 2; //Affects the brightness and length of the tail
int animationDelay = 0; //The greater the animation delay, the slower the LED sequence. Calculated from LEDSpeed and MaxSpeed.
unsigned long waitTime = 40000; //The wait time for each comet is currently set for 1 minute (or 60000 milliseconds).
unsigned long endTime; //The time when we no longer have to wait for the next comet
int cometNumber = 3; //Used to choose which comet colour to show (***Don't change this variable***)
//end
//end
CRGB leds[NUM_LEDS];
//comet code
byte ledh[NUM_LEDS];
byte ledb[NUM_LEDS];
//end
void setup() {
delay(2000); // 2 second delay for recovery
//intialize serial
// Make sure your Serial Terminal app is closed before powering your device
Serial.begin(9600);
Serial.println("Starting.....");//print Starting
//end
//declare buttons
pinMode(5, INPUT_PULLUP);//button1 using internal pullups
pinMode(6, INPUT_PULLUP);//button2 using internal pullups
pinMode(BUTTON, INPUT_PULLUP); //Connect button to digital pin 9, and use the internal pullup resistor
Serial.println("Buttons declared.....");
//end
// tell FastLED about the LED strip configuration
FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
//FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
// set master brightness control
FastLED.setBrightness(BRIGHTNESS);
//comet code
selectNextComet(); //Select the next comet colour
//end
}
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
void loop()
{
//read the buttons
if(digitalRead(5) == LOW){ //checks state of button1
++colorState; //adds one to button colorState (Pattern/Color changer)
Serial.println(colorState); //returns state of button 1.
if(colorState == 15){
FastLED.clear(true); //clears FastLED
}
delay(200); //tenth of a second delay to reduce double button taps
}
if(digitalRead(6) == LOW){
BRIGHTNESS = BRIGHTNESS + 25; //increases BRIGHTNESS by 25 (MAX 255, limited by code below)
Serial.println(BRIGHTNESS);
FastLED.setBrightness(BRIGHTNESS); //send BRIGHTNESS to FastLED
delay(200);
}
if(colorState == 20){ //number of programs -1
colorState = 1; //reset color state
}
if(BRIGHTNESS >= 140){ //keeps lights from overdrawing power
BRIGHTNESS = 5; //reset BRIGHTNESS state
}
//end
gPatterns[gCurrentPatternNumber]();
if(colorState == 1){
// Call the current pattern function once, updating the 'leds' array
//gPatterns[gCurrentPatternNumber]();
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 2){
// Call the current pattern function once, updating the 'leds' array
gCurrentPatternNumber = 1;
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 3){
// Call the current pattern function once, updating the 'leds' array
gCurrentPatternNumber = 2;
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 4){
// Call the current pattern function once, updating the 'leds' array
gCurrentPatternNumber = 3;
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 5){
// Call the current pattern function once, updating the 'leds' array
gCurrentPatternNumber = 4;
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 6){
// Call the current pattern function once, updating the 'leds' array
gCurrentPatternNumber = 5;
// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);
// do some periodic updates
EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}
if(colorState == 7){
fill_solid(leds,NUM_LEDS, CRGB::Red);
FastLED.show();
}
if(colorState == 8){
fill_solid(leds,NUM_LEDS, CRGB::Orange);
FastLED.show();
}
if(colorState == 9){
fill_solid(leds,NUM_LEDS, CRGB::Yellow);
FastLED.show();
}
if(colorState == 10){
fill_solid(leds,NUM_LEDS, CRGB::Green);
FastLED.show();
}
if(colorState == 11){
fill_solid(leds,NUM_LEDS, CRGB::Blue);
FastLED.show();
}
if(colorState == 12){
fill_solid(leds,NUM_LEDS, CRGB::Indigo);
FastLED.show();
}
if(colorState == 13){
fill_solid(leds,NUM_LEDS, CRGB::Violet);
FastLED.show();
}
if(colorState == 14){
fill_solid(leds,NUM_LEDS, CRGB::HotPink);
FastLED.show();
}
if(colorState == 15){
fill_solid(leds,NUM_LEDS, CRGB::FairyLight);
FastLED.show();
}
if(colorState == 16){
showLED(LEDposition, hue, sat, intensity);
//Adjust the hue of the tail so that it is a different colour from the leading LED. To reduce variation in tail colour, reduce the hueRange.
if(hue>(254-hueRange)){
tailHue = random((hue-hueRange),hue);
} else {
tailHue = random(hue, (hue+hueRange));
}
tailbrightness = random(50, 100); //Randomly select the brightness of the trailing LED (provides sparkling tail)
leds[LEDposition]=CHSV((tailHue),sat,tailbrightness); //Set the colour, saturation and brightness of the trailing LED
fadeLEDs(tailLength); //Fade the tail so that the tail brightness dwindles down to nothingness.
setDelay(LEDSpeed); //
LEDposition++;
if(LEDposition>(NUM_LEDS-1)){
for(int i=0; i<50; i++){
showLED(LEDposition, hue, sat, intensity);
fadeLEDs(tailLength);
setDelay(LEDSpeed);
}
LEDposition=0;
selectNextComet(); //Select the next comet colour
waitForNextComet(); //wait for the next comet (either 60 seconds or button press)
}
}
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
// add one to the current pattern number, and wrap around at the end
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void rainbow()
{
// FastLED's built-in rainbow generator
fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
void rainbowWithGlitter()
{
// built-in FastLED rainbow, plus some random sparkly glitter
rainbow();
addGlitter(80);
}
void addGlitter( fract8 chanceOfGlitter)
{
if( random8() < chanceOfGlitter) {
leds[ random16(NUM_LEDS) ] += CRGB::White;
}
}
void confetti()
{
// random colored speckles that blink in and fade smoothly
fadeToBlackBy( leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255);
}
void sinelon()
{
// a colored dot sweeping back and forth, with fading trails
fadeToBlackBy( leds, NUM_LEDS, 20);
int pos = beatsin16( 13, 0, NUM_LEDS-1 );
leds[pos] += CHSV( gHue, 255, 192);
}
void bpm()
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int i = 0; i < NUM_LEDS; i++) { //9948
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
}
}
void juggle() {
// eight colored dots, weaving in and out of sync with each other
fadeToBlackBy( leds, NUM_LEDS, 20);
uint8_t dothue = 0;
for( int i = 0; i < 8; i++) {
leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
//comet code
void showLED(int pos, byte LEDhue, byte LEDsat, byte LEDbright){
leds[pos] = CHSV(LEDhue,LEDsat,LEDbright);
FastLED.show();
}
//===================================================================================================================================================
// fadeLEDs(): This function is used to fade the LEDs back to black (OFF)
//===================================================================================================================================================
void fadeLEDs(int fadeVal){
for (int i = 0; i<NUM_LEDS; i++){
leds[i].fadeToBlackBy( fadeVal );
}
}
//===================================================================================================================================================
// setDelay() : is where the speed of the LED animation sequence is controlled. The speed of the animation is controlled by the LEDSpeed variable.
// and cannot go faster than the maxLEDSpeed variable.
//===================================================================================================================================================
void setDelay(int LSpeed){
animationDelay = maxLEDSpeed - abs(LSpeed);
delay(animationDelay);
}
//===================================================================================================================================================
//selectNextComet() : This is where we select either the Blue, the Pink or the White comet
//===================================================================================================================================================
void selectNextComet(){
cometNumber++;
if(cometNumber>3){
cometNumber=1;
}
switch(cometNumber){
case 1: { //Blue Comet
hue = 160;
sat = 255;
hueRange=20;
break;
}
case 2: { //Pink Comet
hue = 224;
sat = 120;
hueRange=10;
break;
}
default: { //White Comet
hue = 0;
sat = 0;
hueRange = 0;
break;
}
}
}
//===================================================================================================================================================
// waitForNextComet() : Is where we either wait for 60 seconds for another comet to come, or initiate another comet with a button press.
// The button will only be "ACTIVE" while we are waiting for the next comet. It has no effect while a comet is currently running
//===================================================================================================================================================
void waitForNextComet(){
endTime = millis() + waitTime;
while(millis()<endTime){
if(digitalRead(BUTTON)==LOW){
break;
}
}
}
//end