DÍA 152 DE 365

Fase 3: Comunicaciones y Redes Industriales

📖 Teoría a Estudiar

El Comportamiento No Lineal de la Válvula

El PID puro asume que el universo es perfecto y lineal: Si pides 0% de PWM, hay 0 litros. Si pides 50%, hay la mitad del flujo máximo. En la realidad, las electroválvulas proporcionales tienen una curva de respuesta sigmoidal (forma de 'S'):

Transformación Lineal Computacional

Para no confundir al algoritmo PID, dejamos que calcule su salida del `0.0%` al `100.0%` como si viviera en un mundo ideal. Justo antes de enviar esa salida al hardware (Timer PWM), pasamos el número por una **Función de Mapeo**. Si el PID pide un modesto `1.0%` de apertura, el mapeo lo transforma en un `30.5%` de PWM físico, dándole el empujón exacto para vencer el resorte sin abrir de golpe la válvula.

CURVA DE RESPUESTA ELECTROMECÁNICA Y MAPEO DE ACTUADOR Flujo (LPM) Fuerza (PWM %) Ideal (Mente del PID) 30% 85% Deadband Rango Útil Saturación Software Mapping (C Code) PID_Out 0.0 - 100.0 Compensador Map(val, 0, 100, 30.0, 85.0) Hardware PWM 30.0 - 85.0 % PID pide 1.0% -> Mapeo -> PWM al 30.5% (Vence el resorte sin abrir de golpe)

⚙️ Ejercicios Prácticos

Ejercicio 1: Tomaremos el algoritmo PID continuo del Día 151 y crearemos el envoltorio físico mapear_actuador_pwm(). Incorporaremos una constante de cierre de emergencia: Si el PID arroja 0.0 exacto o la venta terminó, ignoramos la zona muerta y apagamos el PWM al 0.0% absoluto para bloquear el paso de gas por completo.


/**
 * @file control_valvula_pid.c
 * @brief Implementación Física del PID con Compensación de Zona Muerta (Deadband)
 */

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

// =========================================================================
// PARÁMETROS FÍSICOS DE LA VÁLVULA (Calibración Mecánica)
// =========================================================================
#define VALVE_DEADBAND_MIN  30.0f  // % de PWM necesario para vencer el resorte
#define VALVE_SATURATION    85.0f  // % de PWM donde el flujo ya es máximo físico

// Dependencias de nuestro sistema (Día 151)
extern float PID_Update(float setpoint, float medicion, float dt); // Función PID abstracta
extern void set_apertura_pwm_hardware(float porcentaje);           // Control del Timer (Día 150/152)
extern float leer_sensor_litros(void);

/**
 * @brief Mapea la salida abstracta del PID (0-100%) al rango efectivo de la válvula (30-85%)
 *        Implementa la función lineal matemática clásica de interpolación.
 * 
 * @param pid_out Salida ideal del PID
 * @return float Porcentaje de PWM compensado para inyectar al hardware
 */
float compensar_zona_muerta_valvula(float pid_out) {
    
    // 1. CIERRE SEGURO (Shut-off)
    // Si la matemática pide cerrar, cerramos por completo (0V absoluto)
    if (pid_out <= 0.01f) {
        return 0.0f;
    }
    
    // 2. SATURACIÓN MATEMÁTICA
    // Si el PID pide más del 100%, limitarlo
    if (pid_out > 100.0f) pid_out = 100.0f;
    
    // 3. MAPEO LINEAL (Y = mX + b)
    // Rango Entrada: 0.0 a 100.0
    // Rango Salida : 30.0 a 85.0
    
    float rango_entrada = 100.0f - 0.0f;
    float rango_salida  = VALVE_SATURATION - VALVE_DEADBAND_MIN;
    
    // Y = ( (X - X_min) * (Y_max - Y_min) / (X_max - X_min) ) + Y_min
    float pwm_compensado = ((pid_out / rango_entrada) * rango_salida) + VALVE_DEADBAND_MIN;
    
    return pwm_compensado;
}

/**
 * @brief Ejecutor principal del Bucle de Control. 
 *        Aísla la lógica de negocio de la física de la planta.
 */
void despachar_gas_controlado(float meta_litros) {
    
    float litros_actuales = leer_sensor_litros();
    
    // Calcular el PID Ideal (Matemática pura 0-100)
    // Nota: El 'dt' (delta time) asume 0.01 segundos si esto se llama cada 10ms
    float pid_ideal = PID_Update(meta_litros, litros_actuales, 0.01f);
    
    // Transformar a Física Real (Compensar el resorte electromecánico)
    float pwm_real = compensar_zona_muerta_valvula(pid_ideal);
    
    // Inyectar al Timer Hardware
    set_apertura_pwm_hardware(pwm_real);
}

int main(void) {
    
    // inicializar_sistema();
    
    float venta_objetivo = 20.0f; // Litros
    bool venta_activa = true;
    
    while(1) {
        
        // El marcapasos de nuestro PID (Sincronizado por SysTick)
        if (bandera_timer_10ms && venta_activa) {
            
            despachar_gas_controlado(venta_objetivo);
            
            // Condición de paro estricto (Metrología completada)
            float litros = leer_sensor_litros();
            if (litros >= venta_objetivo) {
                
                venta_activa = false;
                
                // Forzar cierre eléctrico cortando el hardware directamente
                set_apertura_pwm_hardware(0.0f); 
                
                // guardar_venta_en_eeprom();
            }
            
            bandera_timer_10ms = false;
        }
    }
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Control Fino y Cierre de Válvula Exacto (Smart Valve).

Si conectaras la ecuación PID pura directamente al Timer del PWM, ocurriría un desastre mecánico en los litros finales de la venta. El PID intentaría suavizar la entrega reduciendo su salida al `10%` o `5%`. Pero como tu válvula de gas requiere al menos un `30%` de fuerza PWM solo para vencer el resorte (Deadband), la válvula se cerraría físicamente por completo *antes* de tiempo. El gas dejaría de fluir cuando el marcador llevara 19.80 Litros.

El término Integral (I) del PID notaría que el flujo se detuvo, y empezaría a acumular error desesperadamente. Segundos después, la integral obligaría a la salida a saltar de golpe al `35%`, la válvula se abriría violentamente, y te pasarías a 20.15 Litros. Con este **Mapeo Lineal de Software**, tu algoritmo se vuelve consciente de la inercia del hierro y los resortes de la válvula. Cuando el PID pide un "susurro" de `1%` de gas, el STM32 inyecta inteligentemente un `30.5%` de PWM. La válvula se sostiene microscópicamente abierta, entregando el gas gota a gota, garantizando que el ticket de venta cierre en 20.00 Litros perfectos.

📝 Resumen del Día