Un sensor de presión de Gas de 0 a 20 Bar convierte físicamente la presión en corriente. Si la presión es máxima (20 Bar), dejará pasar 20 miliamperios (mA). Si la presión es cero (0 Bar), dejará pasar 4 miliamperios.
¿Por qué 4mA y no 0mA? Si usamos 0mA para representar "Cero Presión", y un día la excavadora de la obra corta accidentalmente el cable del sensor, tu microcontrolador leerá 0mA y pensará: "Todo está bien, la presión es cero". Has perdido la visibilidad del sistema. Al usar 4mA como base (conocido como Live Zero o Cero Vivo), el microcontrolador sabe distinguir:
Los microcontroladores (como el STM32) no miden corriente; miden voltaje mediante su ADC (Convertidor Analógico a Digital). Para transformar la corriente industrial en voltaje, colocamos una simple "Resistencia Shunt" (Resistencia de Carga) de alta precisión entre el cable y la Tierra (GND). La corriente atravesará la resistencia, generando un voltaje proporcional: V = I * R.
Para un ADC de 3.3V, usamos una resistencia estándar de 150 Ω:
V = 0.004 A * 150 Ω = 0.6 Voltios.V = 0.020 A * 150 Ω = 3.0 Voltios.El rango de 0.6V a 3.0V encaja perfectamente dentro del límite de 3.3V de tu STM32, aprovechando casi toda la resolución de los 12 bits.
La Arquitectura del Hardware Analógico:
Ejercicio 1: El Software del Receptor Analógico. Escribiremos el módulo C que lee este voltaje seguro, implementa la detección de cable roto (Fault Detection) y mapea matemáticamente el rango 4-20mA al valor real físico en PSI o Bar.
/**
* @file analog_4_20ma.c
* @brief Driver de Frontend Analógico Industrial (Lectura y Mapeo) - MISRA C
*/
#include "stm32f401xe.h"
#include <stdint.h>
#include <stdbool.h>
// =========================================================================
// CONSTANTES ELÉCTRICAS Y FÍSICAS (Calibración de Hardware)
// =========================================================================
#define ADC_RESOLUTION_12BIT (4095.0f)
#define VREF_MCU (3.3f) // Voltaje de referencia del ADC
#define SHUNT_RESISTOR_OHMS (150.0f) // Resistencia de carga (150 Ω)
// Límites del protocolo 4-20mA (Tolerancia añadida)
#define CORRIENTE_MIN_FALLA (3.5f) // mA: Debajo de esto = Cable Roto
#define CORRIENTE_CERO_ESCALA (4.0f) // mA: 0% del rango físico
#define CORRIENTE_FULL_ESCALA (20.0f) // mA: 100% del rango físico
#define CORRIENTE_MAX_CORTO (21.0f) // mA: Encima de esto = Cortocircuito
// Atributos del Sensor de Gas instalado en la tubería
#define SENSOR_PRESION_MIN_BAR (0.0f) // A 4mA
#define SENSOR_PRESION_MAX_BAR (25.0f) // A 20mA (Max de la bomba)
// Dependencias
extern uint16_t HAL_ADC_Read_Channel(uint8_t channel);
extern void FSM_Disparar_Alarma_Mantenimiento(const char* causa);
// =========================================================================
// FUNCIÓN PRINCIPAL DE LECTURA
// =========================================================================
/**
* @brief Adquiere el valor del ADC, valida la integridad eléctrica del bucle
* y devuelve la presión real en el tanque.
* @param channel: Canal del ADC (Ej. 0 para PA0)
* @param out_presion_bar: Puntero donde se guardará el resultado físico
* @retval bool: TRUE si la lectura es válida, FALSE si hay un fallo de hardware.
*/
bool Sensor_4_20mA_Leer_Presion(uint8_t channel, float* out_presion_bar) {
// 1. LECTURA CRUDA DEL HARDWARE
uint16_t adc_raw = HAL_ADC_Read_Channel(channel);
// 2. CONVERSIÓN DIGITAL A VOLTAJE
// Regla de tres simple: (adc / 4095) * 3.3V
float voltaje_leido = ((float)adc_raw / ADC_RESOLUTION_12BIT) * VREF_MCU;
// 3. LEY DE OHM (Voltaje a Corriente)
// I = V / R. Como la resistencia está en Ohmios, la corriente sale en Amperios.
// Multiplicamos por 1000 para trabajar cómodamente en miliAmperios (mA).
float corriente_ma = (voltaje_leido / SHUNT_RESISTOR_OHMS) * 1000.0f;
// 4. DIAGNÓSTICO DE HARDWARE (Detección de Fallas Físicas)
// A) CABLE ROTO (Broken Wire Detection)
if (corriente_ma < CORRIENTE_MIN_FALLA) {
FSM_Disparar_Alarma_Mantenimiento("ERR_SENSOR_CABLE_ROTO");
*out_presion_bar = 0.0f;
return false;
}
// B) CORTOCIRCUITO O SOBREPRESIÓN
if (corriente_ma > CORRIENTE_MAX_CORTO) {
FSM_Disparar_Alarma_Mantenimiento("ERR_SENSOR_CORTO_OVERLOAD");
*out_presion_bar = SENSOR_PRESION_MAX_BAR;
return false;
}
// 5. MAPEO MATEMÁTICO (Interpolación Lineal)
// Fórmula: RangoFísico * ((CorrienteActual - CorrienteMin) / (CorrienteMax - CorrienteMin)) + FísicoMin
// Para no dar valores negativos si la corriente fluctúa entre 3.8 y 4.0mA:
if (corriente_ma < CORRIENTE_CERO_ESCALA) {
corriente_ma = CORRIENTE_CERO_ESCALA;
}
float span_corriente = (CORRIENTE_FULL_ESCALA - CORRIENTE_CERO_ESCALA); // 16mA de ancho
float span_presion = (SENSOR_PRESION_MAX_BAR - SENSOR_PRESION_MIN_BAR); // 25 Bar de ancho
*out_presion_bar = ((corriente_ma - CORRIENTE_CERO_ESCALA) / span_corriente) * span_presion;
return true; // Lectura impecable
}
Objetivo del día: Acondicionamiento de Señal y Tolerancia a Fallos Mecánicos.
El "Internet de las Cosas" (IoT) aficionado muere rápido en el mundo real porque asume que los sensores nunca mienten. Si usas un sensor de voltaje de 0-5V en una planta, y una rata muerde el cable, el voltaje caerá a cero. Tu procesador leerá 0V y asumirá pacíficamente que el tanque de Gas LP está vacío, cuando en realidad la máquina se ha vuelto ciega y las bombas podrían arrancar en seco (cavitación) y destruirse.
Al implementar el estándar industrial **4-20mA (Live Zero)**, junto con un **Frontend con Diodos Clamp y Filtro RC**, has diseñado un sistema consciente de su propia integridad. El hardware protege al chip de los picos de voltaje inducidos en la planta, y el software (Firmware MISRA-C) distingue instantáneamente entre "presión cero" (4mA) y "cable cortado" (0mA). Cuando ocurre un fallo físico, el Despachador no miente ni ignora el error: activa el paro de emergencia, ilumina la baliza roja y alerta al SCADA sobre el cable roto. Has garantizado la seguridad operativa (Safety) de la estación de servicio.