DÍA 038 DE 365

Fase 1: Fundamentos de C y Lógica de Software

📖 Teoría a Estudiar: Conversión Analógico-Digital (ADC)

1. Resolución y Cuantización

Un ADC divide el rango de voltaje analógico de entrada en una serie de "escalones" digitales. La cantidad de escalones depende de la Resolución del ADC, medida en bits. Un STM32 o NXP Kinetis moderno posee un ADC de 12 bits. Esto significa que tiene $2^{12} = 4096$ escalones. Si el voltaje máximo de referencia (Vref) es 3.3V, un valor de 0 representa 0V, y 4095 representa 3.3V.

2. Circuito Anti-Aliasing (Filtro RC)

Antes de que el voltaje llegue al pin del microcontrolador, debe estabilizarse. Los motores y válvulas generan ruido de alta frecuencia. En el diseño de hardware, colocamos una resistencia en serie (ej. 1 kΩ) y un capacitor cerámico a tierra (ej. 100nF) pegado al pin del MCU. Esto actúa como un filtro pasa-bajas (RC), suministrando un voltaje limpio al circuito de "Sample and Hold" (Muestreo y Retención) interno del ADC.

3. El Reto del Software: Mapeo sin Floats

Si el ADC lee 2048, ¿cuántos PSI de presión hay en la tubería? Un programador junior usaría la ecuación de la recta con variables float, consumiendo miles de ciclos de CPU por cada lectura (como vimos en el Día 17). El Arquitecto resuelve esto con interpolación lineal usando enteros de 32 bits, multiplicando antes de dividir para conservar la precisión escalar.

CADENA DE ADQUISICIÓN: DE VOLTAJE A PSI Transductor 0 - 250 PSI Señal: 0.5V - 3.3V MCU - ADC 12-Bits REG: 0 - 4095 map_analog() int32_t puro Fórmula de Mapeo Lineal (Sin Floats): Y = (X - X_min) * (Y_max - Y_min) / (X_max - X_min) + Y_min * Se multiplica primero para no perder la fracción, usando variables de 32 bits.

⚙️ Ejercicios Prácticos

Ejercicio 1: Implementa la función de mapeo genérica para enteros de 32 bits. Luego aplícala a un caso real: un sensor industrial de presión que entrega 0.5V (lectura ADC aprox. 620) a 0 PSI, y 3.3V (lectura ADC 4095) a 250 PSI.


#include <stdint.h>

/**
 * @brief  Mapea matemáticamente un rango entero a otro (Interpolación lineal).
 * @param  x       El valor de lectura actual del ADC a mapear.
 * @param  in_min  Límite inferior del rango de entrada del ADC.
 * @param  in_max  Límite superior del rango de entrada del ADC.
 * @param  out_min Límite inferior del valor físico de salida.
 * @param  out_max Límite superior del valor físico de salida.
 * @return El valor físico proporcional (escalado).
 */
int32_t map_analog(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max) {
    
    // RED DE SEGURIDAD 1: Evitar división por cero si se configuran mal los rangos
    if (in_min == in_max) {
        return out_min;
    }
    
    // RED DE SEGURIDAD 2: Limitar la lectura (x) para que no exceda los rangos
    // y provoque lecturas de presión negativas o absurdamente altas.
    if (x < in_min) x = in_min;
    if (x > in_max) x = in_max;
    
    // MAGIA BARE-METAL: Multiplicar primero, dividir después.
    // Al usar int32_t, soportamos multiplicaciones enormes sin desbordamiento (hasta 2.14 Billones).
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

// =====================================================================
// APLICACIÓN EN EL DESPACHADOR LP
// =====================================================================
// Especificaciones del Sensor:
// 0 PSI = 0.5V.  En ADC (3.3V Vref) -> (0.5 / 3.3) * 4095 ≈ 620
// 250 PSI = 3.3V. En ADC (3.3V Vref) -> 4095

#define SENSOR_ADC_MIN   620
#define SENSOR_ADC_MAX   4095
#define PRESION_PSI_MIN  0
#define PRESION_PSI_MAX  250

void Monitorear_Presion_Seguridad(void) {
    
    // Leemos el registro de hardware del ADC (DMA o Polling directo)
    // Supongamos que nos da una lectura de 2357
    int32_t lectura_cruda_adc = 2357; 
    
    // Pasamos el valor por el algoritmo de mapeo
    int32_t presion_actual_psi = map_analog(lectura_cruda_adc, 
                                            SENSOR_ADC_MIN, 
                                            SENSOR_ADC_MAX, 
                                            PRESION_PSI_MIN, 
                                            PRESION_PSI_MAX);
                                            
    // presion_actual_psi contendrá ~125 PSI instantáneamente, sin Floats.
    
    if (presion_actual_psi > 230) {
        // Ejecutar rutina de Alarma / Cierre de Válvulas
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Adquisición de Señal Física de Precisión.

El control del gas se reduce a leer parámetros físicos con exactitud. Si tu código usara rutinas de coma flotante para calcular la presión actual, el procesador desperdiciaría cientos de ciclos de reloj por cada lectura. Utilizando esta función de interpolación basada estrictamente en enteros (int32_t), tu MCU puede procesar miles de lecturas del sensor por segundo sin sudar, dejando el procesador libre para manejar la Matriz de Seguridad y el Bus I2C de forma impecable.

📝 Resumen del Día

❓ Cuestionario de Autoevaluación

1. ¿Qué pasaría en la función de mapeo si usaras int16_t en lugar de int32_t?
Respuesta: Ocurriría un Integer Overflow (desbordamiento). La parte de la ecuación (x - in_min) * (out_max - out_min) fácilmente puede superar los 32,767 (el límite de un entero de 16 bits con signo). El resultado matemático colapsaría, arrojando valores de presión negativos absurdos y comprometiendo la Matriz de Seguridad de tu máquina.