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.
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.
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.
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
}
}
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.
float destructivos.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.