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);
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
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
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
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.
@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
}
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 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
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.