#include <Adafruit_NeoPixel.h>
#include "BluetoothSerial.h"
#include <math.h>
BluetoothSerial SerialBT;
#define LED_PIN 2
#define NUM_LEDS 60
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
int currentEffect = -1;
unsigned long effectTimer = 0;
uint16_t effectStep = 0;
// ================= UTILITY =================
void showColor(uint32_t color) {
for (int i = 0; i < NUM_LEDS; i++) strip.setPixelColor(i, color);
strip.show();
}
void resetEffect() {
effectStep = 0;
effectTimer = millis();
strip.clear();
strip.show();
}
// ================= EFFECT FUNCTIONS =================
// 4
void effectRainbow() {
if (millis() - effectTimer > 20) {
for (int i = 0; i < NUM_LEDS; i++)
strip.setPixelColor(i,
strip.gamma32(strip.ColorHSV((i * 65536 / NUM_LEDS) + effectStep * 256)));
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 5–6
void colorWipe(uint32_t color) {
if (millis() - effectTimer > 40) {
strip.setPixelColor(effectStep % NUM_LEDS, color);
strip.show();
effectStep++;
if (effectStep >= NUM_LEDS) {
strip.clear();
effectStep = 0;
}
effectTimer = millis();
}
}
// 7–9
void theater(uint32_t color) {
if (millis() - effectTimer > 60) {
strip.clear();
for (int i = effectStep % 3; i < NUM_LEDS; i += 3)
strip.setPixelColor(i, color);
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 10–13
void meteor(uint32_t color) {
if (millis() - effectTimer > 30) {
for (int i = 0; i < NUM_LEDS; i++) {
uint32_t c = strip.getPixelColor(i);
strip.setPixelColor(i,
(uint8_t)(c >> 16) * 0.7,
(uint8_t)(c >> 8) * 0.7,
(uint8_t)c * 0.7);
}
strip.setPixelColor(effectStep % NUM_LEDS, color);
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 14–16
void wave(uint32_t color) {
if (millis() - effectTimer > 20) {
for (int i = 0; i < NUM_LEDS; i++) {
int lvl = (sin((i + effectStep) * 0.3) + 1) * 127;
strip.setPixelColor(i,
((color >> 16) & 255) * lvl / 255,
((color >> 8) & 255) * lvl / 255,
(color & 255) * lvl / 255);
}
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 19
void rainbowSlow() {
if (millis() - effectTimer > 50) {
effectRainbow();
effectTimer = millis();
}
}
// 20
void rainbowFast() {
if (millis() - effectTimer > 5) {
effectRainbow();
effectTimer = millis();
}
}
// 21
void scanner(uint32_t color) {
if (millis() - effectTimer > 25) {
strip.clear();
int pos = effectStep % (NUM_LEDS * 2);
if (pos >= NUM_LEDS) pos = (NUM_LEDS * 2) - pos - 1;
strip.setPixelColor(pos, color);
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 22
void fadeInOut(uint32_t color) {
if (millis() - effectTimer > 20) {
int b = abs(128 - (effectStep % 256));
strip.setBrightness(b);
showColor(color);
effectStep++;
effectTimer = millis();
}
}
// 23
void sparkle(uint32_t color) {
if (millis() - effectTimer > 40) {
strip.clear();
strip.setPixelColor(random(NUM_LEDS), color);
strip.show();
effectTimer = millis();
}
}
// 24
void confetti() {
if (millis() - effectTimer > 30) {
strip.setPixelColor(random(NUM_LEDS),
strip.Color(random(255), random(255), random(255)));
strip.show();
effectTimer = millis();
}
}
// 25
void runningDot(uint32_t color) {
if (millis() - effectTimer > 40) {
strip.clear();
strip.setPixelColor(effectStep % NUM_LEDS, color);
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 26
void dualChase(uint32_t c1, uint32_t c2) {
if (millis() - effectTimer > 50) {
strip.clear();
strip.setPixelColor(effectStep % NUM_LEDS, c1);
strip.setPixelColor((effectStep + 5) % NUM_LEDS, c2);
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 27
void randomSolid() {
if (millis() - effectTimer > 500) {
showColor(strip.Color(random(255), random(255), random(255)));
effectTimer = millis();
}
}
// 28
void fireFlicker() {
if (millis() - effectTimer > 30) {
for (int i = 0; i < NUM_LEDS; i++)
strip.setPixelColor(i, random(150,255), random(0,80), 0);
strip.show();
effectTimer = millis();
}
}
// 29
void iceFlicker() {
if (millis() - effectTimer > 40) {
for (int i = 0; i < NUM_LEDS; i++)
strip.setPixelColor(i, 0, random(150,255), random(150,255));
strip.show();
effectTimer = millis();
}
}
// 30
void pulseWhite() {
if (millis() - effectTimer > 20) {
int b = abs(128 - (effectStep % 256));
strip.setBrightness(b);
showColor(strip.Color(255,255,255));
effectStep++;
effectTimer = millis();
}
}
// 31
void alternateRB() {
if (millis() - effectTimer > 300) {
for (int i = 0; i < NUM_LEDS; i++)
strip.setPixelColor(i, (i + effectStep) % 2 ?
strip.Color(255,0,0) : strip.Color(0,0,255));
strip.show();
effectStep++;
effectTimer = millis();
}
}
// 32
void greenWave() {
wave(strip.Color(0,255,0));
}
// 33
void rainbowSparkle() {
if (millis() - effectTimer > 50) {
strip.clear();
strip.setPixelColor(random(NUM_LEDS),
strip.ColorHSV(random(65535)));
strip.show();
effectTimer = millis();
}
}
// 34
void policeLights() {
if (millis() - effectTimer > 200) {
showColor(effectStep % 2 ?
strip.Color(255,0,0) : strip.Color(0,0,255));
effectStep++;
effectTimer = millis();
}
}
// ================= EFFECT SELECTOR =================
void runEffect(int e) {
switch (e) {
case 1: showColor(strip.Color(255,0,0)); break;
case 2: showColor(strip.Color(0,255,0)); break;
case 3: showColor(strip.Color(0,0,255)); break;
case 4: effectRainbow(); break;
case 5: colorWipe(strip.Color(255,255,0)); break;
case 6: colorWipe(strip.Color(0,255,255)); break;
case 7: theater(strip.Color(255,0,0)); break;
case 8: theater(strip.Color(0,255,0)); break;
case 9: theater(strip.Color(0,0,255)); break;
case 10: meteor(strip.Color(255)); break;
case 11: meteor(strip.Color(255,0,0)); break;
case 12: meteor(strip.Color(0,255,0)); break;
case 13: meteor(strip.Color(0,0,255)); break;
case 14: wave(strip.Color(255,0,0)); break;
case 15: wave(strip.Color(0,255,0)); break;
case 16: wave(strip.Color(0,0,255)); break;
case 17: showColor(strip.Color(255,0,255)); break;
case 18: showColor(strip.Color(255,255,255)); break;
case 19: rainbowSlow(); break;
case 20: rainbowFast(); break;
case 21: scanner(strip.Color(255,0,0)); break;
case 22: fadeInOut(strip.Color(0,0,255)); break;
case 23: sparkle(strip.Color(255,255,255)); break;
case 24: confetti(); break;
case 25: runningDot(strip.Color(255,255,0)); break;
case 26: dualChase(strip.Color(255,0,0), strip.Color(0,0,255)); break;
case 27: randomSolid(); break;
case 28: fireFlicker(); break;
case 29: iceFlicker(); break;
case 30: pulseWhite(); break;
case 31: alternateRB(); break;
case 32: greenWave(); break;
case 33: rainbowSparkle(); break;
case 34: policeLights(); break;
}
}
// ================= SETUP =================
void setup() {
strip.begin();
strip.setBrightness(150);
strip.show();
Serial.begin(115200);
SerialBT.begin("ESP32_LED");
}
// ================= LOOP =================
void loop() {
if (SerialBT.available()) {
String cmd = SerialBT.readStringUntil('\n');
cmd.trim();
// SOLID COLORS
if (cmd == "R") { currentEffect = -1; showColor(strip.Color(255,0,0)); }
else if (cmd == "G") { currentEffect = -1; showColor(strip.Color(0,255,0)); }
else if (cmd == "B") { currentEffect = -1; showColor(strip.Color(0,0,255)); }
else if (cmd == "Y") { currentEffect = -1; showColor(strip.Color(255,255,0)); }
else if (cmd == "P") { currentEffect = -1; showColor(strip.Color(255,0,255)); }
else if (cmd == "U") { currentEffect = -1; showColor(strip.Color(255,105,180)); }
// EFFECT SELECT
else if (cmd.startsWith("E")) {
int e = cmd.substring(1).toInt();
if (e >= 1 && e <= 34) {
currentEffect = e;
resetEffect();
}
}
}
if (currentEffect > 0) runEffect(currentEffect);
}