Fading LED with memory

I found this code that does pretty much what i want (button press is on/off, and if you hold it down the LED will fade).

But it only fades if the LED is already on. If it’s off, you have to momentary press the button to turn on first, then press and hold again to fade.

I want it to fade up/down when the button is held down, regardless of what state it’s in, and then when the button is let go it remembers where that position is. from there, a momentary press still turns it on/off in the position it remembered from the last fade event.

I’ve been trying all day, I’m missing something dumb i just know it.

/*
Brighness Changer
Change Brightness of an LED

Adapted by Luke Garwood after example 5-2 from Getting Started With Arduino by Massimo Banzi and Michael Shiloh
*/
int LEDPIN = 9; //set up variable LEDPIN as the pin to which the LED connects
int BUTTONPIN = 7; //set up variable BUTTONPIN as the pin to which the button connects
int ButtonValue; // set up variable to hold value input from BUTTONPIN.
int Old_ButtonValue; //set up variable to determine the previous value of ButtonValue
int LightOn = 0; // Used to determine whether the light is on or off, 1 being true = on, 0 being false = off
int Brightness = 0; //sets an initial brightness of 0 (none)
unsigned long startTime = 0; //determines begginning of button press
void setup() { //function that only runs once initially

** pinMode(LEDPIN, OUTPUT); //pinMode(pin number, either INPUT or OUTPUT)**
** //Set up LEDPIN as an output**
** pinMode(BUTTONPIN, INPUT);// Set up BUTTONPIN as an Input (it recieves information from the Arduino rather than sending information/values)**
}
void loop() { //function that continues to loop
** ButtonValue = digitalRead(BUTTONPIN); //digitalRead tells us if the value for this pin is HIGH or LOW**
** //when button is pushed down digitalRead(BUTTONPIN) returns HIGH**
** if((ButtonValue == HIGH) && (Old_ButtonValue == LOW)) { //a condition that asserts if ButtonValue is read as HIGH (button is pushed)**
** //AND was previously LOW**
** LightOn = 1 - LightOn; // this alternates LightOn to be either 1 or 0 (1 being light on, 0 light off)**
** startTime = millis(); // capture a time at button press**

** delay(10); //for debouncing purposes, putting in a delay so that only one button press is registered**
** }**

** if((ButtonValue == HIGH) && (Old_ButtonValue == HIGH)){ // conditions to tell if the button is being held down**
** if(LightOn == 1 && (millis() - startTime) > 20){ //if the button is held for more than 20ms**
** Brightness ++; //incrementally increase brightness**
** delay(35); //delay so brightness doesn’t change too quickly (longer the delay, longer it takes to reach max)**
** if(Brightness > 255){ //once brightness reaches 255**
** Brightness = 0; // reset the LED back to 0**
** }**
** }**
** }**

Old_ButtonValue = ButtonValue; //after the above code has been executed, giving Old_ButtonValue the ButtonValue to detect the moment of button press.
** if(LightOn == 1) { //when light clicks on**
** analogWrite(LEDPIN, Brightness); //turn LED on at whatever value Brightness is at**
** } else {**
** analogWrite(LEDPIN, 0); // or else click light off**
** }**
}

How is the switch wired? It would be simpler wiring if you used the internal pullup resistor.

instead of

   Brightness ++;
    if (Brightness > 255) {
        Brightness = 0;
    }

consider

   static int delta = 1;

    Brightness += delta;

    if (Brightness >= 255)
        delta = -1;
    else if (Brightness <= 0)
        delta =  1;

gcjr:
instead of

   Brightness ++;

if (Brightness > 255) {
        Brightness = 0;
    }




consider


static int delta = 1;

Brightness += delta;

if (Brightness >= 255)
        delta = -1;
    else if (Brightness <= 0)
        delta =  1;

That is better. Now it doesn’t flip back from dim to full… it ramps back up to full. I like that, but it still doesnt work if the LED state is Off. I have to turn it on first for it to work. Not sure if there is a way around this. I think to get what I want I need to have it stay in a fade state, but stop once it hits full or lowest brightness. A subsequent button hold should fade back down.

shouldn't the LED be turned on all the time and the brightness set to zero possibly in setup

gcjr:
shouldn't the LED be turned on all the time and the brightness set to zero possibly in setup

When I put LightOn = 1; in the setup, remove the momentary press, and remove the reverse delta,

void setup() { //function that only runs once initially

pinMode(LEDPIN, OUTPUT); //pinMode(pin number, either INPUT or OUTPUT)
//Set up LEDPIN as an output
pinMode(BUTTONPIN, INPUT);// Set up BUTTONPIN as an Input (it recieves information from the Arduino rather than sending information/values)
LightOn = 1;
}

void loop() { //function that continues to loop
ButtonValue = digitalRead(BUTTONPIN); //digitalRead tells us if the value for this pin is HIGH or LOW
//when button is pushed down digitalRead(BUTTONPIN) returns HIGH

if((ButtonValue == HIGH) && (Old_ButtonValue == HIGH)){ // conditions to tell if the button is being held down
if(LightOn == 1 && (millis() - startTime) > 600){ //if the button is held for more than 20ms
static int delta = 0;

Brightness += delta;

if (Brightness == 255)
delta = -1;
delay(10);
}
}

it now stays in fade mode, holding the button fades, and then it stops when i let go, and resumes when i hold again. but i can't get it to stop after it hits 0. It just goes back to 255 and fades down again and loops like that.

maybe you need to use the momentary button press to to set delta = 0 and the brightness to some specific value

gcjr:
maybe you need to use the momentary button press to to set delta = 0 and the brightness to some specific value

i figured it out!

The hold down button action was only looking for when the light was on (LightOn == 1)

I changed that to LightOn <=1

if((ButtonValue == HIGH) && (Old_ButtonValue == HIGH)){ // conditions to tell if the button is being held down
if(LightOn <= 1 && (millis() - startTime) > 20){ //if the button is held for more than 20ms

I also had to play with the timings to make it work… If the light is ON, and you press and hold, there is still a brief OFF/ON cycle, but that is because of the delay function and I can only bring that down to 20ms before it starts acting weird. It’s fine the way it is though. - YouTube

Now I want to add a double-click to set 100% brightness. But that may not be possible with the current config… i have been playing with other code that is made to do this, but having troubles getting it to work. I just need to spend more sleepless nights on it lol https://forum.arduino.cc/index.php?topic=14479.0
Thanks for your help gcjr!