/*
fade PWM pins - Version 2
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 and a state machine
class Selector {
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)
WAIT_A,
DIMMDOWN, // press button second time results in fade out (stop at light off)
WAIT_B,
} state;
const uint8_t intervalDebounce = 50;
public:
Selector(uint8_t buttonPin, uint8_t ledPin) : buttonPin{buttonPin}, ledPin{ledPin}
{}
void begin() { // to be called in setup()
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}
void debug() { // just a function to print debug information to Serial
Serial.print(ledPin); Serial.print(F("\t")); Serial.print(state); Serial.print(F("\t")); Serial.println(brightness);
}
void update(uint32_t currentMillis = millis()) { // to be called in loop()
if (currentMillis - previousMillis > intervalDebounce) {
previousMillis = currentMillis;
uint8_t buttonState = digitalRead(buttonPin);
switch (state) {
case State::IDLE :
if (buttonState == LOW) {
debug();
state = State::DIMMUP; // switch to next state
}
break;
case State::DIMMUP :
if (buttonState == LOW) {
if (brightness < 255) brightness++; // increase if possible
analogWrite(ledPin, brightness);
debug();
if (brightness == 0) state = State::WAIT_A; // go back to IDLE
}
else {
state = State::DIMMDOWN; // button isn't pressed any more - goto to next state
}
break;
case State::WAIT_A :
if (buttonState == HIGH) {
debug();
state = State::DIMMDOWN; // goto next state
}
break;
case State::DIMMDOWN :
if (buttonState == LOW) {
if (brightness > 0) brightness--; // decrease if possible
analogWrite(ledPin, brightness);
debug();
if (brightness == 0) state = State::WAIT_B; // go back to IDLE
}
break;
case State::WAIT_B :
if (buttonState == HIGH) {
debug();
state = State::IDLE; // goto next state
}
break;
}
}
}
};
//create instances (each with one button and one led/LED)
Selector selector[] {
{A0, 3}, // buttonPin, ledPin
{A1, 5},
{A2, 6},
};
void setup() {
Serial.begin(115200);
for (auto &i : selector) i.begin(); // call begin for all instances
}
void loop() {
for (auto &i : selector) i.update(); // call update() for all instances
}