DÍA 291 DE 365

Fase 5: Diseño Industrial y Hardware

📖 Teoría a Estudiar

La Filosofía del Board Bring-Up

El "Bring-Up" es una fase transitoria. El objetivo de este código no es ser elegante, asíncrono o escalable. El objetivo es que sea estúpido, secuencial e implacable. Si intentas probar el conversor analógico-digital (ADC) dentro de una tarea de FreeRTOS controlada por un temporizador, cuando el valor devuelto sea cero, no sabrás si falló el hardware del sensor, la interrupción del reloj, el mutex del bus, o la asignación de memoria del sistema operativo.

Un ingeniero senior divide la placa (PCBA) y escribe un menú interactivo. Controlarás el STM32 desde el puerto serie de tu computadora portátil (UART CLI - Command Line Interface). Al presionar una tecla, el hardware deberá responder mecánicamente.

La Secuencia Dorada de Validación

  1. Clocks & GPIO: Parpadear LEDs. (Prueba que el procesador no está colgado).
  2. Consola Serial (UART de Depuración): Enviar texto a la PC (printf). A partir de este momento, el microcontrolador "puede hablar".
  3. Salidas Digitales Aisladas: Activar el optoacoplador del Relé de Gas. Escuchar el "Click" físico certifica que la etapa de potencia 24V (Día 274) funciona.
  4. Entradas Analógicas (ADC): Leer voltajes crudos del frontend 4-20mA (Día 273).
  5. Comunicaciones Externas: Enviar un paquete "AT" al ESP32 por el bus UART secundario y esperar un "OK".
SECUENCIA DE VALIDACIÓN (BOARD BRING-UP) UART DEBUG TERMINAL (115200 8N1) STM32 Bring-Up v1.0 ======================== [1] Test Relé Válvula [2] Leer ADC 4-20mA [3] Ping ESP32 (Wi-Fi) [4] Test Memoria I2C ======================== > Ingresa un comando: 1 Activando Optoacoplador... "CLICK" DETECTADO > Ingresa un comando: _ USB-UART FIRMWARE DE DIAGNÓSTICO (STM32) Bucle Infinito (Super-Loop Bare-Metal) Leer Serial() Switch Toggle_Relay() Read_ADC() Ping_ESP32() ⚠️ RTOS COMPLETAMENTE DESACTIVADO EN ESTA FASE ⚠️

⚙️ Práctica: El Código Validador (Command Line Interface)

Configuración de Hardware: Asumimos que tienes un adaptador USB-TTL (FTDI) conectado a tu computadora. Conecta el pin TX del adaptador al pin de Depuración UART (ej. PA3/RX) de tu STM32, y el RX del adaptador al PA2/TX. Asegúrate de unificar las tierras (GND).

Escribiremos un Super-Loop. Nada de interrupciones asíncronas complicadas; usaremos HAL_UART_Receive en modo bloqueante con timeout para leer el teclado del ingeniero.


/**
 * @file bringup_cli.c
 * @brief Interfaz de Línea de Comandos para Diagnóstico de Hardware Cero
 */

#include "stm32f401xe.h"
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include <string.h>

// Manejadores (Handles) inyectados desde la inicialización
extern UART_HandleTypeDef huart2; // UART de Depuración a PC
extern UART_HandleTypeDef huart1; // UART conectado al ESP32
extern ADC_HandleTypeDef hadc1;   // ADC del Sensor 4-20mA

// =========================================================================
// RUTINA DE IMPRESIÓN (Redirigir printf a UART2)
// =========================================================================
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE {
    HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}

// =========================================================================
// FUNCIONES DE PRUEBA DE HARDWARE
// =========================================================================

void Test_Relay_Valve(void) {
    printf("[*] Activando Relé de la Válvula (Escucha el Click)...\r\n");
    
    // Activa el optoacoplador que diseñamos en el Día 274
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
    HAL_Delay(1000); // Mantiene abierto 1 segundo
    
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
    printf("[V] Relé desactivado.\r\n");
}

