DÍA 300 DE 365

Fase 5: Diseño Industrial y Hardware

📖 Teoría a Estudiar

El Coeficiente de Dilatación y la Tabla API 54

El Gas Licuado de Petróleo (mezcla de propano y butano) tiene un coeficiente de dilatación térmica altísimo. En la industria, no podemos vender litros "calientes" y litros "fríos" a diferentes precios. La ley exige que se cobre el volumen equivalente que ese gas ocuparía exactamente a 20°C (Temperatura Base para México/LATAM), independientemente de la temperatura física actual en la tubería.

Para lograrlo, el Instituto Americano del Petróleo (API) creó la Tabla 54. Es una inmensa base de datos que dicta el VCF (Volume Correction Factor). La ecuación rectora de nuestra metrología será:

$$ V_{20} = V_{real} \times \text{VCF}(T_{real}, \text{Densidad}) $$

Si el GLP está a 30°C (más caliente y dilatado), el VCF será algo como 0.975, "encogiendo" el volumen cobrado de forma justa. Si el gas está a 5°C, el VCF será 1.035, "expandiendo" el volumen cobrado. Para conocer la temperatura con una precisión de $\pm 0.1^\circ\text{C}$, los semiconductores integrados y los termopares son inútiles; necesitamos un Termómetro de Resistencia de Platino (RTD PT100).

ARQUITECTURA DE ADQUISICIÓN TÉRMICA (PT100 4-WIRES) Flujo GLP Líquido PT100 (Clase A) Termopozo aísla el sensor del fluido a alta presión Fuerza (+) Sensado (-) MAX31865 15-Bit ADC (RTD to SPI) 400.0 Ω R_REF (0.1%) SCK MISO MOSI CS STM32 MCU COMPENSACIÓN VCF Vol = (P / K) * VCF LUT 1D (No Floats!) T = 24.5 °C

⚙️ Pasos Prácticos: Integración de Hardware Térmico

Paso 1: Instalación del Termopozo.
Jamás insertes el sensor metálico desnudo directamente en el gas a 15 Bar. Se suelda un Termopozo (Thermowell) de acero inoxidable en la tubería principal. Este es un tubo hueco cerrado en un extremo que invade la corriente de gas. Deslizas tu sensor PT100 dentro del termopozo; así, puedes reemplazar el sensor si se daña sin tener que despresurizar toda la planta gasera.

Paso 2: Conexión Kelvin (4 Hilos).
El PT100 es una resistencia que vale $100.0\Omega$ a 0°C y cambia $\sim0.385\Omega$ por cada grado. ¡La variación es diminuta! Si usas un cable largo de dos hilos, la resistencia del propio cable alterará la lectura. Exigimos conexión de 4 hilos: dos hilos inyectan corriente (Fuerza) y otros dos hilos, sin llevar corriente, simplemente miden el voltaje en la punta del sensor (Sensado), eliminando matemáticamente la caída de tensión del cable.

Paso 3: Conversión SPI con el MAX31865.
El ADC de 12 bits nativo del STM32 es muy ruidoso para leer un PT100. Usamos un IC dedicado como el MAX31865, que posee un ADC delta-sigma de 15 bits optimizado para RTDs. Este chip se interconecta al STM32 mediante un bus SPI de alta velocidad inmune al ruido de la gasolinera.

💻 Firmware: Aritmética Cero-Flotante (Fixed-Point LUT)

Una librería estándar calcularía el volumen corregido utilizando una docena de multiplicaciones float con exponentes para resolver el polinomio de la API 54. Eso saturaría nuestro procesador ARM Cortex-M4 (que carece de hardware FPU doble). Un ingeniero Senior resuelve esto exportando la Tabla API a un arreglo de constantes en C (Lookup Table - LUT) e indexándola mediante escalado entero.


/**
 * @file api54_compensation.c
 * @brief Algoritmo de Compensación Volumétrica API 54 usando Punto Fijo
 */

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

// =========================================================================
// LOOKUP TABLE (LUT) - API TABLE 54 (GLP Estándar Densidad ~0.540)
// =========================================================================
// Representamos el VCF escalado por 10,000 para evitar decimales.
// Ejemplo: VCF 1.0152 se guarda como 10152. VCF 0.9850 se guarda como 9850.
// Índice: Temperatura desde 0.0 °C hasta 40.0 °C, en pasos de 1.0 °C.
// En un producto real, la tabla se almacena en memoria Flash (const).

