DÍA 265 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

El Sensor de Corriente (Aislamiento Total)

Los motores de las gasolineras funcionan con Corriente Alterna (AC) a 110V o 220V. Jamás debes conectar estas líneas cerca de tu STM32. Utilizaremos un Sensor de Efecto Hall (como el ACS724). El cable de 220V de la bomba atraviesa el chip, pero no tiene contacto eléctrico con la placa. El chip mide el campo magnético generado por la corriente y emite un voltaje analógico proporcional (ej. 40mV por cada Amperio), perfectamente seguro para el ADC del STM32.

Al ser corriente alterna, el sensor no emite un voltaje fijo. Emite una onda senoidal. A cero Amperios, el sensor emite exactamente la mitad del voltaje de alimentación (VDD/2 = 1.65V). Cuando la corriente fluye, el voltaje oscila hacia arriba y hacia abajo de ese centro.

Inrush Current vs. Sobrecarga Crónica

El desafío del software es la física de los motores de inducción. Cuando enciendes un motor parado, este necesita vencer la inercia (romper el reposo). Para lograrlo, absorbe la Corriente de Arranque (Inrush Current), que puede ser entre 5 y 8 veces la corriente nominal durante los primeros 2 segundos. Un motor de 5A "jalará" 30A al arrancar.

Si tu código apaga la máquina al ver "30A", el Despachador jamás podrá encender la bomba. Para un mantenimiento predictivo real, debemos calcular el Valor RMS (Root Mean Square) ignorando los primeros segundos de arranque, y luego promediar esas lecturas a lo largo de días o semanas.

FIRMA ELÉCTRICA: INRUSH CURRENT VS DEGRADACIÓN PROGRESIVA I (RMS) Tiempo 30.0 A 8.0 A 5.0 A 0.0 A LÍMITE DE MANTENIMIENTO Delay 2s Pico de Arranque (Inrush) El Software DEBE ignorar esto. MOTOR SANO Amperaje Estable ALERTA PREDICTIVA La Fricción aumentó el trabajo. Agendar Cambio de Filtros. PARO FORZADO (Previene Incendio)

⚙️ Ejercicios Prácticos

Configuración de Hardware: Si la red eléctrica es de 60 Hz, un ciclo completo dura 16.6 milisegundos. Para capturar la forma de la onda con precisión, configuraremos el Timer del ADC para muestrear a 1,000 Hz utilizando el DMA. Almacenaremos 100 muestras (equivalente a 0.1 segundos, atrapando unos 6 ciclos AC enteros).

Ejercicio 1: Cálculo RMS y Filtro de Largo Plazo (EMA). Una vez más, no reinventaremos la rueda. Usaremos la función arm_rms_f32() de la librería CMSIS-DSP, y le agregaremos un Filtro Promediador Exponencial (EMA) para suavizar los picos aleatorios de la red eléctrica, generando un valor "Tendencial" estable.


/**
 * @file dsp_motor_current.c
 * @brief Monitor de Corriente RMS y Sobrecarga Progresiva (CMSIS-DSP / MISRA-C)
 */

#include "stm32f401xe.h"
#include "cmsis_os2.h"
#define ARM_MATH_CM4
#include "arm_math.h"
#include <stdint.h>
#include <stdbool.h>

// =========================================================================
// DEFINICIONES DEL SENSOR Y MOTOR
// =========================================================================
#define ADC_SAMPLES             (100U)      // 100 muestras a 1kHz = 100ms de ventana
#define ADC_MAX_VOLTAGE         (3.3f)
#define ADC_RESOLUTION          (4095.0f)
#define SENSOR_VOLTAGE_OFFSET   (1.65f)     // Voltaje a 0 Amperios (VDD/2)
#define SENSOR_SENSITIVITY      (0.040f)    // ACS724-20A emite 40mV por Amperio

#define LIMITE_AMPERAJE_ALARMA  (7.0f)      // Límite de mantenimiento predictivo
#define LIMITE_AMPERAJE_CORTE   (9.0f)      // Límite de falla inminente

// =========================================================================
// FILTRO EMA PARA TENDENCIAS A LARGO PLAZO
// =========================================================================
#define EMA_ALPHA_CORRIENTE     (0.01f)     // Filtro MUY lento (Ignora picos cortos)
static float32_t corriente_tendencia_rms = 0.0f;
static bool motor_arrancado = false;
static uint32_t timestamp_arranque = 0U;

// Buffers de la DMA
uint16_t adc_corriente_raw[ADC_SAMPLES];
float32_t corriente_ac_instantanea[ADC_SAMPLES];

extern void Motor_Apagar_Emergencia(void);
extern void MQTT_Enviar_Alerta_Corriente(float32_t amperaje);

