/*
* ESP32 18-LED Interactive Controller - FULL VERSION
* Pins: 22, 23, 13, 12, 14, 27, 26, 25, 33, 2, 4, 5, 15, 16, 17, 18, 19, 21
* Button: GPIO 32 (Connect to Pin 32 and GND)
*/
// LED Pin Mapping
const int ledPins[] = {22, 23, 13, 12, 14, 27, 26, 25, 33, 2, 4, 5, 15, 16, 17, 18, 19, 21};
const int totalLeds = 18;
const int buttonPin = 32;
// Variables for Mode Control
volatile int mode = 0;
unsigned long lastDebounceTime = 0;
const int debounceDelay = 250;
// Interrupt Service Routine (ISR) for the button
void IRAM_ATTR changeMode() {
if ((millis() - lastDebounceTime) > debounceDelay) {
mode++;
if (mode > 2) mode = 0;
lastDebounceTime = millis();
}
}
void setup() {
for (int i = 0; i < totalLeds; i++) {
pinMode(ledPins[i], OUTPUT);
digitalWrite(ledPins[i], LOW);
}
// Set up button with internal pullup
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), changeMode, FALLING);
randomSeed(analogRead(0));
}
void loop() {
switch (mode) {
case 0: // Mode 1: Energetic
simpleChase(50);
meetingPoint(80);
break;
case 1: // Mode 2: Shimmering
theaterChase(100);
sparkle(20, 50);
break;
case 2: // Mode 3: Atmospheric
heartbeat(1);
breathingEffect();
break;
}
}
// --- PATTERN FUNCTIONS ---
void simpleChase(int speed) {
for (int i = 0; i < totalLeds; i++) {
digitalWrite(ledPins[i], HIGH);
delay(speed);
digitalWrite(ledPins[i], LOW);
if (mode != 0) return; // Exit early if mode changed
}
}
void meetingPoint(int speed) {
int half = totalLeds / 2;
// Inward
for (int i = 0; i < half; i++) {
digitalWrite(ledPins[i], HIGH);
digitalWrite(ledPins[totalLeds - 1 - i], HIGH);
delay(speed);
digitalWrite(ledPins[i], LOW);
digitalWrite(ledPins[totalLeds - 1 - i], LOW);
}
// Outward
for (int i = half - 1; i >= 0; i--) {
digitalWrite(ledPins[i], HIGH);
digitalWrite(ledPins[totalLeds - 1 - i], HIGH);
delay(speed);
digitalWrite(ledPins[i], LOW);
digitalWrite(ledPins[totalLeds - 1 - i], LOW);
}
}
void theaterChase(int speed) {
for (int q = 0; q < 3; q++) {
for (int i = 0; i < totalLeds; i = i + 3) {
if (i + q < totalLeds) digitalWrite(ledPins[i + q], HIGH);
}
delay(speed);
for (int i = 0; i < totalLeds; i = i + 3) {
if (i + q < totalLeds) digitalWrite(ledPins[i + q], LOW);
}
}
}
void sparkle(int count, int duration) {
for (int i = 0; i < count; i++) {
int index = random(0, totalLeds);
digitalWrite(ledPins[index], HIGH);
delay(duration);
digitalWrite(ledPins[index], LOW);
if (mode != 1) return;
}
}
void heartbeat(int times) {
for (int i = 0; i < times; i++) {
allLeds(HIGH); delay(100);
allLeds(LOW); delay(100);
allLeds(HIGH); delay(150);
allLeds(LOW); delay(600);
}
}
void breathingEffect() {
// Simulating a glow since simple digital pins can't fade without PWM
allLeds(HIGH);
delay(500);
allLeds(LOW);
delay(500);
}
void allLeds(int state) {
for (int i = 0; i < totalLeds; i++) {
digitalWrite(ledPins[i], state);
}
}