1 button 1 led fade

im trying to make a 1 button 1 led fade so that when i hold the button the led fades bright when i let go it stops at that brightness, but when i press the button the second time i want it to fade out instead of going to max bright then fading out i don't know where to start but i have a code for what i described i don't want
`int led = 9;
int brightness= 0;
int fadeAmount = 1;
int OUTPUTS;
void setup() {
pinMode(8, INPUT_PULLUP);
pinMode(led,OUTPUTS);

}
void loop () {
int button_press=digitalRead(8);
if(button_press == LOW) {
analogWrite (led, brightness);

brightness = brightness + fadeAmount;

if(brightness <= 0 or brightness >= 255) {
  fadeAmount = -fadeAmount;
}
delay(30);

}
}
`

should have indented beter but this code when button is helt fades in stops when button is relesed and when to press again it goes max bright before fading out

Do You release the button during fade up or fade down?

yes. you push and hold the button and once it gets to the max brightness i want it to stop but if its in a mid brightness and you want it down just let go and press it again to start going down rather that just going to max bright then fading out

Make it a drawing, a picture, a step by step description.
Your reply is one long sentence. Long sentences often makes the message going wrong.

i want
1; push and hold button results in fade in (stop at max)
2 release of button at any time pauses light at current brightness
3; press button second time results in fade out (stop at light off)
4; release of button at any time pauses light at current brightness
5; repeat

i have
1; push and hold button results in fade in then out once max is reached
2; release of button at any time pauses light at current brightness
3;press button second time continues from where light state was fading in or out
(its pretty much a fade in fade out loop that you can pause by releasing the button)

You are reinitialising your button_press every iteration of loop().
You should remember the state of button_press, so store it in a variable.
Once you do that, you can find out whether the button is still pressed or if it has been released in the mean time.
If it is pressed again after a release, you can use the same mechanism you already have to reverse the direction of fade.

thanks.
The code looks like doing that, to me. It starts fading up and at maximum it goes into fade down and then reverses. Whenever You release the button the light stays where it is. When pressing again the action continues at the cycle point it was stopped.
What's wrong in that?

i will try and remember the buttonstate i think i had that setup yesterday and it didn't work.
The person im making this for needs it to work specifically like this im not sure why. they had a much longer code to do the same as this

Hello codynutbrain

This is a very good task description.

Take a view to the IPO model to get started:

INPUT: read and debounce botton
PROCESS: analyze current button state wrt 'becomes' either 'pressed' or 'released'
OUTPUT: using this button state to run a timer to dim the led as specified.

Have a nice day and enjoy coding in C++.

Does it even compile?

For "or" (logical OR operator) "||" is used.

So it will be
if(brightness <= 0 || brightness >= 255)

@codynutbrain
I would use a finite state machine.
I see 4 states:

      IDLE,                          // wait for button press
      DIMMUP,                        // push and hold button results in fade in (stop at max)
      HOLD,                          // stay in setted brightness
      DIMMDOWN                       // press button second time results in fade out (stop at light off)

once the states for the state machine are clear, the code can be written top down:

/*
  fade PWM pins

  https://forum.arduino.cc/t/1-button-1-led-fade/1113139/4
  2023-04-10 by noiasca
  to be deleted: 2023-06
  code in forum
*/

// a class for one button, one LED
class Dimmer {
    const uint8_t buttonPin;         // the input GPIO, active LOW
    const uint8_t ledPin;            // the output GPIO, active HIGH, must be a PWM pin
    uint8_t brightness = 0;          // current PWM for output pin
    uint32_t previousMillis = 0;     // time management
    enum State {
      IDLE,                          // wait for button press
      DIMMUP,                        // push and hold button results in fade in (stop at max)
      HOLD,                          // stay in setted brightness
      DIMMDOWN                       // press button second time results in fade out (stop at light off)
    } state;
    const uint8_t intervalUp = 50;   // up interval / debounce button
    const uint8_t intervalDown = 10;

  public:
    Dimmer(uint8_t buttonPin, uint8_t ledPin) : buttonPin{buttonPin}, ledPin{ledPin}
    {}

    void begin() {                         // to be called in setup()
      pinMode(buttonPin, INPUT_PULLUP);
      pinMode(ledPin, OUTPUT);
    }

