Cuando trazas tus esquemáticos en KiCad, colocas capacitores de desacoplo de 100nF y 10uF cerca de cada componente integrado, además de los grandes capacitores electrolíticos para estabilizar los reguladores de voltaje TO-252 que alimentan tu máquina. En el momento $T=0$, cuando el relevador principal se cierra, estos capacitores están vacíos. La fuente de poder los percibe temporalmente como un cable directo a tierra (GND).
Si la pantalla LCD, el módulo Wi-Fi, la EEPROM, la impresora térmica y el chip de RS485 exigen esta corriente simultáneamente, el consumo se dispara a varios amperios durante un par de milisegundos. Esta **Corriente de Irrupción (Inrush Current)** puede superar la capacidad máxima del regulador, hundiendo la línea de 3.3V hacia los 1.8V y provocando que el STM32 lance un Reset de Hardware por caída de voltaje (BOR - Brownout Reset).
Para lograr una arquitectura industrial robusta, los subsistemas en el PCB se alimentan mediante circuitos Load Switch (con MOSFETs) o utilizando el pin EN (Enable) presente en la mayoría de los reguladores modernos o periféricos. Estos pines se conectan a los GPIO del STM32. El procesador arranca aislado, consumiendo muy poca energía, y luego decide **cuándo y en qué orden** habilitar al resto del hardware.
Ejercicio 1: Reemplazaremos la llamada estática de inicializaciones al principio del `main()`. Crearemos una **Máquina de Estados de Boot No Bloqueante**. El procesador encenderá, levantará el reloj central (PLL), y luego usará la base de tiempo de `millis()` (nuestro contador alimentado por SysTick) para habilitar progresivamente los GPIOs de control de potencia, configurando y esperando que cada dispositivo levante su bandera de "Ready".
/**
* @file power_sequence.c
* @brief Máquina de Estados para Arranque Escalonado (Anti-Inrush)
*/
#include "stm32f401xe.h"
#include <stdbool.h>
#include <stdint.h>
// Dependencia de la base de tiempo global (Día 98)
extern volatile uint32_t ms_ticks;
// Macros para control de pines EN (Enable) en GPIOA
#define EN_SENSORS_ON() (GPIOA->BSRR = GPIO_BSRR_BS1)
#define EN_COMMS_ON() (GPIOA->BSRR = GPIO_BSRR_BS2)
#define EN_POWER_ON() (GPIOA->BSRR = GPIO_BSRR_BS3)
// Estados de la máquina de arranque
typedef enum {
BOOT_START = 0,
BOOT_WAIT_SENSORS,
BOOT_INIT_SENSORS,
BOOT_WAIT_COMMS,
BOOT_INIT_COMMS,
BOOT_WAIT_ACTUATORS,
BOOT_INIT_ACTUATORS,
BOOT_COMPLETE
} BootState_t;
static BootState_t estado_boot = BOOT_START;
static uint32_t tiempo_inicio_estado = 0;
// Bandera global para que el Súper Bucle sepa cuándo puede operar
bool sistema_listo = false;
// Dependencias de inicialización de módulos
extern void inicializar_i2c1(void);
extern void inicializar_usart2_modbus(void);
extern void inicializar_pwm_valvula(void);
/**
* @brief Configura los GPIOs encargados de activar la potencia.
* Se llama inmediatamente al iniciar el hardware.
*/
void inicializar_pines_power_sequence(void) {
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// Configurar PA1, PA2, PA3 como salidas Push-Pull
GPIOA->MODER &= ~((3 << 2) | (3 << 4) | (3 << 6));
GPIOA->MODER |= ((1 << 2) | (1 << 4) | (1 << 6));
// ESTADO SEGURO INICIAL: Todo APAGADO (BSRR Reset)
GPIOA->BSRR = GPIO_BSRR_BR1 | GPIO_BSRR_BR2 | GPIO_BSRR_BR3;
}
/**
* @brief Máquina de estados no bloqueante que despierta al hardware.
* Debe llamarse continuamente en el main hasta que retorne true.
*/
void gestor_secuencia_arranque(void) {
switch (estado_boot) {
case BOOT_START:
// 1. Dar energía a la sección crítica (EEPROM, Reloj RTC Externo)
EN_SENSORS_ON();
tiempo_inicio_estado = ms_ticks;
estado_boot = BOOT_WAIT_SENSORS;
break;
case BOOT_WAIT_SENSORS:
// Esperar 50ms para que los capacitores I2C se carguen
// y los chips hagan su propio Power-On-Reset.
if ((ms_ticks - tiempo_inicio_estado) >= 50) {
estado_boot = BOOT_INIT_SENSORS;
}
break;
case BOOT_INIT_SENSORS:
// Ahora sí, configurar el hardware interno del STM32 para usar el I2C
inicializar_i2c1();
// 2. Dar energía a las telecomunicaciones (MAX485, Módulo Wi-Fi)
EN_COMMS_ON();
tiempo_inicio_estado = ms_ticks;
estado_boot = BOOT_WAIT_COMMS;
break;
case BOOT_WAIT_COMMS:
// Esperar 100ms. Los chips de radio frecuencia consumen mucha corriente al prender.
if ((ms_ticks - tiempo_inicio_estado) >= 100) {
estado_boot = BOOT_INIT_COMMS;
}
break;
case BOOT_INIT_COMMS:
inicializar_usart2_modbus();
// 3. Dar energía a la potencia brutal (Impresoras, Válvulas)
EN_POWER_ON();
tiempo_inicio_estado = ms_ticks;
estado_boot = BOOT_WAIT_ACTUATORS;
break;
case BOOT_WAIT_ACTUATORS:
// Esperar 250ms a que los grandes condensadores electrolíticos se asienten
if ((ms_ticks - tiempo_inicio_estado) >= 250) {
estado_boot = BOOT_INIT_ACTUATORS;
}
break;
case BOOT_INIT_ACTUATORS:
inicializar_pwm_valvula();
// Secuencia Finalizada exitosamente
estado_boot = BOOT_COMPLETE;
sistema_listo = true;
break;
case BOOT_COMPLETE:
// No hacer nada, el sistema ya está arriba.
break;
}
}
int main(void) {
// Configuración Base Extrema (Sólo Relojes y SysTick)
// inicializar_relojes_84mhz();
// SysTick_Init_1ms();
inicializar_pines_power_sequence();
// Bucle infinito principal
while(1) {
// Fase 1: El Despertar
if (!sistema_listo) {
gestor_secuencia_arranque();
}
// Fase 2: Operación Normal Industrial
else {
// La máquina de gas funciona normal
// despachar_gas_controlado();
// procesar_modbus();
// lcd_actualizar();
}
}
return 0;
}
Objetivo del día: Control de Transientes de Encendido y Estabilidad Inicial.
Cuando diseñas tu PCB en KiCad, separas cuidadosamente los planos de tierra analógicos y digitales, y colocas docenas de capacitores alrededor del procesador y los integrados para filtrar el ruido. Pero la física es implacable: un capacitor descargado es un cortocircuito eléctrico en el milisegundo cero. Si intentas encender la impresora térmica, las electroválvulas y el módulo de comunicaciones en el mismo momento en que el STM32 arranca, la fuente de 24V sufrirá, y el regulador principal de 3.3V colapsará antes de siquiera estabilizarse.
Al implementar una **Máquina de Estados de Arranque Escalonado (Power Sequence)**, has fusionado tu diseño de hardware (los reguladores con pines EN) con la inteligencia de tu firmware. El procesador despierta en silencio y toma el control absoluto. Enciende la primera zona del PCB, espera a que la corriente se estabilice matemáticamente contando milisegundos con el SysTick, configura los puertos asociados, y pasa a la siguiente fase. Esta delicada coreografía de encendido garantiza que la metrología, la comunicación y el control de potencia inicien siempre sobre una plataforma de voltaje impecable y estable.
Enable de un regulador de voltaje secundario, o utilizando Load Switches).delay_ms(100) rígidas al principio del main() son ineficientes. Una Máquina de Estados No Bloqueante permite que el procesador vigile interrupciones de seguridad críticas mientras administra pacientemente el encendido del sistema.