DÍA 194 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

Temporizadores de Hardware vs. Software

Un Temporizador de Hardware (Hardware Timer) es silicio puro. Existe físicamente dentro del chip STM32 (como TIM2 o TIM3). Cuenta pulsos eléctricos sin importar qué haga la CPU. Son valiosos y escasos; debes guardarlos para generar señales PWM para motores o para leer encoders de alta velocidad.

Un Temporizador de Software (Software Timer) es una estructura lógica en RAM administrada por FreeRTOS. El Kernel usa el Tick del sistema (1 ms) para actualizar internamente cientos de variables. Cuando la variable de tu timer llega a cero, el RTOS dispara automáticamente una función llamada Callback.

Tipos de Timers (CMSIS-OS v2)

La Regla de Oro del Callback (Daemon Task)

Cuando el timer expira, la función Callback NO se ejecuta en tu hilo. Se ejecuta dentro del hilo privado del RTOS llamado Timer Service Task (o Daemon Task). Por ley marcial: Jamás debes usar funciones bloqueantes (como osDelay, while() infinitos, o esperar Mutexes) dentro de un Callback de Timer. Si lo haces, bloquearás el reloj maestro de todos los timers del sistema.

LÓGICA DEL TEMPORIZADOR DE INACTIVIDAD (WATCHDOG LÓGICO) TIEMPO → Venta Inicia osTimerStart(60s) Contando (15s...) Caudal Detectado osTimerStart(60s) ¡TIMER RESET! Nadie hace nada por 60 segundos... TIMER CALLBACK! Inyecta Mensaje a Cola: CMD_CANCELAR_VENTA Contexto de Ejecución Esta función corre en el RTOS Daemon. No bloquea a las tareas principales.

⚙️ Ejercicios Prácticos

Ejercicio 1: Implementaremos un Timer osTimerOnce. Cuando la Tarea WiFi ordene iniciar una venta, arrancaremos el timer a 60 segundos. Si el hardware de metrología detecta gas, "patearemos el perro" (reiniciaremos el timer a 60s). Si el cliente se va a tomar un café y pasan los 60 segundos exactos sin flujo, el Callback del timer insertará un comando de emergencia en la Cola de Mensajes (Día 192) para que la Válvula se cierre y la bomba se apague automáticamente.


/**
 * @file timer_inactividad.c
 * @brief Software Timer en CMSIS-OS v2 para apagado seguro de bomba
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"

// ID Global del Timer y de la Cola de Mensajes (Día 192)
osTimerId_t timer_inactividad_id;
extern osMessageQueueId_t cola_comandos_id; 

// =======================================================
// 1. EL CALLBACK DEL TEMPORIZADOR
// =======================================================
// ¡PELIGRO! Esta función corre en el contexto oculto de FreeRTOS.
// Regla: Rápida, sin retardos, y delega el trabajo pesado a otras tareas.
void Callback_Timer_Inactividad(void *argument) {
    
    // El usuario dejó la máquina encendida pero no está sirviendo gas.
    // Creamos el mensaje de apagado
    MensajeVenta_t mensaje_apagar;
    mensaje_apagar.comando = CMD_CERRAR_EMERGENCIA;
    mensaje_apagar.parametro = 0.0f;
    
    // Lo enviamos a la Cola de la Metrología (Timeout 0, no podemos bloquearnos aquí)
    osMessageQueuePut(cola_comandos_id, &mensaje_apagar, 0, 0);
    
    // Opcional: Apagar la bomba electromecánicamente por hardware directo
    HAL_GPIO_WritePin(GPIOA, PIN_BOMBA_RELE, GPIO_PIN_RESET);
}

// =======================================================
// 2. TAREA: METROLOGÍA (El proceso de carga)
// =======================================================
void Thread_Metrologia(void *argument) {
    
    MensajeVenta_t msg_rx;
    
    for (;;) {
        // Leemos la cola (Puede despertar por WiFi o por el Callback del Timer)
        if (osMessageQueueGet(cola_comandos_id, &msg_rx, NULL, 10) == osOK) {
            
            if (msg_rx.comando == CMD_INICIAR_VENTA) {
                Valvula_SetApertura(100.0f);
                // Arrancamos el contador regresivo de 60,000 milisegundos (60 seg)
                osTimerStart(timer_inactividad_id, 60000U);
            }
            
            else if (msg_rx.comando == CMD_CERRAR_EMERGENCIA) {
                // ¡Cerramos todo por inactividad!
                Valvula_SetApertura(0.0f);
                // Detenemos el timer por si acaso
                osTimerStop(timer_inactividad_id);
            }
        }
        
        // Simulación: Si hay flujo constante de gas...
        if (Caudalimetro_Hay_Flujo_Actual()) {
            // El usuario está activo, "Pateamos el perro" (Watchdog lógico).
            // Volver a llamar a osTimerStart reinicia la cuenta a 60 segundos.
            osTimerStart(timer_inactividad_id, 60000U);
        }
    }
}

// =======================================================
// INICIALIZACIÓN
// =======================================================
int main(void) {
    SystemClock_Config();
    osKernelInitialize();
    
    // CREAR EL TEMPORIZADOR DE SOFTWARE
    // Parámetro 1: Función a ejecutar cuando expire
    // Parámetro 2: Modo (osTimerOnce = Se detiene tras 1 disparo / osTimerPeriodic = Infinito)
    // Parámetro 3: Argumentos extra (NULL)
    // Parámetro 4: Atributos (NULL)
    timer_inactividad_id = osTimerNew(Callback_Timer_Inactividad, osTimerOnce, NULL, NULL);
    
    if (timer_inactividad_id == NULL) {
        Error_Handler(); // Falta de RAM en el Heap de FreeRTOS
    }
    
    // ... Creación de Tareas y Cola ...
    osKernelStart();
    while (1);
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Seguridad Operacional y Lógica de "Deadman Switch" (Hombre Muerto).

En la industria de los hidrocarburos (Gas LP), la automatización puede ser mortal si no se consideran los errores humanos. Es común que un operador "autorice" una carga desde la caja registradora, pero el despachador en el patio se olvide de conectar la manguera y se vaya a cobrarle a otro cliente. La bomba centrífuga del gas queda encendida; el gas se agita, se calienta, su volumen se expande y la presión en la tubería se eleva a niveles críticos, forzando a las válvulas de alivio mecánicas a expulsar gas flamable a la atmósfera para no estallar.

Al programar un **Software Timer de Inactividad (60 segundos)**, has implementado un mecanismo de seguridad industrial de Nivel 2. No requirió soldar un solo chip 555 ni configurar periféricos escasos. Has usado la abstracción del RTOS para que la máquina vigile al humano. Si la máquina otorga presión, pero el caudalímetro no registra movimiento en 1 minuto, el Timer ejecuta su Callback silencioso, envía la orden a la Cola de la Metrología, apaga el relé de la bomba y cancela la transacción comercial en la pantalla. Has salvado dinero, desgaste mecánico, y posiblemente vidas.

📝 Resumen del Día