Ayer definimos que cualquier sensor de seguridad que sea verdaderamente crítico debe ser forzosamente diseñado como Normalmente Cerrado (NC)[cite: 1]. Sin embargo, evaluar estos sensores con un simple if/else esporádico presenta un riesgo mortal conocido como Chattering o Zapateo.
Imagina que la presión de gas oscila rápidamente o el cable del botón de paro está ligeramente flojo. Si programas tu STM32 así: if(seguro) { abrir_valvula(); } else { cerrar_valvula(); }, el microcontrolador (corriendo a millones de ciclos por segundo) abrirá y cerrará la válvula mecánica cientos de veces por segundo. Esto destruirá los solenoides, generará arcos eléctricos y probablemente causará una ignición.
Un sistema de grado industrial utiliza el if/else junto con una variable de Estado Global. Una vez que el código entra al else (condición de fallo), se activa una bandera booleana que ignora futuras lecturas del sensor hasta que un operador humano realice un reinicio seguro y deliberado.
Ayer establecimos la importancia de usar en nuestro diseño PCB una resistencia Pull-Up externa muy fuerte (por ejemplo, de 4.7kΩ) conectada al pin de 3.3V, complementada con un capacitor cerámico de 100nF derivado a tierra[cite: 1]. Esto forma un filtro pasabajas (RC).
Sin embargo, el capacitor provoca que la subida/bajada de voltaje sea curva (analógica), no cuadrada. Un pin digital puro del STM32 puede malinterpretar este voltaje intermedio provocando interrupciones fantasmas. Para un Despachador Industrial, debes enrutar la señal del Paro de Emergencia a través de una compuerta inversora con Histéresis (Schmitt Trigger) como el SN74LVC1G14 antes de llegar al STM32. Esto cuadra la señal perfectamente garantizando que el if de C lea un 0 o un 1 absoluto.
Ejercicio 1: Aplica un if/else jerárquico. Usa "Early Returns" (Retornos tempranos) para evitar el temido "código espagueti" (muchos if anidados). En C puro de alto rendimiento, evalúa primero las excepciones/falsos y sal de la función inmediatamente.
#include <stdint.h>
#include <stdbool.h>
// Prototipos externos
extern void Safe_Shutdown(void);
extern bool verificar_permisivos_despacho(void);
extern bool boton_reset_presionado(void);
extern bool uart_esp32_token_valido(void);
extern void activar_solenoides_gas(void);
// Variable de estado global para enclavamiento.
// "static" la encapsula en este archivo (Seguridad de Memoria).
static bool sistema_enclavado = false;
/**
* @brief Tarea no bloqueante que administra las válvulas.
* Debe ser llamada periódicamente desde FreeRTOS.
*/
void procesar_estado_despachador(void) {
// 1. EVALUACIÓN PRIORITARIA: ¿Estamos ya en un estado de fallo?
if (sistema_enclavado == true) {
// Exigimos 2 pasos físicos y lógicos para salir del bloqueo.
// Reutilizamos la función de token de red (ESP32) requerida previamente para validación[cite: 1].
if (boton_reset_presionado() && uart_esp32_token_valido()) {
sistema_enclavado = false; // Desbloqueo Autorizado
} else {
// Mantener válvulas cerradas y abortar la evaluación actual
Safe_Shutdown();
return; // EARLY RETURN: Ahorra ciclos de reloj de la CPU
}
}
// 2. FUNCIONAMIENTO NORMAL: Uso del if/else clásico
// Si no estamos enclavados, verificamos cortocircuito lógico del Día 3
if ( !verificar_permisivos_despacho() ) {
// ¡FALLA DETECTADA DURANTE EL DESPACHO!
// Enclavar inmediatamente para evitar el Zapateo (Chattering)
sistema_enclavado = true;
Safe_Shutdown();
} else {
// Todo es seguro. El despachador puede operar.
activar_solenoides_gas();
}
}
Hito Logrado: Prevención de Chattering y Seguridad Activa.
Hoy tu código dejó de ser reactivo y pasó a tener Memoria de Estado. Si hay un corto en los cables o una despresurización, el STM32 no intentará "recuperarse" automáticamente, lo cual es inmensamente peligroso en sistemas de combustión y gas LP. Forzaste la intervención manual y remota (Token ESP32), subiendo el estándar de tu desarrollo de un "proyecto escolar" a un equipo que cumple normativas NOM/ISO industriales.
if/else repetitivas desgasten los actuadores físicos ante señales intermitentes de fallo.return; dentro de los bloques if de falla para abortar la función, haciendo el código más rápido y fácil de leer al evitar indentaciones masivas (else { else { else { } } }).1. ¿Por qué es un riesgo de seguridad omitir el `return;` dentro del bloque `if(sistema_enclavado)` en sistemas críticos?
Respuesta: Si omites el return; o no gestionas correctamente el else, el microcontrolador continuará ejecutando líneas de código por debajo del bloque de bloqueo. Esto abre la posibilidad de que un bug lógico, una interrupción no controlada o una función posterior envíen accidentalmente una señal para reabrir las válvulas en el mismo ciclo de procesamiento, anulando totalmente el Paro de Emergencia.