Un transductor de presión industrial (como los utilizados en sistemas de Gas LP y Diésel) generalmente requiere 5V para funcionar, pero su salida de señal está estandarizada a un rango seguro: usualmente **0.5V a 4.5V**. ¿Por qué no de 0V a 5V? Para detectar cables rotos. Si el cable se corta, el ADC leerá 0V y tu software sabrá que el sensor falló (Error de hardware), en lugar de pensar erróneamente que hay 0 PSI de presión.
El ADC de tu STM32F4 explota si le inyectas más de 3.3V. Si nuestro sensor entrega hasta 4.5V, necesitamos un Divisor de Tensión Resistivo por hardware. Usando dos resistencias ($R_1$ y $R_2$), comprimimos el rango de 5V hacia un rango máximo de 3.3V.
Para este ejercicio, asumiremos que aplicamos un divisor (ej. $R_1=2k\Omega$, $R_2=3.3k\Omega$) que reduce el rango de la señal del sensor. De modo que cuando hay 0 PSI (0.5V del sensor), al pin del microcontrolador le llegan **0.33V**. Cuando hay presión máxima de 150 PSI (4.5V del sensor), al pin le llegan **2.97V**.
El ADC convierte voltajes a números (0 a 4095). Si nuestro $V_{ref}$ es 3.3V:
La relación entre el valor ADC crudo y la presión física se define por la ecuación de la recta: $y = mx + b$. En nuestro código C, resolveremos esto usando aritmética de enteros (Punto Fijo).
Ejercicio 1: Integra la lectura de Polling del ADC en una función que utilice matemática entera (Punto Fijo) para entregar la presión del gas en PSI, con un decimal de precisión. Si el sensor se desconecta, el sistema debe reportar un error crítico para apagar la válvula.
/**
* @file presion_driver.c
* @brief Algoritmo Metrológico de Adquisición de Presión
*/
#include "stm32f401xe.h"
// Constantes calibradas de la Recta de Transferencia
#define ADC_OFFSET_RAW 409 // Equivale a 0.33V (0 PSI)
#define ADC_MAX_RAW 3685 // Equivale a 2.97V (150 PSI)
#define PRESION_MAX_PSI 150 // Fondo de escala del sensor
#define ERROR_SENSOR 9999 // Código de error para cable roto
// Función de inicialización y lectura heredadas del Día 111
extern void inicializar_adc1_pa1(void);
extern uint16_t leer_adc1_crudo(void);
/**
* @brief Calcula la presión en PSI escalada por 10 (Punto Fijo).
* Ejemplo: Retornar '1425' significa 142.5 PSI.
* @return uint32_t Presión calculada o código de ERROR_SENSOR.
*/
uint32_t obtener_presion_psi(void) {
// 1. Tomamos la "fotografía" analógica del tubo de gas
uint16_t adc_crudo = leer_adc1_crudo();
// 2. DIAGNÓSTICO DE HARDWARE (Seguridad)
// Si el valor es drásticamente menor al offset (ej. ADC < 200),
// el cable se cortó o el sensor perdió masa.
if (adc_crudo < (ADC_OFFSET_RAW - 50)) {
return ERROR_SENSOR;
}
// Si el valor está apenas por debajo del offset por ruido eléctrico, lo limitamos a 0
if (adc_crudo < ADC_OFFSET_RAW) {
return 0;
}
// 3. MATEMÁTICA DE PUNTO FIJO
// Restamos el offset para que 0 PSI = 0 crudo
uint32_t adc_util = adc_crudo - ADC_OFFSET_RAW;
// Rango dinámico útil del ADC
uint32_t rango_adc = ADC_MAX_RAW - ADC_OFFSET_RAW; // = 3276
// Calculamos PSI usando factor de escala * 10 para ganar un decimal.
// Ecuación: (ADC_util * Max_PSI * Escala) / Rango_ADC
uint32_t presion_fija = (adc_util * PRESION_MAX_PSI * 10) / rango_adc;
// 4. Limitar al máximo mecánico si excede ligeramente por ruido
if (presion_fija > (PRESION_MAX_PSI * 10)) {
presion_fija = PRESION_MAX_PSI * 10;
}
return presion_fija;
}
int main(void) {
inicializar_adc1_pa1();
// Valvula_Init();
while(1) {
uint32_t presion_actual = obtener_presion_psi();
if (presion_actual == ERROR_SENSOR) {
// ¡Peligro de explosión o fallo de lectura!
// VALVULA_OFF();
// Disparar_Alarma();
}
else if (presion_actual > 1200) { // 120.0 PSI
// Sobrepresión detectada en la manguera
// Control_Proporcional_Bajar_Flujo();
}
// Retardo no bloqueante del SysTick para no saturar al ADC
// delay_ms_nobloqueante(100);
}
return 0;
}
Objetivo del día: Telemetría Diagnóstica y Evitación de Ruptura.
Al despachar Gas LP, el calor ambiental expande el líquido. Si la manguera de tu despachador se dobla accidentalmente y la bomba del camión sigue empujando el fluido, la presión pasará de 80 PSI a 150 PSI en una fracción de segundo, lo que podría arrancar la boquilla de las manos del cliente.
Tu algoritmo no solo mide esa fuerza; implementa un diagnóstico de integridad de lazo (Loop Integrity). Gracias al escalamiento matemático que desarrollaste, tu código Bare-Metal procesa la multiplicación cruzada de la ecuación de la recta de manera nativa sin el peso del Coprocesador de Punto Flotante. Si alguien corta el cable del sensor por vandalismo, el valor crudo caerá a `0`, detonando la rutina ERROR_SENSOR y bloqueando la electroválvula. Tu Tesis acaba de alcanzar un nivel de robustez de control de procesos (PID/SCADA) real.
while) es aceptable en Bare-Metal debido a que el hardware del ADC completa la conversión en menos de 2 microsegundos (mucho más rápido que un rebote mecánico).