DÍA 244 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

Física de Alta Tensión: TVS vs MOVs

Para desviar un rayo electromagnético (ESD) lejos de tu STM32, necesitas un componente que sea "invisible" a voltajes normales (3.3V), pero que se convierta en un cortocircuito perfecto hacia tierra (GND) en el instante que el voltaje supere los 5V. Existen dos tecnologías dominantes:

La Topología "Pi" (π) para Entradas Humanas

El estándar industrial para conectar un teclado mecánico a un microcontrolador se basa en 3 etapas defensivas:

  1. El Diodo TVS: Va pegado físicamente al conector de entrada. Desvía el 99% de la furia del rayo a la Tierra del chasis (Earth GND).
  2. La Resistencia Serie (ej. 1 kΩ): El 1% del voltaje residual que logra pasar el diodo TVS chocará contra este "muro". La corriente se limitará a miliamperios inofensivos.
  3. El Capacitor Shunt (ej. 100 nF): Absorbe los últimos picos de alta frecuencia (Ruido y EMI) y retrasa la señal útil (Hardware Debounce), entregando una línea de 3.3V perfectamente plana al STM32.
TOPOLOGÍA DE DEFENSA ESD (PI FILTER) PARA TECLADO MUNDO FÍSICO 15,000 V Estática Tecla '5' BARRERA DE PROTECCIÓN (PCB) TVS Avalancha a 5V R_Serie: 1 kΩ 3.3V 10 kΩ 100 nF Señal Limpia (0V a 3.3V) STM32 MCU GPIO_IN Botón Libre: 3.3V Botón Presionado: 0V

⚙️ Ejercicios Prácticos

El Diseño de la Placa (PCB): El lugar físico donde sueldas el diodo TVS lo es todo. Si pones el diodo junto al chip STM32, el arco de 15kV viajará por 10 centímetros de pista de cobre emitiendo radiación electromagnética (Crosstalk) a todas las pistas vecinas antes de morir. El Diodo TVS debe soldarse a menos de 5 milímetros del conector donde se enchufa el cable del teclado. La energía debe drenarse a tierra antes de que entre al laberinto de tu placa.

Ejercicio 1: Software Debounce (Antirrebote). Aunque tu capacitor de 100nF filtra el ruido de alta frecuencia (picos de nanosegundos), la lámina de acero del botón mecánico seguirá "rebotando" durante unos 10 milisegundos generando oscilaciones. Desarrollaremos un algoritmo MISRA-C Compliant basado en una Máquina de Estados Temporizada, prohibiendo el uso de `osDelay` (que detendría la tarea) y usando variables de estado.


/**
 * @file teclado_industrial.c
 * @brief Escaneo de Teclado con Antirrebote Finito (MISRA-C)
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"
#include <stdint.h>
#include <stdbool.h>

// =========================================================================
// DEFINICIONES DE HARDWARE Y TIMINGS
// =========================================================================
// Definimos el pin conectado al filtro Pi del Teclado
#define TECLADO_PORT            GPIOA
#define TECLADO_PIN_NUM5        GPIO_PIN_4

// Tiempo oficial de estabilización mecánica de la lámina de acero (20 milisegundos)
#define DEBOUNCE_TIEMPO_MS      (20U)

// =========================================================================
// MÁQUINA DE ESTADOS DEL BOTÓN (Reglas 10.4)
// =========================================================================
typedef enum {
    BTN_ESTADO_REPOSO     = 0U,
    BTN_ESTADO_EVALUANDO  = 1U,
    BTN_ESTADO_PRESIONADO = 2U,
    BTN_ESTADO_SOLTANDO   = 3U
} EstadoBoton_t;

static EstadoBoton_t estado_tecla_5 = BTN_ESTADO_REPOSO;
static uint32_t t_inicio_debounce = 0U;

// =========================================================================
// RUTINA DE ESCANEO NO BLOQUEANTE
// =========================================================================
/**
 * @brief  Monitorea el botón sin usar retardos bloqueantes, permitiendo
 *         que la tarea escanee una matriz de 16 teclas a máxima velocidad.
 * @retval bool: TRUE solo en el flanco de bajada validado (Un solo evento por pulsación)
 */