void Test_ADC_4_20mA(void) {
    printf("[*] Leyendo Bucle de Corriente 4-20mA (Día 273)...\r\n");
    
    HAL_ADC_Start(&hadc1);
    if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
        uint32_t adc_value = HAL_ADC_GetValue(&hadc1);
        
        // Conversión rápida a voltaje (Asumiendo VREF=3.3V y 12-bits)
        float voltage = ((float)adc_value / 4095.0f) * 3.3f;
        
        // Mapeamos a mA (R_Shunt = 150 Ohms)
        float current_mA = (voltage / 150.0f) * 1000.0f;
        
        printf("    - Valor Crudo (12-bit): %lu\r\n", adc_value);
        printf("    - Voltaje Calculado:    %.2f V\r\n", voltage);
        printf("    - Corriente Sensada:    %.2f mA\r\n", current_mA);
        
        if(current_mA < 3.5f) {
            printf("[!] ADVERTENCIA: < 4mA. Cable Roto o Sensor Desconectado.\r\n");
        } else {
            printf("[V] Lazo de corriente dentro de rango operativo.\r\n");
        }
    } else {
        printf("[X] ERROR: Fallo de timeout en el hardware ADC.\r\n");
    }
    HAL_ADC_Stop(&hadc1);
}

void Test_ESP32_Comm(void) {
    printf("[*] Enviando comando 'AT' al ESP32 Wi-Fi...\r\n");
    uint8_t at_cmd[] = "AT\r\n";
    uint8_t rx_buffer[10] = {0};
    
    // Enviar comando al ESP32
    HAL_UART_Transmit(&huart1, at_cmd, strlen((char*)at_cmd), 100);
    
    // Esperar respuesta "OK" (Modo bloqueante simple)
    HAL_StatusTypeDef status = HAL_UART_Receive(&huart1, rx_buffer, 4, 1000);
    
    if (status == HAL_OK) {
        printf("[V] ESP32 Respondió: %s\r\n", rx_buffer);
    } else {
        printf("[X] ERROR: El ESP32 no responde. Revisa pistas TX/RX.\r\n");
    }
}

// =========================================================================
// EL BUCLE PRINCIPAL (SUPER-LOOP DE DIAGNÓSTICO)
// =========================================================================
void BringUp_Menu_Loop(void) {
    uint8_t rx_byte;
    
    printf("\r\n======================================\r\n");
    printf(" DESPACHADOR GAS LP - BRING-UP MODO \r\n");
    printf("======================================\r\n");
    printf(" [1] Test Relé (Válvula)\r\n");
    printf(" [2] Test Sensor Presión (4-20mA)\r\n");
    printf(" [3] Ping ESP32 (UART)\r\n");
    printf("======================================\r\n");
    
    while (1) {
        printf("> Ingresa comando: ");
        
        // Espera infinita por una tecla del ingeniero
        if (HAL_UART_Receive(&huart2, &rx_byte, 1, HAL_MAX_DELAY) == HAL_OK) {
            printf("%c\r\n", rx_byte); // Eco
            
            switch (rx_byte) {
                case '1': Test_Relay_Valve(); break;
                case '2': Test_ADC_4_20mA(); break;
                case '3': Test_ESP32_Comm(); break;
                case '\r':
                case '\n': break; // Ignorar enter
                default:
                    printf("[X] Comando inválido.\r\n");
                    break;
            }
        }
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Certificación de Capa Física y Abstracción de Hardware (HAL).

Cuando construyas el sistema operativo de tu Despachador (El RTOS de la Fase 6), habrá docenas de tareas corriendo simultáneamente: el Wi-Fi gestionando colas MQTT, el display actualizando el precio del gas, y el caudalímetro calculando masa por segundo. Si en ese caos intentas leer el sensor de 4-20mA y devuelve basura, podrías pasar una semana depurando tu código de gestión de memoria, cuando en realidad el operador en la fábrica soldó la resistencia Shunt de 150 Ohmios al revés (Día 273).

Al implementar el **Bring-Up Code** interactivo, aíslas la física del software. Te sientas frente a la placa pelada, conectas tu adaptador serial y presionas "1". Si la válvula hace *Click*, certificas para siempre que el ruteo de potencia (Día 280), el optoacoplador y los diodos Flyback funcionan físicamente. Si presionas "2" y lees `3.8mA`, sabes que el hardware ADC no tiene puentes de soldadura (Día 288). Solo cuando cada pieza de hardware ha respondido satisfactoriamente a su "Ping" manual, el ingeniero sella la placa, borra el código Bring-Up, y da luz verde para inyectar la arquitectura de software de misión crítica.

📝 Resumen del Día