#define LED_STRIPE 29 #define MODE_BTN_PIN 14 #define BMINUS_BTN_PIN 15 #define BPLUS_BTN_PIN 26 // declare as volaile to not optimize them by the compiler and use them in interrupts volatile int btn_state = 0; volatile bool do_loop = true; volatile bool debounce = false; volatile int max_brightness = 255; // function to adjust the delay when the max_brightness decrements unsigned long adjustedDelay(unsigned long baseDelay) { const int fullRange = 255 - 10; int currentRange = max_brightness - 10; float scale = (float)fullRange / currentRange; return (unsigned long)(baseDelay * scale * 3.0); } void mode_interrupt(){ if(debounce) return; btn_state++; do_loop = false; debounce = true; // set debounce flag to prevent mode skips because of mechanical button bounces } void brighness_minus_interrupt(){ if(max_brightness <= 10) { max_brightness = 10; return; } max_brightness -= 10; } void brighness_plus_interrupt(){ if(max_brightness >= 255){ max_brightness = 255; return; } max_brightness += 10; } void blink(){ while(do_loop){ analogWrite(LED_STRIPE, max_brightness); delay(500); digitalWrite(LED_STRIPE, LOW); delay(500); } } void bounce(){ int direction = 1; int i = 10; int step = 20; const int minStep = 1; while(do_loop){ i += direction * step; if(i >= max_brightness){ i = max_brightness; direction = -1; step = 20; } if(i <= 10){ i = 10; direction = 1; step = 20; } if(step > minStep){ step--; } analogWrite(LED_STRIPE, i); delay(adjustedDelay(20)); } } void bounce_fast_step(){ int direction = 1; int i = 10; const int minStep = 1; const int maxStep = 20; while(do_loop){ int step; if(direction > 0){ step = map(i, 10, max_brightness, minStep, maxStep); } else{ step = map(i, max_brightness, 10, maxStep, minStep); } i += direction * step; if(i >= max_brightness){ i = max_brightness; direction = -1; } if(i <= 10){ i = 10; direction = 1; } analogWrite(LED_STRIPE, i); delay(adjustedDelay(30)); } } void fade(){ while(true){ for(int i = 10; i < max_brightness; i++){ if(!do_loop) return; analogWrite(LED_STRIPE, i); delay(adjustedDelay(20)); } for(int i = max_brightness; i > 10; i--){ if(!do_loop) return; analogWrite(LED_STRIPE, i); delay(adjustedDelay(20)); } } } void on(){ while(do_loop){ analogWrite(LED_STRIPE, max_brightness); delay(10); } } void off(){ digitalWrite(LED_STRIPE, LOW); while(do_loop){ delay(10); } } void setup() { Serial.begin(115200); pinMode(LED_STRIPE, OUTPUT); pinMode(MODE_BTN_PIN, INPUT_PULLUP); pinMode(BMINUS_BTN_PIN, INPUT_PULLUP); pinMode(BPLUS_BTN_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(MODE_BTN_PIN), mode_interrupt, RISING); attachInterrupt(digitalPinToInterrupt(BMINUS_BTN_PIN), brighness_minus_interrupt, RISING); attachInterrupt(digitalPinToInterrupt(BPLUS_BTN_PIN), brighness_plus_interrupt, RISING); Serial.println("INIT DONE!"); } void loop() { debounce = false; do_loop = true; switch(btn_state){ case 0: Serial.println("ON"); on(); break; case 1: Serial.println("FADE"); fade(); break; case 2: Serial.println("BOUNCE"); bounce(); break; case 3: Serial.println("BOUNCE (fast step)"); bounce_fast_step(); break; case 4: Serial.println("BLINK"); blink(); break; default: if(btn_state != -1){ Serial.println("OFF"); btn_state = -1; off(); } break; } Serial.print("Current brightness: "); Serial.println(max_brightness); }