bool Escanear_Tecla_5(void) {
    bool evento_registrado = false;
    
    // Lectura del GPIO (Activo en BAJO por la resistencia Pull-Up)
    // 0 = Presionado, 1 = Libre
    GPIO_PinState lectura_fisica = HAL_GPIO_ReadPin(TECLADO_PORT, TECLADO_PIN_NUM5);
    uint32_t tiempo_actual = osKernelGetTickCount();

    switch (estado_tecla_5) {
        
        case BTN_ESTADO_REPOSO:
            if (lectura_fisica == GPIO_PIN_RESET) {
                // Posible pulsación. Iniciamos el cronómetro de evaluación.
                t_inicio_debounce = tiempo_actual;
                estado_tecla_5 = BTN_ESTADO_EVALUANDO;
            }
            break;
            
        case BTN_ESTADO_EVALUANDO:
            if (lectura_fisica == GPIO_PIN_SET) {
                // Era ruido o un rebote que regresó a 3.3V. Falsa alarma.
                estado_tecla_5 = BTN_ESTADO_REPOSO;
            } 
            else {
                // El pin sigue en 0V. ¿Ya pasaron 20ms?
                if ((tiempo_actual - t_inicio_debounce) >= DEBOUNCE_TIEMPO_MS) {
                    // ¡Confirmado! El usuario realmente presionó y sostuvo la tecla.
                    estado_tecla_5 = BTN_ESTADO_PRESIONADO;
                    evento_registrado = true; // Emitimos el evento 1 sola vez
                }
            }
            break;
            
        case BTN_ESTADO_PRESIONADO:
            // Esperamos pacientemente a que el usuario suelte el dedo
            if (lectura_fisica == GPIO_PIN_SET) {
                t_inicio_debounce = tiempo_actual; // Iniciamos cronómetro para soltar
                estado_tecla_5 = BTN_ESTADO_SOLTANDO;
            }
            break;
            
        case BTN_ESTADO_SOLTANDO:
            // Verificamos que el botón realmente regresó y se estabilizó en 3.3V
            if (lectura_fisica == GPIO_PIN_RESET) {
                estado_tecla_5 = BTN_ESTADO_PRESIONADO; // Rebotó de regreso
            } 
            else {
                if ((tiempo_actual - t_inicio_debounce) >= DEBOUNCE_TIEMPO_MS) {
                    estado_tecla_5 = BTN_ESTADO_REPOSO; // Ciclo completado limpio
                }
            }
            break;
            
        default:
            estado_tecla_5 = BTN_ESTADO_REPOSO;
            break;
    }
    
    return evento_registrado;
}

// Tarea Superior RTOS
/*
void Task_Gestor_Interfaz(void *argument) {
    for(;;) {
        if (Escanear_Tecla_5() == true) {
            // Agregar número 5 a la pantalla LCD
        }
        osDelay(pdMS_TO_TICKS(5U)); // Polling de alta velocidad (5ms)
    }
}
*/
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Certificación IEC 61000-4-2 (Inmunidad a Descargas Electrostáticas).

Las certificaciones internacionales no se obtienen con discursos, se obtienen en laboratorios de tortura electrónica. Para vender tu Despachador de Gas LP a las grandes petroleras, el equipo será sometido a la prueba **IEC 61000-4-2**. Un ingeniero con una "Pistola ESD" se acercará a la membrana del teclado de tu máquina, y disparará arcos de 8kV por contacto directo y 15kV a través del aire. Si en el momento del disparo la pantalla parpadea, la venta se pausa o el STM32 se reinicia, la máquina reprueba y no sale al mercado.

Al implementar el **Filtro Pi (TVS + Resistor + Capacitor)** en cada una de las líneas del teclado, has encapsulado la violencia eléctrica. El Diodo TVS en configuración de avalancha absorbe el pico masivo de amperaje en picosegundos, mientras que la resistencia de 1kΩ frena el remanente de energía, impidiendo que los diodos internos de protección del pin del STM32 se quemen. Adicionalmente, tu Máquina de Estados **Antirrebote (Debounce) en Software** garantiza que si un milivoltio de ruido logra cruzar la barrera, será rechazado lógicamente por no cumplir con la "ventana de tiempo de retención" de 20 milisegundos. Has creado una interfaz humano-máquina a prueba de la furia de la naturaleza.

📝 Resumen del Día