/*# =============================================================================
# UNIVERSIDAD INTERNACIONAL DE LA RIOJA (UNIR) - MAESTRÍA INDUSTRIA 4.0
# Actividad: Manejo y programación del display de siete segmentos (Actividad 3)
# Descripción: Visualización de nombre "HENRY" y Dado Electrónico + Logs Consola
# Autor: [Henry] - Versión: 1.2 - Fecha: [27/11/2025]
# =============================================================================*/
// ============ CONFIGURACIÓN DE HARDWARE Y PINES ============
// Configuración de pines para segmentos en orden: {A, B, C, D, E, F, G}
// Mapping físico solicitado: A=17, B=5, C=15, D=2, E=0, F=16, G=4
const int PINES_GPIO_SEGMENTOS[7] = {17, 5, 15, 2, 0, 16, 4};
#define PIN_BOTON_DADO 12 // GPIO12 para el pulsador del dado
// ============ PARÁMETROS DE OPERACIÓN Y CONSTANTES ============
// Patrones Hexadecimales para Ánodo Común (Lógica Inversa: 0=ON, 1=OFF)
// Los índices corresponden a los dígitos 0-9
const byte PATRONES_HEX_DIGITOS[10] = {
0xC0, // 0: 11000000
0xF9, // 1: 11111001
0xA4, // 2: 10100100
0xB0, // 3: 10110000
0x99, // 4: 10011001
0x92, // 5: 10010010
0x82, // 6: 10000010
0xF8, // 7: 11111000
0x80, // 8: 10000000
0x90 // 9: 10010000
};
// Secuencia numérica del nombre "HENRY"
// Desglose: H(8), E(5), N(14->1,4), R(18->1,8), Y(25->2,5)
const int DIGITOS_SECUENCIA_NOMBRE[] = {8, 5, 1, 4, 1, 8, 2, 5};
const int LONGITUD_TOTAL_SECUENCIA = 8;
const unsigned long INTERVALO_ACTUALIZACION_SECUENCIA = 1000; // Tiempo entre letras (ms)
const unsigned long RETARDO_ANTIRREBOTE_BOTON = 50; // Tiempo de anti-rebote (ms)
// ============ VARIABLES DE ESTADO GLOBALES ============
int indice_secuencia_actual = 0;
unsigned long tiempo_ultima_actualizacion_secuencia = 0;
int ultimo_estado_boton = HIGH; // Estado inicial HIGH por Input Pullup
unsigned long tiempo_ultimo_rebote = 0;
// ============ PROTOTIPOS DE FUNCIONES ============
void gestionar_entrada_boton();
void procesar_secuencia_nombre();
void ejecutar_modo_dado();
void renderizar_digito_en_display(int numero);
void limpiar_display();
// ============ FUNCIÓN DE CONFIGURACIÓN PRINCIPAL (setup) ============
void setup() {
Serial.begin(115200);
Serial.println("Iniciando Sistema: Display Nombre + Dado Electrónico...");
Serial.println("Esperando ciclo de nombre...");
// Configuración de pines del display como salida
for (int i = 0; i < 7; i++) {
pinMode(PINES_GPIO_SEGMENTOS[i], OUTPUT);
// Inicializar en HIGH para asegurar que estén APAGADOS (Ánodo Común)
digitalWrite(PINES_GPIO_SEGMENTOS[i], HIGH);
}
// Configuración del botón con resistencia interna pull-up
// El estado normal será HIGH, al pulsar será LOW
pinMode(PIN_BOTON_DADO, INPUT_PULLUP);
// Semilla aleatoria basada en ruido analógico para entropía real
randomSeed(analogRead(34));
}
// ============ BUCLE DE EJECUCIÓN PRINCIPAL (loop) ============
void loop() {
gestionar_entrada_boton();
// Si el botón NO está presionado, ejecutamos la secuencia del nombre
if (digitalRead(PIN_BOTON_DADO) == HIGH) {
procesar_secuencia_nombre();
}
}
// ============ DEFINICIÓN DE FUNCIONES AUXILIARES ============
/**
* Gestiona la lectura del pulsador con filtro anti-rebote (debounce).
* Si se detecta una pulsación válida (LOW), activa el modo "Dado".
*/
void gestionar_entrada_boton() {
int lectura_actual = digitalRead(PIN_BOTON_DADO);
if (lectura_actual != ultimo_estado_boton) {
tiempo_ultimo_rebote = millis();
}
if ((millis() - tiempo_ultimo_rebote) > RETARDO_ANTIRREBOTE_BOTON) {
if (lectura_actual == LOW) {
Serial.println("\n>> INTERRUPCIÓN: Pulsador detectado -> Iniciando Dado <<");
ejecutar_modo_dado();
// Al retornar, reseteamos temporizador y log
tiempo_ultima_actualizacion_secuencia = millis();
Serial.println("\n>> Retomando ciclo de nombre (HENRY)...");
}
}
ultimo_estado_boton = lectura_actual;
}
/**
* Controla la visualización secuencial del nombre de forma no bloqueante.
* Utiliza millis() e imprime en consola el estado actual.
*/
void procesar_secuencia_nombre() {
unsigned long tiempo_actual = millis();
if (tiempo_actual - tiempo_ultima_actualizacion_secuencia >= INTERVALO_ACTUALIZACION_SECUENCIA) {
tiempo_ultima_actualizacion_secuencia = tiempo_actual;
int digito_a_mostrar = DIGITOS_SECUENCIA_NOMBRE[indice_secuencia_actual];
// Impresión en Consola
Serial.print("[Ciclo Nombre] Índice ");
Serial.print(indice_secuencia_actual);
Serial.print(": Mostrando dígito -> ");
Serial.println(digito_a_mostrar);
renderizar_digito_en_display(digito_a_mostrar);
// Avanzar índice circularmente
indice_secuencia_actual++;
if (indice_secuencia_actual >= LONGITUD_TOTAL_SECUENCIA) {
indice_secuencia_actual = 0;
limpiar_display();
// Log opcional para indicar fin de vuelta
Serial.println("--- Fin de secuencia 'HENRY', reiniciando ---");
}
}
}
/**
* Ejecuta la lógica del dado electrónico con animación.
*/
void ejecutar_modo_dado() {
// 1. Animación visual
for (int i = 0; i < 12; i++) {
renderizar_digito_en_display(random(1, 7));
delay(50 + (i * 15));
limpiar_display();
delay(10);
}
// 2. Resultado final
int resultado_dado = random(1, 7);
Serial.print(">>> RESULTADO DEL DADO: ");
Serial.println(resultado_dado);
renderizar_digito_en_display(resultado_dado);
delay(2000); // Mantener resultado
limpiar_display();
indice_secuencia_actual = 0;
}
/**
* Renderiza un número en el display de 7 segmentos (Ánodo Común).
*/
void renderizar_digito_en_display(int numero) {
if (numero < 0 || numero > 9) return;
byte patron = PATRONES_HEX_DIGITOS[numero];
for (int i = 0; i < 7; i++) {
bool estado_bit = bitRead(patron, i);
digitalWrite(PINES_GPIO_SEGMENTOS[i], estado_bit);
}
}
void limpiar_display() {
for (int i = 0; i < 7; i++) {
digitalWrite(PINES_GPIO_SEGMENTOS[i], HIGH);
}
}