I would have single-press for ON, and single-press for OFF (no need for long press). That is to say, whatever state you are in, a single press will switch to the other state.
Where is loop()? You are missing half the sketch.
#include <FastLED.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
#include <EEPROM.h>
#include <LowPower.h>
#define MOSFET_PIN 5 //Power to strip applied via MOSFET
#define DATA_PIN 6
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 16
CRGB leds[NUM_LEDS];
CRGB leds_temp[NUM_LEDS / 2]; //added for half fire
#define FRAMES_PER_SECOND 120
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
uint8_t BRIGHTNESS;
uint8_t gCurrentPatternNumber;
//----------ENCODER SETUP SECTION-------------
ClickEncoder *encoder;
uint8_t last; //, value;
uint8_t value = EEPROM.read(0); //read EEPROM address 0 to set value to last brightness level
void timerIsr() {
encoder->service();
encoder->setDoubleClickEnabled(true);
}
bool brightnessMode = false;
bool setAccelerationEnabled = true;
bool PartyMode = false;
bool gReverseDirection = true; //added for half fire
//---------END ENCODER SETUP-------------------------
//---------------------------------------------------------
//-------------BEGIN TIMING SECTION------------------------
bool ButtonHeld = false;
const unsigned long TenHours = 60UL * 60UL * 1000UL;
const unsigned long TwentyFourHours = 00001; // 60UL * 60UL * 1000UL; //CURRENT OFF TIME = actual OFFTIME=OFFTIME-ONTIME
const unsigned long OneHour = 60UL * 60UL * 1000UL; //CURRENT ON TIME SETTING
const unsigned long TenSeconds = 10000;
const unsigned long EightHours = 8 * OneHour;
//const unsigned long TenHours = 10 * OneHour;
const unsigned long TwelveHours = 10000; //12 * OneHour;
//const unsigned long TwentyFourHours = 24 * OneHour;
// Default to 8 on, 16 off.
unsigned long OnTime = TenSeconds; //-------------CHOOSE TIME TO BE ON FOR--------------
unsigned long StartTime;
const bool LightOnValue = HIGH;
const bool LightOffValue = LOW;
bool LightState = LightOnValue;
//--------------END TIMING SECTION------------------------------------
//--------------------------------------------------------------------
//Light Box Colors Travel CCW with first LED located right of bottom center.
//Define Gradient Palette up here, create gpattern below loop, add gpattern to simplepatternlist
DEFINE_GRADIENT_PALETTE( PurpleOrange_gp ) {
0, 147, 0, 150, //(purple)
110, 255, 69, 0, //(orange)
255, 147, 0, 150 //(purple)
}; //end PurpleOrange_gp
DEFINE_GRADIENT_PALETTE( GreenMint_gp ) {
0, 50, 205, 50, //lime green
110, 245, 255, 250, //mint cream
255, 50, 205, 50 //lime green
}; //end GreenMint_gp
DEFINE_GRADIENT_PALETTE( BlueWhiteYellow_gp ) {
0, 11, 2, 105, //Beast Blue
30, 11, 2, 105,
90, 200, 200, 180,
110, 200, 200, 180, //White
130, 200, 200, 180,
205, 255, 231, 0,
255, 255, 231, 0 //Belle Yellow
}; //end BlueWhiteYellow_gp
DEFINE_GRADIENT_PALETTE( RedYellowRed_gp ) {
0, 139, 0, 0, // Dark Red
60, 139, 0, 0,
//100, 255, 231, 0,
120, 255, 231, 0,
130, 255, 231, 0, //Belle Yellow
//120, 255, 231, 0,
195, 139, 0, 0,
255, 139, 0, 0 // Dark Red
}; //end RedYellowRed_gp
DEFINE_GRADIENT_PALETTE( Sunset_gp ) {
0, 200, 139, 136, //(pink)
120, 253, 184, 19, //OrangeYellow
130, 253, 184, 19, //OrangeYellow
255, 200, 139, 136, //(pink)
}; //end Sunset_gp
DEFINE_GRADIENT_PALETTE( BlueWhite_gp ) {
0, 240, 255, 255,
10, 40, 172, 234,
120, 40, 172, 234, //Blue
110, 240, 255, 255, //White
130, 40, 172, 234,
240, 40, 172, 234, //Blue
255, 240, 255, 255
}; //end BlueWhite_gp
DEFINE_GRADIENT_PALETTE( CandlesOnly_gp ) {
0, 0, 0, 0,
30, 0, 0, 0,
110, 224, 157, 55,
120, 255, 231, 0, //224, 157, 55, //CandleLight
130, 224, 157, 55,
225, 0, 0, 0,
255, 0, 0, 0
}; //end CandlesOnly_gp
//--------------------------------------------------------------------------------------------
//----------BEGIN SETUP-----------------------------------------------------------------------
void setup() {
delay(1000); //sanity delay
Serial.begin(115200);
pinMode (MOSFET_PIN, OUTPUT); //configure MOSFET_PIN as output
digitalWrite(MOSFET_PIN, LOW); //Turn MOSFET ON
if (EEPROM.read(256) != 123) { // not equal to 123 = EEPROM hasn't been used before
EEPROM.put(256, 123); // write value 123 to byte 256
EEPROM.put(0, 120); // Set Default Brightness to 120
EEPROM.put(1, 0); // Set Default Pattern to first
} else { // if byte 256 is equal to 123
EEPROM.get(0, BRIGHTNESS); //Get last brightness value from EEPROM before power failure
EEPROM.get(1, gCurrentPatternNumber); // get last pattern from EEPROM before power failure
}
// tell FastLED about the LED strip configuration
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
// set master brightness control
FastLED.setBrightness(BRIGHTNESS);
FastLED.setTemperature(0xFF7029);
StartTime = millis();
encoder = new ClickEncoder(2, 3, 4);
encoder->setDoubleClickEnabled(true);
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
}//end of Setup
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
// List of patterns to cycle through. Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {
Yellow,
PurpleOrange,
GreenMint,
BlueWhiteYellow,
RedYellowRed,
Sunset,
CandlesOnly,
White,
rainbow,
BlueWhite
};//end SimplePatternList
typedef void (*PartyPatternList[])();
PartyPatternList pPatterns = {
rainbow,
confetti,
sinelon,
rainbowWithGlitter,
juggle,
bpm,
fire,
BlueWhite,
PurpleOrange,
BlueWhiteYellow,
RedYellowRed,
Sunset
}; //end party patterns
//----------------------------------------------------------------------------
//-----------------BEGIN LOOP-------------------------------------------------
void loop() {
//---------BEGIN 24HR TIMER SECTION---------------------
unsigned long currentMillis = millis();
unsigned long interval = (LightState == LightOnValue) ? OnTime : TwentyFourHours - OnTime;
if (currentMillis - StartTime >= interval && ButtonHeld == HIGH)
{
LightState = !LightState;
StartTime += interval;
}
if (LightState == 0 && ButtonHeld == 0) {
LightState = 1;
}
//---------END TIMER SECTION----------------------------------
//------BEGIN ENCODER INTERROGATION---------------------------
value += encoder->getValue();
if (value != last) {
last = value;
if (value == 256)
value = 0; //prevent encoder from exceeding 255
if (value == -1)
value = 255; //prevent encoder from going negative
if (brightnessMode == true) { //begin brightnessMode
BRIGHTNESS = value;
Serial.print("value = ");
Serial.println(value);
Serial.print("Brightness value: ");
Serial.println(BRIGHTNESS);
FastLED.setBrightness(BRIGHTNESS);
}//end brightness mode
else {
if (value < last) {
Serial.print("Current Pattern: ");
Serial.println(gCurrentPatternNumber);
gCurrentPatternNumber = (value);
nextPattern();
}
else {
Serial.print("Current Pattern #! ");
Serial.println(gCurrentPatternNumber);
gCurrentPatternNumber = (value);
prevPattern();
}
}//end pattern mode
} //end Brightness/Pattern Modes
//Begin ClickEncoder Button Modes
ClickEncoder::Button b = encoder->getButton();
if (b != ClickEncoder::Open) {
switch (b) {
case ClickEncoder::Clicked:
Serial.println("Button was clicked");
brightnessMode = !brightnessMode;
if (brightnessMode) {
Serial.println("Knob now controls brightness");
} else {
Serial.println("Knob now controls color");
}
break;
case ClickEncoder::DoubleClicked:
Serial.println("Button was Double Clicked");
PartyMode = !PartyMode;
break;
case ClickEncoder::Held:
Serial.println("Button is being held");
ButtonHeld = !ButtonHeld;
StartTime = millis();
//LightState == !LightState;
Serial.print("ButtonHeld: ");
Serial.println(ButtonHeld);
//delay(1000);
FastLED.clear();
FastLED.show();
if (ButtonHeld) {
LITTOP();
}
else {
LITBOTTOM();
}
FastLED.delay(1000);
//delay(500);
}
} //End ClickEncoder Button Modes
//Begin Lights On Functionality
if (LightState == true) {
// Call the current pattern function once, updating the 'leds' array
if (!PartyMode) {
gPatterns[gCurrentPatternNumber]();
FastLED.show();
}
if (PartyMode) {
// typedef void (*PartyPatternList[])();
//PartyPatternList pPatterns
pPatterns[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( 15 ) {
nextPattern(); // change patterns periodically
}
}
// send the 'leds' array out to the actual LED strip
// insert a delay to keep the framerate modest
FastLED.delay(1000 / FRAMES_PER_SECOND);
EVERY_N_SECONDS( 15 ) {
Serial.println("updating EEPROM if necessary");
EEPROM.put(0, value);
EEPROM.put(1, gCurrentPatternNumber);
Serial.print("EEPROM BRIGHT = ");
Serial.println(value);
Serial.print("EEPROM PATTERN = ");
Serial.println(gCurrentPatternNumber);
}//end of writing to EEPROM every N seconds
}
//End Lights On Functionality
//Begin Lights Off Functionality
else {
Serial.print("millis: ");
Serial.println(millis());
Serial.print("StartTime: ");
Serial.println(StartTime);
FastLED.delay(1000);
FastLED.clear();
FastLED.show();
//begin low power mode after lights turn off
FastLED.delay(500);
digitalWrite(MOSFET_PIN, HIGH); // turn power to strip off
Serial.println("SleepyTime");
FastLED.delay(500);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_ON, SPI_OFF, USART0_OFF, TWI_OFF);
// LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); // Sleep for 8 s with ADC module and BOD module off
FastLED.delay(500);
digitalWrite(MOSFET_PIN, LOW); // turn power to strip on(an interrupt occured, turn power on for safety)
FastLED.delay(500);
Serial.println("wakeywakey"); //show if interrupt occurs waking chip
//end low power mode
}//end lights off functionality
}//end of loop
//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
#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);
// gCurrentPatternNumber = (gCurrentPatternNumber + 1);
// if (gCurrentPatternNumber > ARRAY_SIZE(gPatterns)) {
// gCurrentPatternNumber = ARRAY_SIZE(gPatterns)+1;
// }
}
void prevPattern()
{
gCurrentPatternNumber = (gCurrentPatternNumber - 1) % ARRAY_SIZE( gPatterns);
// gCurrentPatternNumber = (gCurrentPatternNumber - 1);
// if (gCurrentPatternNumber > ARRAY_SIZE(gPatterns)) {
// gCurrentPatternNumber = ARRAY_SIZE(gPatterns) - 1;
// }
}
//begin patterns
void LITBOTTOM() {
leds[0] = CRGB(255, 255, 255);
leds[1] = CRGB(255, 255, 255);
leds[14] = CRGB(255, 255, 255);
leds[15] = CRGB(255, 255, 255);
FastLED.show();
}
void LITTOP() {
leds[6] = CRGB(255, 255, 255);
leds[7] = CRGB(255, 255, 255);
leds[8] = CRGB(255, 255, 255);
leds[9] = CRGB(255, 255, 255);
FastLED.show();
}
void CandlesOnly() {
CRGBPalette16 palette = CandlesOnly_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end CandlesOnly
void BlueWhite() {
CRGBPalette16 palette = BlueWhite_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end BlueWhite
void Sunset() {
CRGBPalette16 palette = Sunset_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end Sunset
void Red() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Red;
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
} // end Red
void Yellow() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Yellow;
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
} // end Yellow
void White() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::White;
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
} // end White
void RedYellowRed() {
CRGBPalette16 palette = RedYellowRed_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end RedYellowRed
void BlueWhiteYellow() {
CRGBPalette16 palette = BlueWhiteYellow_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end BlueWhiteYellow
void PurpleOrange() {
CRGBPalette16 palette = PurpleOrange_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end Purple Orange
void GreenMint() {
CRGBPalette16 palette = GreenMint_gp;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, i * 256 / NUM_LEDS);
}
for (uint16_t i = 0; i < NUM_LEDS; i++)
{
leds[i].r = dim8_video(leds[i].r);
leds[i].g = dim8_video(leds[i].g);
leds[i].b = dim8_video(leds[i].b);
}
}//end GreenMint
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//Begin Party Patterns
//
//
void rainbow()
{
// FastLED's built-in rainbow generator
fill_rainbow( leds, NUM_LEDS, 0, 255 / NUM_LEDS );
//fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
//BlueWhite,
// PurpleOrange,
// GreenMint,
// BlueWhiteYellow,
// RedYellowRed,
// Sunset
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);
byte dothue = 0;
for ( int i = 0; i < 8; i++) {
leds[beatsin16( i + 7, 0, NUM_LEDS - 1 )] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames. More cooling = shorter flames.
// Default 55, suggested range 20-100
#define COOLING 200
// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire. Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 50
void Fire2012()
{
// Array of temperature readings at each simulation cell
static byte heat[NUM_LEDS];
// Step 1. Cool down every cell a little
for ( int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for ( int k = NUM_LEDS - 3; k > 0; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if ( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160, 255) );
}
// Step 4. Map from heat cells to LED colors
for ( int j = 0; j < NUM_LEDS; j++) {
leds[j] = HeatColor( heat[j]);
}
}
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames. More cooling = shorter flames.
// Default 50, suggested range 20-100
#define COOLING 230
// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire. Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 150
//---------------------------------------------------------------
// **** NOTE these changes to the Fire2012 function:
// - function renamed to Fire2012_halfStrip
// - leds was replaced with leds_temp so the fire is drawn into
// the temporary (leds_temp) array.
// - NUM_LEDS was replaced with NUM_LEDS/2 (half the strip length).
// - The gReverseDirection logic was removed from Fire2012 code
// since the reversing happens in the mirror2ndHalf function.
//---------------------------------------------------------------
void Fire2012_halfStrip() {
// Fuction only operates on half the number of pixels (NUM_LEDS/2)
// Array of temperature readings at each simulation cell
static byte heat[NUM_LEDS / 2];
// Step 1. Cool down every cell a little
for ( int i = 0; i < NUM_LEDS / 2; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / (NUM_LEDS / 2)) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for ( int k = (NUM_LEDS / 2) - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
if ( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160, 255) );
}
// Step 4. Map from heat cells to LED colors
for ( int j = 0; j < NUM_LEDS / 2; j++) {
CRGB color = HeatColor( heat[j]);
leds_temp[j] = color;
}
}//end_Fire2012_halfStrip
//---------------------------------------------------------------
void mirror2ndHalf() {
//copy and mirror pixel data from leds_temp to leds array.
if (gReverseDirection == false) { //false is center outward
for (uint8_t i = 0; i < NUM_LEDS / 2; i++) {
leds[(NUM_LEDS / 2) - 1 - i] = leds_temp[i];
leds[(NUM_LEDS / 2) + i] = leds_temp[i];
}
} else { //true is from ends inward
for (uint8_t i = 0; i < NUM_LEDS / 2; i++) {
leds[i] = leds_temp[i];
leds[(NUM_LEDS - 1) - i] = leds_temp[i];
}
}
}//end_mirror2ndHalf
void fire() {
Fire2012_halfStrip(); // draw fire data to leds_temp
mirror2ndHalf(); // copy and mirror data from leds_temp to leds
FastLED.show(); // display leds
FastLED.delay(1000 / FRAMES_PER_SECOND);
// random16_add_entropy( random());
//
// Fire2012(); // run simulation frame
// FastLED.show(); // display this frame
//
//#if defined(FASTLED_VERSION) && (FASTLED_VERSION >= 2001000)
// FastLED.delay(1000 / FRAMES_PER_SECOND);
//#else
// delay(1000 / FRAMES_PER_SECOND);
//#endif
}