DÍA 238 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

El Dilema de la Memoria en Matrices 2D

Si la Temperatura varía de -10°C a +50°C (600 décimas), y la Densidad varía de 500 a 600 kg/m³ (1000 décimas), una tabla (Array 2D) con resolución de 0.1 en ambos ejes requeriría 600 x 1000 = 600,000 valores flotantes. Multiplicado por 4 bytes cada uno, necesitaríamos 2.4 Megabytes de memoria ROM. ¡Imposible para un STM32F401!

La solución en sistemas embebidos de grado aeroespacial es usar una Matriz Rala (Sparse Grid). Guardamos los valores de corrección térmica (VCF) solo en saltos enteros (ej. a 25°C y 26°C; a 535 kg/m³ y 540 kg/m³). Luego, si el sensor dice que estamos exactamente a 25.4°C y 538.2 kg/m³, usamos el algoritmo de Interpolación Bilineal para calcular el valor central exacto.

¿Cómo funciona la Interpolación Bilineal?

Visualiza un rectángulo donde conoces el valor numérico en las 4 esquinas. Tu valor real es un punto en medio del rectángulo.

  1. Paso 1 (Interpolación Horizontal X): Se traza una línea imaginaria entre las dos esquinas superiores y se averigua el valor central arriba. Se repite el proceso entre las dos esquinas inferiores para obtener el valor central abajo.
  2. Paso 2 (Interpolación Vertical Y): Teniendo los dos nuevos puntos centrales (arriba y abajo), se traza una línea vertical entre ellos y se calcula el punto final exacto que estamos buscando.
INTERPOLACIÓN BILINEAL DE UNA MATRIZ RALA (SPARSE GRID 2D) Densidad (X) Temperatura (Y) Q12 T=26°C, D=535 VCF=0.9810 Q22 T=26°C, D=540 VCF=0.9850 Q11 T=25°C, D=535 VCF=0.9830 Q21 T=25°C, D=540 VCF=0.9870 x1 (535) x2 (540) y1 (25°C) y2 (26°C) R2 (X) R1 (X) Punto P (Lectura Real) T= 25.4°C | D= 538.2 VCF Exacto = 0.9845 x: 538.2 y: 25.4°C

⚙️ Ejercicios Prácticos

Circuito Lógico: La Densidad no siempre requiere un sensor hiper-caro de Efecto Coriolis. En la mayoría de las estaciones de servicio, cuando el camión cisterna surte la bomba principal, el chofer le entrega al gerente una hoja con la densidad exacta de ese lote. El gerente puede digitar esa densidad manual (`538.2`) en el teclado físico o en el panel de WebSockets (Día 227) de nuestro STM32/ESP32, y la máquina la guardará en la EEPROM.

Ejercicio 1: Implementaremos la función matemática `Interpolacion_Bilineal` en C. Presta atención al control de MISRA-C: debemos comprobar la división por cero (`x2 == x1`), algo imperativo en software crítico.


/**
 * @file api_bilinear.c
 * @brief Interpolación Bilineal MISRA-C:2012 para Cálculo de VCF 2D
 */

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

typedef float float32_t;

// =========================================================================
// DEFINICIÓN DE LA CUADRÍCULA VIRTUAL (LUT 2D DE EJEMPLO)
// =========================================================================
// Eje Y = Temperatura (ej. 25 y 26 °C)
// Eje X = Densidad Base (ej. 535 y 540 kg/m3)

// En un archivo real, esta sería una matriz gigante guardada en Flash (const)
// VCF_Table[temp_index][density_index]

// =========================================================================
// ALGORITMO MATEMÁTICO PURO (MISRA-C COMPLIANT)
// =========================================================================
/**
 * @brief  Calcula la interpolación bilineal de un punto (x, y)
 * @param  x    Valor real del Eje X (Densidad leída)
 * @param  y    Valor real del Eje Y (Temperatura leída)
 * @param  x1   Punto menor en X de la cuadrícula
 * @param  x2   Punto mayor en X de la cuadrícula
 * @param  y1   Punto menor en Y de la cuadrícula
 * @param  y2   Punto mayor en Y de la cuadrícula
 * @param  q11  Valor VCF en (x1, y1)
 * @param  q21  Valor VCF en (x2, y1)
 * @param  q12  Valor VCF en (x1, y2)
 * @param  q22  Valor VCF en (x2, y2)
 * @retval float32_t Valor VCF interpolado exacto, o -1.0F si hay error matemático
 */
