En el comercio internacional de hidrocarburos, el volumen se vende compensado a una Temperatura Base de Referencia. En México y gran parte del mundo, esa norma está estandarizada a 20.0 °C (o 15°C en la normativa ISO). Si el gas está más caliente que 20°C, se expande; por lo tanto, debemos restarle volumen al contador. Si el gas está muy frío, se condensa, y debemos añadirle volumen al contador para ser equitativos.
Las computadoras de flujo profesionales aplican la norma "API Table 54". Para no saturar el procesador con tablas pesadas, la industria acepta una aproximación lineal de altísima precisión usando el Coeficiente de Expansión Térmica ($\alpha$). Para una mezcla comercial estándar de Gas LP (Propano 60% / Butano 40%), el coeficiente aproximado es de $0.003$ por cada grado Celsius de diferencia.
La fórmula universal en punto flotante sería:
$$ V_{real} = V_{medido} \times [1 - \alpha (T_{actual} - T_{ref})] $$
Pero como establecimos en el Día 106, en Bare-Metal está prohibido usar Floats. Multiplicaremos todo por 100,000 para trabajar exclusivamente con enteros en el núcleo de la ALU del ARM Cortex-M.
Ejercicio 1: Integra la lectura de temperatura obtenida por el ADC en el Día 114 y construye el algoritmo metrológico compensar_volumen_gas(). La variable de temperatura de entrada vendrá multiplicada por 10 para simular un decimal (Ej. 255 significa 25.5°C). Usa enteros de 64 bits (uint64_t) de forma temporal durante la multiplicación cruzada para evitar que la memoria RAM colapse por desbordamiento.
/**
* @file api_metrology.c
* @brief Algoritmo de Compensación Dinámica Termo-Volumétrica (Bare-Metal)
*/
#include <stdint.h>
// --- CONSTANTES METROLÓGICAS (PUNTO FIJO) ---
// Norma oficial: 20.0 °C. Escalado x10 = 200.
#define TEMP_REFERENCIA_X10 200
// Coeficiente Alfa del Gas LP: ~0.00300 por cada °C
// Para evitar floats, multiplicamos por 100,000 => 300
#define COEF_EXPANSION_LP_X100K 300
// El 1 entero absoluto en nuestro sistema de punto fijo
#define MULTIPLICADOR_BASE_1 100000
/**
* @brief Calcula el Volumen Compensado (Masa real) según la norma API.
* @param volumen_crudo_ml: Litros brutos medidos por la turbina (en mililitros).
* @param temp_actual_x10: Temperatura actual del tubo leída por el ADC (x10).
* @return uint32_t Mililitros reales facturables.
*/
uint32_t compensar_volumen_gas(uint32_t volumen_crudo_ml, int32_t temp_actual_x10) {
// 1. Calcular el Delta de Temperatura (T_actual - T_ref)
// Ejemplo: Si el gas está a 35.0°C (350) bajo el sol. Delta = 150.
// Si el gas está a 5.0°C (50) en invierno. Delta = -150.
int32_t delta_t = temp_actual_x10 - TEMP_REFERENCIA_X10;
// 2. Calcular el Factor CTL (Correction for Temperature on Liquid)
// Formula original: 1.0 - (Coef * Delta_T)
// El Delta_T viene escalado x10, por eso dividimos entre 10 en la fórmula.
// Ejemplo (35°C): 100,000 - ((300 * 150) / 10) = 100,000 - 4500 = 95,500. (0.955 float)
int32_t factor_ctl = MULTIPLICADOR_BASE_1 - ((COEF_EXPANSION_LP_X100K * delta_t) / 10);
// Si el sensor falla y da un factor absurdo, protegemos el algoritmo.
if (factor_ctl < 80000 || factor_ctl > 120000) {
// En un despachador real, esto dispararía una alarma de metrología.
// Por seguridad, forzamos un factor de 1 (Sin corrección).
factor_ctl = MULTIPLICADOR_BASE_1;
}
// 3. Aplicar el factor al volumen despachado.
// Como volumen_crudo_ml puede ser 20,000 mL y factor_ctl es 95,500,
// la multiplicación da 1,910,000,000. ¡Cerca del límite de 32 bits (4.29B)!
// Por seguridad, forzamos al compilador a usar la ALU de 64 bits durante la operación.
uint64_t volumen_calculado = (uint64_t)volumen_crudo_ml * (uint64_t)factor_ctl;
// Regresamos a la escala original dividiendo entre 100,000
uint32_t volumen_facturable_ml = (uint32_t)(volumen_calculado / MULTIPLICADOR_BASE_1);
return volumen_facturable_ml;
}
// Ejemplo de integración
int main(void) {
// Estos valores vienen del EXTI1 (Día 102) y del ADC1 Modo Scan (Día 114)
uint32_t volumen_turbina = 10000; // 10.00 Litros físicos medidos
int32_t temperatura_tubo = 350; // 35.0 °C bajo el sol de la tarde
while(1) {
// ¡Magia Ciberfísica!
// El cliente cargó 10 Litros físicos. Pero como el gas estaba dilatado por el sol,
// el algoritmo compensado le cobrará exactamente 9.55 Litros.
// Equidad absoluta y cumplimiento normativo.
uint32_t venta_legal_ml = compensar_volumen_gas(volumen_turbina, temperatura_tubo);
// lcd_escribir_litros(venta_legal_ml);
}
return 0;
}
Objetivo del día: Cumplimiento Normativo (PROFECO / NOM-005-SCFI).
Este es el algoritmo que convierte un proyecto escolar en un producto comercializable. En México, la **NOM-005-SCFI** establece rigurosamente que todos los sistemas de medición y despacho de hidrocarburos deben contar con un sistema de compensación de temperatura que lleve el fluido a una base estandarizada de 20°C. Si el verificador de PROFECO llega a tu estación, inyecta líquido caliente y tu máquina no resta el volumen expandido de la pantalla LCD, serás clausurado de inmediato por fraude al consumidor.
Al procesar la compensación mediante operaciones uint64_t y Punto Fijo base 100k, el procesador ARM Cortex-M efectúa la corrección volumétrica en una fracción minúscula de milisegundo cada vez que la turbina gira, permitiendo un despacho en tiempo real fluido, legalmente exacto y completamente a prueba de excepciones de división matemática.
(uint64_t) obligando al procesador a utilizar dos registros de la ALU para la operación segura antes de dividir y regresar a 32 bits.