¿Por qué la industria petroquímica usa sensores analógicos de 4 a 20 miliamperios en lugar de 0 a 10 Voltios? Por el diagnóstico inherente. En un sensor de 0-10V, si la presión es cero, el sensor envía 0V. Si el cable se corta, el ADC lee 0V. La CPU no tiene forma de saber la diferencia entre "No hay gas" y "El cable está roto".
En el estándar 4-20mA, el Cero Físico (0 Bar de presión) equivale a 4 mA. Esto se conoce como "Cero Vivo" (Live Zero). Si tu ADC lee 0 mA, es eléctricamente imposible que sea una lectura válida. Significa absoluta y categóricamente que el circuito está abierto (Cable Roto). Si lee >20 mA, hay un cortocircuito a VCC.
El caudalímetro genera pulsos digitales mediante un transistor de Colector Abierto (NPN Open-Collector). Esto significa que el sensor solo puede jalar el voltaje a tierra (0V), no puede empujarlo hacia arriba. Por eso instalas una resistencia Pull-Up hacia los 3.3V en tu placa. Si el técnico desconecta el cable del caudalímetro, la resistencia Pull-Up interna obligará al pin del STM32 a leer permanentemente 3.3V (Estado Lógico 1). A esto se le llama el estado de reposo "Seguro a Fallos".
El Problema: El operario marca $200 pesos, la válvula hace "Click", pero la pantalla se queda congelada en `0.00 L` durante 8 segundos. Luego, la máquina muestra `ERROR E04 (FLUJO)` y se apaga. El técnico llega a la estación. ¿Cómo sabe si la válvula no abrió, si no hay presión de gas en el tanque, o si el sensor de flujo está dañado?
El Método (Half-Splitting):
Convertiremos esta teoría de hardware en código. Programaremos funciones que no solo "leen" el pin, sino que auditan su estado eléctrico físico basándose en los umbrales de falla (Fault Thresholds).
/**
* @file hardware_diagnostic_audit.c
* @brief Algoritmos de Detección de Falla en Lazos de Control (Wire Break)
*/
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include <stdbool.h>
// =========================================================================
// DEFINICIONES DE LÍMITES ELÉCTRICOS (FAULT THRESHOLDS)
// =========================================================================
// ADC de 12 bits (0 a 4095). R_Shunt = 150 Ohm. VCC = 3.3V.
// 4 mA = (0.004 A * 150 Ohm) = 0.6V -> ADC = (0.6 * 4095) / 3.3 = ~744
// 20 mA = (0.020 A * 150 Ohm) = 3.0V -> ADC = (3.0 * 4095) / 3.3 = ~3722
#define ADC_THRESHOLD_OPEN_CIRCUIT (200U) // Menos de ~1 mA es físicamente un cable roto
#define ADC_THRESHOLD_SHORT_CIRCUIT (3900U) // Más de ~21 mA es un corto a VCC
// Pin del Caudalímetro
#define FLOWMETER_PORT GPIOA
#define FLOWMETER_PIN GPIO_PIN_0
typedef enum {
SENSOR_OK,
ERR_WIRE_CUT_OPEN,
ERR_SHORT_TO_GND,
ERR_SHORT_TO_VCC
} SensorHealth_t;
// =========================================================================
// DIAGNÓSTICO DEL LAZO 4-20mA (PRESIÓN ANALÓGICA)
// =========================================================================
/**
* @brief Evalúa la integridad eléctrica del transductor de presión.
* @param raw_adc_value: Lectura cruda del ADC (0 - 4095).
*/
SensorHealth_t Diag_Check_4_20mA_Loop(uint16_t raw_adc_value) {
if (raw_adc_value < ADC_THRESHOLD_OPEN_CIRCUIT) {
printf("[!] DIAG_ADC: Cable cortado (Corriente < 4mA). \r\n");
return ERR_WIRE_CUT_OPEN;
}
else if (raw_adc_value > ADC_THRESHOLD_SHORT_CIRCUIT) {
printf("[!] DIAG_ADC: Cortocircuito detectado a +24V. \r\n");
return ERR_SHORT_TO_VCC;
}
return SENSOR_OK;
}
// =========================================================================
// DIAGNÓSTICO DEL CAUDALÍMETRO (ESTADOS DIGITALES ATASCADOS)
// =========================================================================
/**
* @brief Vigila si el pin EXTI se queda atascado en un voltaje fijo.
* Esto debe llamarse dentro del Timeout Failsafe (Día 303) para dar un reporte detallado.
*/
SensorHealth_t Diag_Check_Flowmeter_State(void) {
// Leemos el estado eléctrico crudo del pin
GPIO_PinState pin_state = HAL_GPIO_ReadPin(FLOWMETER_PORT, FLOWMETER_PIN);
if (pin_state == GPIO_PIN_SET) {
// El pin está HIGH constante. El transistor NPN no está conduciendo a GND.
// Dado que usamos una resistencia Pull-Up a 3.3V, esto es el comportamiento
// esperado de un CABLE CORTADO o un sensor desenchufado.
printf("[!] DIAG_EXTI: Pin atascado en HIGH. Posible cable cortado.\r\n");
return ERR_WIRE_CUT_OPEN;
} else {
// El pin está LOW constante. El voltaje se está drenando.
// Esto indica que el cable de señal se peló y está tocando el chasis de la máquina (GND)
// o que el transistor del sensor se quemó y quedó en cortocircuito interno.
printf("[!] DIAG_EXTI: Pin atascado en LOW. Posible corto a chasis (GND).\r\n");
return ERR_SHORT_TO_GND;
}
}
Objetivo del día: Autodiagnóstico de Hardware a nivel eléctrico y Reducción del MTTR.
El error catastrófico del diseño "amateur" es tratar al hardware analógico y digital como cajas negras que solo escupen números. Un estudiante lee "0" en su ADC y su pantalla muestra felizmente "0.0 Bar de presión", ignorando que las tuberías industriales siempre tienen un mínimo de presión de vapor residual. Si lees 0 absolutos en un entorno petroquímico, tu hardware está ciego.
Al implementar **Detección de Cable Roto (Wire Break Detection)** en tu rutina de diagnóstico, cambiaste las reglas del juego. Tu microcontrolador ahora comprende la topología eléctrica de su propio cuerpo. Sabe que gracias al estándar industrial de 4-20mA, cualquier valor por debajo de 4mA no es "baja presión", es un fallo de cableado severo. Y gracias al uso inteligente de las resistencias internas **Pull-Up** del STM32, el procesador puede distinguir si el silencio del caudalímetro se debe a que el engranaje no gira, a que alguien cortó el cable con unas pinzas (Stuck HIGH), o a que el aislamiento se fundió y tocó la tubería de metal (Stuck LOW). Has dotado a tu máquina de un sistema nervioso que siente el dolor de sus propias extremidades mutiladas, guiando al técnico de servicio exactamente hacia el conector dañado.