#include <Adafruit_NeoPixel.h>
#define PIN_DATOS 8
#define PIN_POTENCIOMETRO A1
#define ANCHO 30
#define ALTO 8
#define NUM_LEDS 240
Adafruit_NeoPixel tira(NUM_LEDS, PIN_DATOS, NEO_GRB + NEO_KHZ800);
// --- VARIABLES DEL HISTORIAL DE AUDIO ---
uint32_t coloresFila[ALTO];
uint32_t colorRojoPico;
int historialAlturas[ANCHO];
int historialPicos[ANCHO];
int tiempoEsperaPico[ANCHO];
const int retrasoFlotando = 4;
// --- VARIABLES DE CONTROL DE MODO (SILENCIO) ---
int ultimaLecturaPot = 0;
unsigned long tiempoUltimoSonido = 0;
const unsigned long tiempoParaEspera = 2000;
// --- VARIABLES DE LA PELOTITA REBOTADORA ---
int pelotaX = 15;
int pelotaY = 4;
int velocidadX = 1;
int velocidadY = 1;
uint32_t colorPelota;
void setup() {
tira.begin();
tira.setBrightness(150); // Subido el brillo general de la tira para mayor claridad
colorRojoPico = tira.Color(255, 0, 0);
// Colores base del ecualizador
coloresFila[0] = tira.Color(0, 255, 0);
coloresFila[1] = tira.Color(0, 255, 0);
coloresFila[2] = tira.Color(0, 255, 0);
coloresFila[3] = tira.Color(150, 255, 0);
coloresFila[4] = tira.Color(255, 255, 0);
coloresFila[5] = tira.Color(255, 150, 0);
coloresFila[6] = tira.Color(255, 0, 0);
coloresFila[7] = colorRojoPico;
for (int i = 0; i < ANCHO; i++) {
historialAlturas[i] = 0;
historialPicos[i] = 0;
tiempoEsperaPico[i] = 0;
}
randomSeed(analogRead(A0));
cambiarColorPelota();
tiempoUltimoSonido = millis();
}
void loop() {
tira.clear();
int lecturaPot = analogRead(PIN_POTENCIOMETRO);
if (abs(lecturaPot - ultimaLecturaPot) > 15 || lecturaPot > 30) {
tiempoUltimoSonido = millis();
ultimaLecturaPot = lecturaPot;
}
// --- MODO 1: GRÁFICA DE AUDIO (RECORRIDO) ---
if (millis() - tiempoUltimoSonido < tiempoParaEspera) {
for (int x = 0; x < ANCHO - 1; x++) {
historialAlturas[x] = historialAlturas[x + 1];
historialPicos[x] = historialPicos[x + 1];
tiempoEsperaPico[x] = tiempoEsperaPico[x + 1];
}
int nuevaAltura = map(lecturaPot, 0, 1023, 0, ALTO);
historialAlturas[ANCHO - 1] = nuevaAltura;
if (nuevaAltura >= historialPicos[ANCHO - 1]) {
historialPicos[ANCHO - 1] = nuevaAltura;
tiempoEsperaPico[ANCHO - 1] = retrasoFlotando;
}
for (int x = 0; x < ANCHO; x++) {
int alturaBarra = historialAlturas[x];
for (int y = 0; y < alturaBarra; y++) {
int filaInvertida = (ALTO - 1) - y;
int numeroLed = (filaInvertida * ANCHO) + x;
tira.setPixelColor(numeroLed, coloresFila[y]);
}
if (alturaBarra < historialPicos[x]) {
if (tiempoEsperaPico[x] > 0) tiempoEsperaPico[x]--;
else if (historialPicos[x] > 0) historialPicos[x]--;
}
if (historialPicos[x] > 0) {
int nivelPico = historialPicos[x] - 1;
int filaInvertidaPico = (ALTO - 1) - nivelPico;
int numeroLedPico = (filaInvertidaPico * ANCHO) + x;
tira.setPixelColor(numeroLedPico, colorRojoPico);
}
}
pelotaX = 15;
pelotaY = 4;
}
// --- MODO 2: REBOTE DE PELOTITA (SILENCIO) ---
else {
pelotaX += velocidadX;
pelotaY += velocidadY;
bool huboRebote = false;
if (pelotaX <= 0 || pelotaX >= ANCHO - 1) {
velocidadX = -velocidadX;
huboRebote = true;
}
if (pelotaY <= 0 || pelotaY >= ALTO - 1) {
velocidadY = -velocidadY;
huboRebote = true;
}
if (huboRebote) {
cambiarColorPelota();
}
int numeroLedPelota = (pelotaY * ANCHO) + pelotaX;
tira.setPixelColor(numeroLedPelota, colorPelota);
}
tira.show();
delay(70);
}
// CORREGIDO: Lógica de selección de colores de alto brillo para evitar tonos tenues
void cambiarColorPelota() {
int opcionColor = random(0, 6); // Escoge un número al azar entre 0 y 5
switch (opcionColor) {
case 0: colorPelota = tira.Color(255, 0, 0); break; // Rojo Brillante
case 1: colorPelota = tira.Color(0, 255, 0); break; // Verde Brillante
case 2: colorPelota = tira.Color(0, 0, 255); break; // Azul Neón
case 3: colorPelota = tira.Color(255, 255, 0); break; // Amarillo Puro
case 4: colorPelota = tira.Color(255, 0, 255); break; // Magenta / Rosa Fuerte
case 5: colorPelota = tira.Color(0, 255, 255); break; // Cian / Celeste Eléctrico
}
}