static const uint16_t VCF_LUT_API54[41] = {
    10565, 10540, 10515, 10490, 10464, // 0  a 4  °C (Gas Frío, VCF > 1)
    10438, 10411, 10385, 10358, 10330, // 5  a 9  °C
    10303, 10275, 10248, 10220, 10192, // 10 a 14 °C
    10164, 10135, 10107, 10078, 10049, // 15 a 19 °C
    10000, 9970,  9941,  9911,  9881,  // 20 a 24 °C (20°C es Base = 1.0000)
    9850,  9819,  9788,  9757,  9726,  // 25 a 29 °C (Gas Caliente, VCF < 1)
    9694,  9662,  9630,  9597,  9564,  // 30 a 34 °C
    9531,  9497,  9463,  9428,  9393,  // 35 a 39 °C
    9358                             // 40 °C
};

// =========================================================================
// OBTENCIÓN DEL VCF (Interpolación Básica en Enteros)
// =========================================================================
/**
 * @brief Obtiene el Factor de Corrección Volumétrica escalado.
 * @param temp_deciC: Temperatura del PT100 en décimas de grado (Ej: 245 = 24.5°C)
 * @retval uint32_t: VCF escalado x 10,000.
 */
uint32_t Get_API54_VCF(int16_t temp_deciC) {
    // Si la temperatura sale de los límites de diseño (0 - 40°C), acotamos.
    if (temp_deciC < 0) temp_deciC = 0;
    if (temp_deciC > 400) temp_deciC = 400; // 40.0 °C

    // Índice directo en la tabla (Descartamos la fracción decimal momentáneamente)
    uint16_t index = temp_deciC / 10;
    
    // Obtenemos el VCF base
    uint32_t vcf_base = VCF_LUT_API54[index];
    
    // NOTA: Para metrología legal fina, aquí se agregaría una interpolación
    // lineal con el resto (temp_deciC % 10) usando solo sumas y multiplicaciones enteras.
    // Para simplificar este módulo de Bring-Up, devolvemos el VCF del grado entero.
    
    return vcf_base;
}

// =========================================================================
// METROLOGÍA CENTRAL (Cero uso de floats, protección contra Overflow)
// =========================================================================
/**
 * @brief Aplica la corrección térmica al volumen crudo despachado.
 * @param raw_volume_mL: Volumen en mililitros calculados por la turbina (Ayer Día 299).
 * @param current_temp_deciC: Temperatura actual en décimas de grado.
 * @retval uint32_t: Volumen Corregido a 20°C en mililitros.
 */
uint32_t Calculate_Compensated_Volume(uint32_t raw_volume_mL, int16_t current_temp_deciC) {
    
    // 1. Obtener el Factor (Ej: 9850 para 25.0°C)
    uint32_t vcf_scaled = Get_API54_VCF(current_temp_deciC);
    
    // 2. Multiplicar. 
    // PELIGRO: Si despachamos 50,000 mL (50 Litros) * 10,500 VCF = 525,000,000.
    // Un uint32_t aguanta hasta 4,294,967,295. Estamos seguros para despachos 
    // de hasta 400 Litros. Para auto-tanques mayores, forzamos uint64_t preventivo.
    
    uint64_t corrected_vol_64 = ((uint64_t)raw_volume_mL * vcf_scaled) / 10000ULL;
    
    return (uint32_t)corrected_vol_64;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Certificación Metrológica API/OIML e Ingeniería Cero-Flotante.

La tecnología es inútil si la matemática está desconectada de la física. Imagina que diseñas el hardware perfecto, pero ignoras la dilatación térmica. Al llegar mayo en Monterrey (40°C), un tanque estacionario de 100 Litros pedirá llenado. El gas estará caliente y expandido; tu turbina contará 100 litros físicos, pero la masa energética equivalente a 20°C será de apenas 93 litros. El cliente reclamará que la estufa le duró menos tiempo de lo prometido, y PROFECO clausurará el equipo.

Al fusionar la medición SPI de 15 bits del **MAX31865 + PT100 (4-Hilos)** con la arquitectura de compensación en firmware, has erradicado el margen de error físico. Pero lo magistral reside en la eficiencia del software. Al incrustar la **Tabla API 54 como un arreglo unidimensional constante (LUT)** e indexarlo con una función transitoria basada puramente en el tipo `uint64_t`, libraste al microcontrolador de la agonía de procesar divisiones de coma flotante por software. El código se ejecuta de forma determinista en apenas unos pocos ciclos de reloj, asegurando que el cálculo volumétrico compensado mantenga el ritmo furioso de los pulsos del caudalímetro sin ahogar el futuro Scheduler del RTOS. Tu Despachador de Gas LP ha alcanzado la madurez industrial total.

📝 Resumen del Día