// =========================================================================
// TAREA RTOS: ANÁLISIS DE CORRIENTE (1Hz)
// =========================================================================
void Task_Motor_Current_Monitor(void *argument) {
    
    // Supongamos que la Tarea de Metrología enciende el motor y 
    // establece la bandera 'motor_arrancado = true'.
    
    for(;;) {
        if (motor_arrancado) {
            
            // --- 1. ZONA CIEGA DE ARRANQUE (BLIND SPOT) ---
            // Ignorar los primeros 2000 milisegundos para dejar pasar el Inrush Current
            if ((osKernelGetTickCount() - timestamp_arranque) < 2000U) {
                osDelay(pdMS_TO_TICKS(100U));
                continue; 
            }
            
            // --- 2. CONVERSIÓN DIGITAL A FÍSICA (Voltaje a Amperios) ---
            // Llenamos el array de floats restando el Offset central.
            // Si el ADC lee 1.65V, la corriente instantánea será 0.0A.
            for (uint16_t i = 0U; i < ADC_SAMPLES; i++) {
                float32_t voltaje_pin = ((float32_t)adc_corriente_raw[i] / ADC_RESOLUTION) * ADC_MAX_VOLTAGE;
                corriente_ac_instantanea[i] = (voltaje_pin - SENSOR_VOLTAGE_OFFSET) / SENSOR_SENSITIVITY;
            }
            
            // --- 3. PROCESAMIENTO DSP (RMS) ---
            // Calcula matemáticamente la Raíz Cuadrada de la Media de los Cuadrados
            // para toda la onda senoidal, dándonos el Amperaje Real.
            float32_t rms_actual = 0.0f;
            arm_rms_f32(corriente_ac_instantanea, ADC_SAMPLES, &rms_actual);
            
            // --- 4. FILTRO DE TENDENCIA (EMA) ---
            // Inicializar filtro en la primera lectura real post-arranque
            if (corriente_tendencia_rms == 0.0f) {
                corriente_tendencia_rms = rms_actual;
            } else {
                // Suavizar la lectura (Ignora micro-atascos o ruido de red)
                corriente_tendencia_rms = (rms_actual * EMA_ALPHA_CORRIENTE) + 
                                          (corriente_tendencia_rms * (1.0f - EMA_ALPHA_CORRIENTE));
            }
            
            // --- 5. TOMA DE DECISIÓN (DIAGNÓSTICO) ---
            if (corriente_tendencia_rms >= LIMITE_AMPERAJE_CORTE) {
                // FALLA CRÍTICA INMINENTE: Motor trancado.
                // Apagado de emergencia para evitar fuego o destrucción del bobinado.
                Motor_Apagar_Emergencia();
                MQTT_Enviar_Alerta_Corriente(corriente_tendencia_rms);
            } 
            else if (corriente_tendencia_rms >= LIMITE_AMPERAJE_ALARMA) {
                // DESGASTE MECÁNICO DETECTADO (Predictivo)
                // El motor sigue despachando, pero le cuesta demasiado esfuerzo.
                // Enviar aviso silencioso a la nube para agendar mantenimiento preventivo.
                MQTT_Enviar_Alerta_Corriente(corriente_tendencia_rms);
            }
        } else {
            // Motor apagado, resetear el filtro para el próximo cliente
            corriente_tendencia_rms = 0.0f;
        }
        
        // Ejecutar este análisis 1 vez por segundo
        osDelay(pdMS_TO_TICKS(1000U));
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Digitalización de Signos Vitales y Prevención de Desastres Mecánicos.

La diferencia entre un sistema "Smart" genérico y un equipo Industrial radica en cómo manejan la física de la potencia. Si le pones un sensor de corriente a un motor y configuras un límite estricto en el software, la máquina se bloqueará sola en su primer encendido debido al *Inrush Current*. Si no usas un cálculo RMS y simplemente lees el ADC aleatoriamente, estarás leyendo los ceros y los picos de la onda senoidal alterna, obteniendo valores inservibles.

Al implementar la librería **CMSIS-DSP para cálculo RMS real** y envolver el resultado en un **Filtro Promediador Exponencial (EMA)**, le has enseñado a tu firmware a tener paciencia. La máquina ignora el caos del encendido, suaviza los ruidos transitorios de la red eléctrica, y vigila una "Línea de Tendencia" perfecta. Cuando las partes mecánicas internas (como el by-pass de la bomba de Gas LP) comiencen a fallar por suciedad meses después de la instalación, la línea de tendencia subirá milímetro a milímetro. Tu código disparará una alerta en AWS semanas antes de que el daño sea permanente. Estás vendiendo tiempo, el recurso más valioso para cualquier gasolinera.

📝 Resumen del Día