#include <Adafruit_NeoPixel.h>
// Configuración de pines
#define LED_PIN 8 // Pin de datos para los WS2812
#define BUTTON_PIN 9 // Pin del botón
#define NUM_LEDS 4 // Número de LEDs
// Crear objeto NeoPixel
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Variables para el control del botón
int buttonState;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
// Modos de la linterna
enum Mode {
OFF, // 0 - Apagada
WHITE_LOW, // 1 - Luz blanca baja
WHITE_HIGH, // 2 - Luz blanca alta
RED_NIGHT, // 3 - Luz roja nocturna
POLICE_FLASH, // 4 - Parpadeo policía futurista
POLICE_ALTERNATE // 5 - Parpadeo policía alternado
};
Mode currentMode = OFF;
// Variables para el efecto policía
unsigned long lastFlashTime = 0;
int flashState = 0;
void setup() {
Serial.begin(115200);
// Inicializar el botón con pull-up interno
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Inicializar la tira de LEDs
strip.begin();
strip.show(); // Inicializar todos los LEDs apagados
strip.setBrightness(255); // Brillo máximo por defecto
Serial.println("Linterna LED iniciada");
}
void loop() {
// Leer el estado del botón con debounce
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
// Si el botón se presionó (cambio de HIGH a LOW)
if (buttonState == LOW) {
changeMode();
}
}
}
lastButtonState = reading;
// Ejecutar el modo actual
executeMode();
}
void changeMode() {
// Cambiar al siguiente modo
currentMode = (Mode)((currentMode + 1) % 6);
Serial.print("Modo cambiado a: ");
Serial.println(currentMode);
// Resetear estado del parpadeo
flashState = 0;
lastFlashTime = millis();
}
void executeMode() {
switch(currentMode) {
case OFF:
setAllLEDs(0, 0, 0);
break;
case WHITE_LOW:
strip.setBrightness(80); // ~30% de brillo
setAllLEDs(255, 255, 255);
break;
case WHITE_HIGH:
strip.setBrightness(255); // 100% de brillo
setAllLEDs(255, 255, 255);
break;
case RED_NIGHT:
strip.setBrightness(100); // Brillo moderado para modo nocturno
setAllLEDs(255, 0, 0);
break;
case POLICE_FLASH:
policeFlashEffect();
break;
case POLICE_ALTERNATE:
policeAlternateEffect();
break;
}
}
void setAllLEDs(uint8_t r, uint8_t g, uint8_t b) {
for(int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(r, g, b));
}
strip.show();
}
void policeFlashEffect() {
unsigned long currentTime = millis();
// Tiempos variables para cada estado (en milisegundos)
int flashTimings[] = {80, 40, 200, 80, 80, 40, 150, 60, 300};
if (currentTime - lastFlashTime > flashTimings[flashState]) {
lastFlashTime = currentTime;
strip.setBrightness(255);
switch(flashState) {
case 0:
// Azul brillante
setAllLEDs(0, 50, 255);
break;
case 1:
// Negro (pausa corta)
setAllLEDs(0, 0, 0);
break;
case 2:
// Negro (pausa larga)
setAllLEDs(0, 0, 0);
break;
case 3:
// Cian intenso
setAllLEDs(0, 255, 255);
break;
case 4:
// Púrpura
setAllLEDs(180, 0, 255);
break;
case 5:
// Negro (pausa corta)
setAllLEDs(0, 0, 0);
break;
case 6:
// Negro (pausa media)
setAllLEDs(0, 0, 0);
break;
case 7:
// Flash blanco breve
setAllLEDs(255, 255, 255);
break;
case 8:
// Negro (pausa larga)
setAllLEDs(0, 0, 0);
break;
}
flashState++;
if (flashState > 8) {
flashState = 0;
}
}
}
void policeAlternateEffect() {
unsigned long currentTime = millis();
// Alternar cada 150ms
if (currentTime - lastFlashTime > 150) {
lastFlashTime = currentTime;
strip.setBrightness(255);
if (flashState == 0) {
// LEDs 0 y 1 en ROJO, LEDs 2 y 3 APAGADOS
strip.setPixelColor(0, strip.Color(255, 0, 0));
strip.setPixelColor(1, strip.Color(255, 0, 0));
strip.setPixelColor(2, strip.Color(0, 0, 0));
strip.setPixelColor(3, strip.Color(0, 0, 0));
flashState = 1;
} else {
// LEDs 0 y 1 APAGADOS, LEDs 2 y 3 en AZUL
strip.setPixelColor(0, strip.Color(0, 0, 0));
strip.setPixelColor(1, strip.Color(0, 0, 0));
strip.setPixelColor(2, strip.Color(0, 0, 255));
strip.setPixelColor(3, strip.Color(0, 0, 255));
flashState = 0;
}
strip.show();
}
}