DÍA 239 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

El Estado de Reposo (IDLE State)

En nuestra Arquitectura de Software, el sistema pasa el 95% de su vida útil en el estado ESTADO_REPOSO. Durante esta fase, las válvulas solenoides están sin energía (Normalmente Cerradas) bloqueando el flujo a más de 120 PSI de presión. El microcontrolador solo debe estar vigilando la pantalla o esperando que el usuario descuelgue la pistola para iniciar una venta.

El Golpe de Ariete (Water Hammer)

¿Qué pasa si programamos que "Cualquier pulso en Reposo = Alarma de Fuga"? Tendremos cientos de alarmas falsas. En hidráulica, cuando la válvula se cierra bruscamente al terminar un despacho de gas, la inercia cinética del líquido choca contra la pared de la válvula cerrada y rebota hacia atrás. Esta onda de choque hace que la turbina del caudalímetro gire levemente hacia atrás y hacia adelante generando 1 o 2 pulsos residuales.

Para evitar pánico innecesario, la máquina debe tolerar un Umbral de Ruido Hidráulico (ej. 3 pulsos). Solo si el contador de pulsos en reposo supera ese umbral, el sistema decreta una Alarma Nivel 1: Fuga Detectada.

SIL-3: Acción de Mitigación Incondicional

Cuando la fuga es confirmada, el firmware no puede simplemente mostrar un mensaje y seguir funcionando. Las reglas de diseño seguro exigen un secuestro total de la Máquina de Estados (Lockdown):

  1. Transicionar incondicionalmente a ESTADO_BLOQUEO_EMERGENCIA.
  2. Activar el relevador de la Válvula de Corte General (Válvula de Bola Motorizada de Emergencia), la cual está antes del medidor.
  3. Inyectar un mensaje MQTT de prioridad máxima hacia AWS y no permitir nuevos despachos hasta que un técnico haga un reset por hardware o llave física.
LÓGICA DE DETECCIÓN: ANOMALÍA EN ESTADO DE REPOSO Tubería Física Válvula (CERRADA) Caudalímetro Fuga Pulso (EXTI) ESTADO_REPOSO Esperando cliente... pulsos_reposo = 0 Pulso recibido > UMBRAL ? (Ej. 3 pulsos) NO (Ruido) SÍ (FUGA!) ESTADO_EMERGENCIA Cerrar Válvula General Enviar MQTT IoT Alert

⚙️ Ejercicios Prácticos

Circuito Electrónico de Redundancia: La Norma Oficial Mexicana exige que un Despachador de Gas LP tenga al menos dos válvulas en serie. Una es la válvula solenoide de trabajo (rápida, operada cada despacho). La otra es la válvula de corte general (lenta, generalmente de bola motorizada), la cual solo se usa en emergencias y cuando la máquina se apaga por las noches. Nuestra alarma activará el relé de esta segunda válvula.

Ejercicio 1: Integraremos la lógica de detección de fugas dentro de la Tarea de Metrología. Utilizaremos el estándar MISRA-C asegurándonos de que los estados del sistema estén estrictamente definidos mediante un `enum` y que las variables sean tipadas.


/**
 * @file fsm_fugas.c
 * @brief Lógica de Detección Falsa de Fluido y Bloqueo de Emergencia (MISRA-C)
 */

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

// =========================================================================
// DEFINICIONES DEL SISTEMA
// =========================================================================
// Umbral de ruido para ignorar el "Golpe de Ariete" al cerrar la válvula
#define UMBRAL_RUIDO_HIDRAULICO     (3U)

typedef enum {
    ESTADO_REPOSO         = 0U,
    ESTADO_DESPACHANDO    = 1U,
    ESTADO_EMERGENCIA     = 2U
} FSM_Estado_t;

// Variable global de estado compartida (Protegida)
static FSM_Estado_t estado_maquina_actual = ESTADO_REPOSO;

