#include "FastLED.h" // Incluye la biblioteca FastLED para controlar LEDs
#include "faces.h" // Incluye un archivo de cabecera que contiene las definiciones de las caras animadas
// Tamaño de la matriz de LEDs
#define NUM_ROWS 28
#define NUM_COLS 26
// Define los pines de conexión
#define DATA_PIN 3 // Pin de datos para la matriz de LEDs
#define BUTTON_0 9 // Pin para el primer botón
#define BUTTON_1 10 // Pin para el segundo botón
#define BUTTON_2 11 // Pin para el tercer botón
// Brillo de los LEDs
#define BRIGHTNESS 255 // Se establece el brillo de los LEDs en su valor máximo (255)
// Define el arreglo de LEDs
#define NUM_LEDS NUM_ROWS * NUM_COLS // Calcula el número total de LEDs en la matriz
CRGB leds[NUM_LEDS]; // Crea un arreglo para controlar los LEDs
// Controles de animación
byte pressed = 1; // Rastrea qué cara se está mostrando actualmente
bool button0Pressed = false; // Variable para verificar si el botón 0 se ha presionado
bool button1Pressed = false; // Variable para verificar si el botón 1 se ha presionado
bool button2Pressed = false; // Variable para verificar si el botón 2 se ha presionado
void setup() {
pinMode(BUTTON_0, INPUT_PULLUP); // Configura el pin del botón 0 como entrada con resistencia pull-up
pinMode(BUTTON_1, INPUT_PULLUP); // Configura el pin del botón 1 como entrada con resistencia pull-up
pinMode(BUTTON_2, INPUT_PULLUP); // Configura el pin del botón 2 como entrada con resistencia pull-up
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); // Inicializa FastLED para controlar la matriz de LEDs
FastLED.setBrightness(BRIGHTNESS); // Establece el brillo de los LEDs
mid(); // Inicia la visualización con la cara orientada hacia adelante
}
void loop() {
// Lee las entradas de los botones
button0Pressed = digitalRead(BUTTON_0) == LOW; // Verifica si el botón 0 se ha presionado
button1Pressed = digitalRead(BUTTON_1) == LOW; // Verifica si el botón 1 se ha presionado
button2Pressed = digitalRead(BUTTON_2) == LOW; // Verifica si el botón 2 se ha presionado
// Si se ha producido una entrada Y es diferente a la cara actual, muestra esa cara
if (button0Pressed && !(pressed == 0)) {
pressed = 0; // Establece la cara mostrada como la cara izquierda
left(); // Muestra la cara izquierda
}
if (button1Pressed && !(pressed == 1)) {
pressed = 1; // Establece la cara mostrada como la cara central
mid(); // Muestra la cara central
}
if (button2Pressed && !(pressed == 2)) {
pressed = 2; // Establece la cara mostrada como la cara derecha
right(); // Muestra la cara derecha
}
// Parpadea los ojos ocasionalmente
EVERY_N_MILLISECONDS_I(blinktime, 1000) {
blinking(); // Realiza la animación de parpadeo
// Después del parpadeo, vuelve a la cara anterior
switch (pressed) {
case 0: left(); break; // Si la cara era la izquierda, muestra la cara izquierda nuevamente
case 1: mid(); break; // Si la cara era la central, muestra la cara central nuevamente
case 2: right(); break; // Si la cara era la derecha, muestra la cara derecha nuevamente
}
// Establece el próximo retraso de parpadeo
blinktime.setPeriod( random16(1000, 3000) ); // El parpadeo ocurre en intervalos aleatorios entre 1 y 3 segundos
}
}
// Funciones relacionadas con las caras:
void mid() {
// Lee la cara hacia adelante desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(IdleFace + i); // Lee los datos de la cara desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
}
void left() {
// Lee la cara izquierda desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(LeftFace + i); // Lee los datos de la cara izquierda desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
}
void right() {
// Lee la cara derecha desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(RightFace + i); // Lee los datos de la cara derecha desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
}
void blinking() {
// Elige la cara de parpadeo adecuada según la dirección actual
switch (pressed) {
case 0: leftB(); break; // Si la cara era la izquierda, realiza el parpadeo de la cara izquierda
case 1: midB(); break; // Si la cara era la central, realiza el parpadeo de la cara central
case 2: rightB(); break; // Si la cara era la derecha, realiza el parpadeo de la cara derecha
}
}
void midB() {
// Lee la cara de parpadeo desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(IdleBlink + i); // Lee los datos de la cara de parpadeo desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
// Mantiene el parpadeo durante 50 milisegundos para que sea visible
delay(50);
}
void leftB() {
// Lee la cara de parpadeo desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(LeftBlink + i); // Lee los datos de la cara de parpadeo izquierda desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
// Mantiene el parpadeo durante 50 milisegundos para que sea visible
delay(50);
}
void rightB() {
// Lee la cara de parpadeo desde la memoria de programa y la muestra
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(RightBlink + i); // Lee los datos de la cara de parpadeo derecha desde la memoria de programa
}
FastLED.show(); // Actualiza la visualización en la matriz de LEDs
// Mantiene el parpadeo durante 50 milisegundos para que sea visible
delay(50);
}