float32_t Calcular_Interpolacion_Bilineal(
    float32_t x, float32_t y,
    float32_t x1, float32_t x2,
    float32_t y1, float32_t y2,
    float32_t q11, float32_t q21,
    float32_t q12, float32_t q22) 
{
    // 1. MISRA-C Regla 10.4: Prevenir División por Cero.
    // Si la cuadrícula es inválida (tamaño 0), abortar cálculo para evitar HardFault.
    float32_t divisor_x = x2 - x1;
    float32_t divisor_y = y2 - y1;
    
    // Al usar floats, no comprobamos == 0.0F directo por errores de coma flotante,
    // pero en este contexto industrial los valores de cuadrícula son enteros exactos (ej. 540-535 = 5.0)
    if ((divisor_x < 0.001F) || (divisor_y < 0.001F)) {
        return -1.0F; // Error crítico: Cuadrícula mal formada
    }

    // 2. Interpolación Horizontal a lo largo de Y1 (Línea Inferior)
    // Formula: R1 = ((x2 - x) / (x2 - x1))*Q11 + ((x - x1) / (x2 - x1))*Q21
    float32_t r1 = (((x2 - x) / divisor_x) * q11) + (((x - x1) / divisor_x) * q21);

    // 3. Interpolación Horizontal a lo largo de Y2 (Línea Superior)
    float32_t r2 = (((x2 - x) / divisor_x) * q12) + (((x - x1) / divisor_x) * q22);

    // 4. Interpolación Vertical final (Entre R1 y R2)
    // Formula: P = ((y2 - y) / (y2 - y1))*R1 + ((y - y1) / (y2 - y1))*R2
    float32_t p_final = (((y2 - y) / divisor_y) * r1) + (((y - y1) / divisor_y) * r2);

    return p_final;
}

// =========================================================================
// RUTINA METROLÓGICA DEL RTOS (EJECUCIÓN)
// =========================================================================
void Task_Compensacion_Metrologica(void *argument) {
    
    // Estos valores vienen del sensor de temperatura y de la configuración EEPROM
    float32_t lectura_densidad_actual = 538.2F;
    float32_t lectura_temperatura_actual = 25.4F;
    
    // Supongamos que ya corrimos un algoritmo de búsqueda (Binary Search)
    // en nuestra matriz en ROM para encontrar las 4 esquinas que encierran a 25.4 y 538.2
    float32_t lut_x1 = 535.0F; float32_t lut_x2 = 540.0F;
    float32_t lut_y1 = 25.0F;  float32_t lut_y2 = 26.0F;
    
    // Extraídos directo de la memoria FLASH (Punteros)
    float32_t vcf_q11 = 0.9830F; // T=25, D=535
    float32_t vcf_q21 = 0.9870F; // T=25, D=540
    float32_t vcf_q12 = 0.9810F; // T=26, D=535
    float32_t vcf_q22 = 0.9850F; // T=26, D=540
    
    // Ejecución rápida O(1) de CPU
    float32_t vcf_exacto = Calcular_Interpolacion_Bilineal(
        lectura_densidad_actual, lectura_temperatura_actual,
        lut_x1, lut_x2,
        lut_y1, lut_y2,
        vcf_q11, vcf_q21,
        vcf_q12, vcf_q22
    );
    
    if (vcf_exacto > 0.0F) {
        // Exito: Aplicar a la metrología
        // litros_compensados = litros_brutos * vcf_exacto;
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Precisión Científica con Recursos Computacionales Limitados.

Cobrar Gas LP sin compensar sus densidades térmicas sería como vender frutas sin báscula, guiándose solo por el tamaño a la vista. Las normas de la OIML (Organización Internacional de Metrología Legal) son brutales: Si la máquina tiene un error de más del 1%, es clausurada.

En procesadores avanzados de PC esto se resuelve computando las ecuaciones diferenciales de la Tabla API. Pero en tu STM32F401, ejecutar un polinomio logarítmico cada 50 milisegundos causaría un cuello de botella que podría ocasionar la pérdida de pulsos del caudalímetro. Al implementar el algoritmo de **Interpolación Bilineal** acoplado a una **Matriz Rala en ROM**, lograste la misma precisión científica (4 decimales de exactitud) ejecutando únicamente unas cuantas sumas, restas y divisiones básicas. El procesador ni suda, la RAM permanece en cero absoluto y el cliente recibe su volumen exacto facturado a 20°C y corregido a la densidad del lote actual. Esta elegancia matemática es lo que convierte a un programador de scripts en un Ingeniero de Sistemas Críticos.

📝 Resumen del Día