    // just a function to print debug information to Serial
    void debug() {
      Serial.print(ledPin); Serial.print(F("\t")); Serial.println(brightness);
    }

    void update(uint32_t currentMillis = millis()) {   // to be called in loop()
      uint8_t buttonState = digitalRead(buttonPin);
      switch (state) {
        case State::IDLE :
          if (buttonState == LOW) {
            previousMillis = currentMillis;
            brightness = 1;
            analogWrite(ledPin, brightness);
            state = State::DIMMUP;             // switch to next state
            debug();
          }
          break;
        case State::DIMMUP :
          if (currentMillis - previousMillis > intervalUp) {
            if (buttonState == LOW) {
              previousMillis = currentMillis;
              if (brightness < 255) brightness++;  // increase if possible
              analogWrite(ledPin, brightness);
              debug();
            }
            else {
              state = State::HOLD;                // button isn't pressed any more - goto to next state
            }
          }
          break;
        case State::HOLD :
          if (currentMillis - previousMillis > intervalDown) {
            if (buttonState == LOW) {
              previousMillis = currentMillis;
              if (brightness > 0) brightness--;  // decrease if possible
              analogWrite(ledPin, brightness);
              state = DIMMDOWN;                  // goto next state
              debug();
            }
          }
          break;
        case State::DIMMDOWN :
          if (currentMillis - previousMillis > intervalDown) {
            previousMillis = currentMillis;
            if (brightness > 0) brightness--;
            analogWrite(ledPin, brightness);
            debug();
            if (brightness == 0) state = State::IDLE;  // go back to IDLE
          }
          break;
      }
    }
};

//create  instances (each with one button and one led/LED)
Dimmer dimmer[] {
  {A0, 3},  // buttonPin, ledPin
  {A1, 5},
  {A2, 6},
};

void setup() {
  Serial.begin(115200);
  for (auto &i : dimmer) i.begin();  // call begin for all instances
}

void loop() {
  for (auto &i : dimmer) i.update(); // call update() for all instances
}

example on wokwi:

further explanation on:
http://werner.rothschopf.net/microcontroller/202304_millis_dimmer_fading_led.htm

This code doesn't block other activities and can run "in near parallel".

If you only have one button/one LED just comment out the other definitions (or delete them):

Dimmer dimmer[] {
  {A0, 3},  // buttonPin, ledPin
//  {A1, 5},
//  {A2, 6},
};

You are making things complicated for Op.
Your code is good but difficult for beginners to understand.

The code is not working as he wants. In your code after pressing button first time it the value start increase and rest at the position after releasing the button but when you press second time the value suddenly drops to 0 and start increasing.

this is how I understood

can't follow your comment on

because this is what he describes at

Why?

To have a good example is the best way to learn.

Have a nice day and enjoy coding in C++.

p.s. If you don´t like to learn ignore this proper example to learn the ussage of classes simple.

May be I am wrong. What i understood is that on second time pressing the button the led brightness should decrease and stop when reached to 0 .

this happens if you press the button and hold it until 0 is reached. Then the first condition starts again.
This behaviour can be changed if you only go back in IDLE state if button isn't pressed anymore.

if (brightness == 0 && buttonState != LOW) state = State::IDLE;  // go back to IDLE - alternative if you don't want to restart in case button is still pressed.

but that's not specified by @codynutbrain up to now.

I have seen beginners struggling using millis instead of delay
@noiasca is using 2d array, enumeration, calling function .... which make me think that it may be difficult for Op to understand the code.
i didn't want to seem rude though

I think he will be able to ask in case of not understanding.

You are next Advocatus for the beginners?

You might provide an example that reflects the paradigm of procedural coding.

Have a nice day and enjoy coding in C++.

after reading again all TO posts ... if words are not enough maybe a picture is?

modified:
1; push and hold button results in fade in (stop at max)
2; release of button during DIMMUP phase pauses light at current brightness
3; press button and hold time in DIMMDOWN phase results in fade out (stop at light off)
4; release of button during DIMMUP phase pauses light at current brightness
5; repeat when brightness is 0 and button was released

or in 3rd party words:
increase starts only at 0, with a single push and hold
decrease with several push and holds

if this is what you @codynutbrain want, please let me know - I have an updated sketch available.