// Pulsos interceptados por la ISR
extern volatile uint32_t isr_pulsos_acumulados;

// =========================================================================
// ACCIONES DE MITIGACIÓN (HARDWARE)
// =========================================================================
/**
 * @brief Ejecuta el protocolo SIL de cierre total.
 */
static void Activar_Protocolo_Lockdown(void) {
    // 1. Asegurar que la válvula solenoide primaria esté apagada
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); 
    
    // 2. Activar el Relé de la Válvula Motorizada de Corte General (Redundancia)
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); 
    
    // 3. Encender Zumbador (Buzzer)
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); 
    
    // 4. Delegar notificación IoT a la Tarea UART/ESP32
    // Enviar_Alarma_Nube(ALERTA_FUGA_DETECTADA);
}

// =========================================================================
// MÁQUINA DE ESTADOS (TAREA PRINCIPAL)
// =========================================================================
void Task_Control_Valvulas(void *argument) {
    
    uint32_t pulsos_locales_previos = 0U;
    uint32_t pulsos_en_reposo = 0U;
    
    for(;;) {
        // Lectura Atómica (Evitar Data Race)
        taskENTER_CRITICAL();
        uint32_t snapshot_pulsos = isr_pulsos_acumulados;
        taskEXIT_CRITICAL();
        
        // Calcular si hubo incremento desde el último ciclo
        uint32_t incremento = snapshot_pulsos - pulsos_locales_previos;
        pulsos_locales_previos = snapshot_pulsos;

        // FSM Lógica
        switch (estado_maquina_actual) {
            
            case ESTADO_REPOSO:
                if (incremento > 0U) {
                    pulsos_en_reposo += incremento;
                    
                    // ¿Superó el umbral del Golpe de Ariete?
                    if (pulsos_en_reposo >= UMBRAL_RUIDO_HIDRAULICO) {
                        // ¡PELIGRO! FLUJO FANTASMA DETECTADO
                        estado_maquina_actual = ESTADO_EMERGENCIA;
                    }
                }
                break;
                
            case ESTADO_DESPACHANDO:
                // En despacho es normal que haya pulsos. 
                // La variable pulsos_en_reposo debe estar reseteada a 0.
                pulsos_en_reposo = 0U;
                break;
                
            case ESTADO_EMERGENCIA:
                // Estado Latch-up (Atrapado). La máquina no puede salir de aquí
                // a menos que un técnico gire una llave física de Mantenimiento.
                Activar_Protocolo_Lockdown();
                break;
                
            default:
                // MISRA-C Regla 16.4: Transición segura por corrupción de RAM
                estado_maquina_actual = ESTADO_EMERGENCIA;
                break;
        }
        
        osDelay(pdMS_TO_TICKS(100U)); // Monitorear cada 100ms
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Diagnóstico Predictivo y Redundancia Mecánica por Software.

Un ingeniero mecánico sabe que todos los sellos de goma del mundo eventualmente se degradarán (especialmente bajo la presión de 150 PSI del Gas LP líquido). Si la solenoide principal sufre desgaste microscópico, empezará a "gotear" gas hacia la manguera cuando la máquina no esté operando. Si el despachador de la noche deja la pistola en el suelo, ese gas se fugará silenciosamente a la atmósfera creando una nube explosiva.

Al diseñar la lógica de **Alerta de Fuga en Reposo**, has creado una capa de diagnóstico predictivo. El STM32 actúa como un auditor del hardware físico. Si la orden lógica es `CERRADO`, pero la física dice `FLUJO`, el software asume que el hardware primario ha fallado e invoca al hardware secundario (la válvula de corte general motorizada). Esta redundancia cruzada (Software monitoreando al Hardware A para activar el Hardware B) es la base de las certificaciones SIL-3 (Safety Integrity Level) que las grandes petroquímicas (PEMEX, Repsol) exigen antes de comprar e instalar cualquier equipo electrónico en sus despachadoras.

📝 Resumen del Día