DÍA 052 DE 365

Fase 1: Fundamentos de C y Lógica de Software

📖 Teoría a Estudiar

Timeout de Bomba y Software Watchdog

En el diseño de software para sistemas embebidos de control, una de las peores asunciones que puedes hacer es creer que el mundo físico responderá de forma instantánea o predecible a tus comandos. Si el microcontrolador activa un relevador para encender una bomba industrial, no hay garantía de que el líquido realmente empiece a fluir. Puede haber una manguera rota, una válvula bloqueada o el tanque principal podría estar vacío.

Un Software Watchdog (Perro Guardián de Software) o lógica de Timeout, es un mecanismo no bloqueante que mide el tiempo transcurrido entre una acción y la recepción de la confirmación física. Si el tiempo supera un límite predefinido de seguridad, el sistema aborta la operación para prevenir daños catastróficos mecánicos o eléctricos.

INICIAR DESPACHO BOMBA = ON tiempo_inicio = millis() ¿HAY FLUJO? SÍ Reset Timer NO ¿TIMEOUT? > 5000 ms AÚN NO SÍ (ERROR) BOMBA = OFF ALARMA

Los 3 Pasos de la Lógica Temporal

  1. Sello de Tiempo (Timestamp): Utilizar una base de tiempos en milisegundos (usualmente generada por el SysTick Timer del Cortex-M) para guardar el momento exacto en el que ocurrió el último pulso del sensor.
  2. Comparación Delta: En cada iteración de tu Súper Bucle, restar el sello de tiempo guardado al tiempo actual para obtener el tiempo transcurrido (Delta).
  3. Actuación Segura: Si el Delta supera tu umbral máximo (ej. 5000 ms), disparas la interrupción de la máquina de estados, cortas voltajes y registras un error.

⚙️ Ejercicios Prácticos

Ejercicio 1: Programa una máquina de estados sencilla en C que simule el encendido de un motor y supervise el flujo de datos. Emplearemos una función abstracta obtener_milisegundos() para simular el reloj de hardware de tu STM32.


#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

// --- 1. CONSTANTES CRÍTICAS DE SEGURIDAD ---
#define TIMEOUT_BOMBA_MS  5000  // 5 segundos de tolerancia máxima sin flujo

// Variables globales simuladas
uint32_t ultimo_pulso_ms = 0;
bool bomba_encendida = false;
bool alarma_critica = false;

// Función abstracta que representa el SysTick del STM32 (HAL_GetTick)
extern uint32_t obtener_milisegundos(void); 
// Función abstracta que representa la lectura de hardware (GPIO o DMA)
extern uint32_t leer_pulsos_caudalimetro(void);


// --- 2. RUTINA DE WATCHDOG DE FLUJO ---
void verificar_seguridad_flujo(void) {
    
    // Si la bomba no está operando o hay un error, no hay nada que vigilar
    if (!bomba_encendida || alarma_critica) return;
    
    uint32_t tiempo_actual = obtener_milisegundos();
    uint32_t pulsos = leer_pulsos_caudalimetro();
    
    // 2A. Evaluar si recibimos confirmación de hardware
    if (pulsos > 0) {
        // Todo está bien, reseteamos el temporizador del Watchdog
        ultimo_pulso_ms = tiempo_actual;
    } 
    // 2B. Si no hay pulsos, verificar cuánto tiempo ha pasado (Delta)
    else {
        uint32_t tiempo_sin_flujo = tiempo_actual - ultimo_pulso_ms;
        
        if (tiempo_sin_flujo >= TIMEOUT_BOMBA_MS) {
            // ¡PÁNICO! Han pasado 5s con la bomba ON pero 0 pulsos leídos.
            bomba_encendida = false;  // Cortar relevador inmediatamente
            alarma_critica = true;    // Bloquear sistema
            
            // hardware_apagar_motor(); // Función subyacente física
            printf("CRITICAL ERROR: Timeout de bomba superado. Sistema abortado.\n");
        }
    }
}

// --- 3. SÚPER BUCLE ---
int main(void) {
    // Al iniciar el despacho (por ejemplo, presionar Start)
    bomba_encendida = true;
    ultimo_pulso_ms = obtener_milisegundos(); // Iniciamos el cronómetro
    
    while(1) {
        if (!alarma_critica) {
            verificar_seguridad_flujo();
            
            // ... resto del control lógico del dispensador ...
        }
        
        // Simulación de retraso del loop (No usar delays bloqueantes reales)
    }
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Prevención de Cavitación y Riesgos Mecánicos.

El manejo de gas LP licuado requiere protocolos extremadamente robustos. Si tu microcontrolador STM32 manda 3.3V al relevador que acciona la bomba trifásica, esperas que el caudalímetro másico empiece a mandar pulsos casi inmediatamente. Pero, ¿qué pasa si el tanque estacionario está vacío? La bomba girará "en seco". La fricción sin el gas actuando como refrigerante generará calor extremo, un riesgo absoluto de cavitación o explosión en un entorno de hidrocarburos.

Integrar este Watchdog de Flujo puramente lógico te garantiza que, sin añadir costosos sensores adicionales de presión negativa, tu sistema es "consciente" de su entorno. Si no hay confirmación de flujo en 5,000 milisegundos, el software desenergiza la estación y levanta una bandera de alarma en tu FreeRTOS, bloqueando la máquina y protegiendo el equipo industrial.

📝 Resumen del Día

❓ Cuestionario de Autoevaluación

1. ¿Por qué usamos `tiempo_actual - ultimo_pulso_ms` en lugar de una función tipo `delay_ms(5000)` para esperar a que llegue el gas?
Respuesta: Usar un delay() detendría por completo (bloquearía) la ejecución de la CPU. Durante esos 5 segundos el procesador no podría leer un botón de Paro de Emergencia, no actualizaría la pantalla LCD, ni revisaría otros sensores de seguridad. El enfoque de "Delta de tiempo" permite cronometrar en segundo plano, dejando que el procesador ejecute el resto del código libremente a miles de ciclos por segundo.

2. ¿Qué ocurre con la resta de `uint32_t` si el contador de milisegundos llega a su límite (aprox. 49.7 días) y se desborda (vuelve a cero)?
Respuesta: Debido a la magia de la aritmética modular sin signo en C (unsigned overflow), la resta (Nuevo - Antiguo) sigue dando el resultado exacto del intervalo siempre y cuando el intervalo real sea menor al límite máximo del contador (lo cual es cierto para un timeout de 5 segundos). Es un mecanismo intrínsecamente seguro para el rollover.