Módulo 2

Entradas y salidas digitales (GPIOs)

GPIO y Control Digital

ESP32 Mecatrónica IoT UNAM

Introducción a los GPIOs del ESP32

Los GPIOs (General Purpose Input/Output) del ESP32 representan la interfaz fundamental entre el microcontrolador y el mundo exterior. Estos pines programables permiten la comunicación bidireccional con sensores, actuadores y otros dispositivos electrónicos, siendo esenciales para cualquier aplicación mecatrónica o IoT.

El ESP32 cuenta con 34 pines GPIO físicos, de los cuales aproximadamente 25-28 están disponibles para uso general dependiendo de la configuración del módulo. Cada GPIO puede ser configurado individualmente como entrada o salida digital, con capacidades adicionales como:

  • Entrada digital: Lee estados HIGH/LOW
  • Salida digital: Genera estados HIGH/LOW
  • Pull-up/Pull-down: Resistencias internas
  • Interrupciones: Detección de eventos
  • PWM: Modulación por ancho de pulso
  • ADC/DAC: Conversión analógica

Pinout y Especificaciones Técnicas

El ESP32 DevKit cuenta con una distribución específica de pines que es crucial conocer para el desarrollo de proyectos mecatrónicos eficientes.

GPIOs Recomendados para Salidas

GPIO Función Aplicación
GPIO 2 LED integrado Indicador de estado
GPIO 4 Uso general Control de relés
GPIO 5 Uso general Control de actuadores
GPIO 18 Uso general PWM para motores
GPIO 19 Uso general Control de servos

GPIOs Recomendados para Entradas

GPIO Característica Aplicación
GPIO 21 Pull-up interno Botones, switches
GPIO 22 Pull-up interno Sensores digitales
GPIO 23 Uso general Encoders
GPIO 25 ADC/DAC Sensores analógicos
GPIO 27 Touch sensor Interfaces táctiles
Importante: Los GPIOs 6-11 están conectados a la memoria flash SPI y no deben utilizarse. Los GPIOs 34-39 son solo de entrada y no tienen pull-up interno.

Configuración y Programación de GPIOs

La configuración correcta de los GPIOs es fundamental para el funcionamiento adecuado de cualquier sistema mecatrónico. A continuación se presentan los métodos principales de configuración:

C++ - Arduino IDE
// Configuración básica de GPIOs en ESP32
#define LED_PIN 2        // GPIO 2 - LED integrado
#define BUTTON_PIN 21    // GPIO 21 - Botón con pull-up interno
#define RELAY_PIN 4      // GPIO 4 - Control de relé
#define SENSOR_PIN 22    // GPIO 22 - Sensor digital

// Variables para el estado del sistema
bool ledState = false;
bool lastButtonState = HIGH;
bool currentButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
    Serial.begin(115200);
    Serial.println("\n=== Sistema de Control GPIO ESP32 ===");
    
    // Configuración de pines de salida
    pinMode(LED_PIN, OUTPUT);           // LED como salida
    pinMode(RELAY_PIN, OUTPUT);         // Relé como salida
    
    // Configuración de pines de entrada
    pinMode(BUTTON_PIN, INPUT_PULLUP);  // Botón con pull-up interno
    pinMode(SENSOR_PIN, INPUT);         // Sensor como entrada
    
    // Estado inicial - todos los actuadores apagados
    digitalWrite(LED_PIN, LOW);
    digitalWrite(RELAY_PIN, LOW);
    
    Serial.println("Configuración de GPIOs completada");
    Serial.println("GPIO 2  (LED): SALIDA");
    Serial.println("GPIO 4  (RELAY): SALIDA");  
    Serial.println("GPIO 21 (BUTTON): ENTRADA + PULL-UP");
    Serial.println("GPIO 22 (SENSOR): ENTRADA");
    Serial.println("Sistema iniciado correctamente\n");
}

void loop() {
    // Lectura del botón con anti-rebote (debounce)
    currentButtonState = digitalRead(BUTTON_PIN);
    
    // Verificar si el estado del botón cambió
    if (currentButtonState != lastButtonState) {
        lastDebounceTime = millis();
    }
    
    // Aplicar anti-rebote
    if ((millis() - lastDebounceTime) > debounceDelay) {
        // Si el estado es estable y diferente al anterior
        if (currentButtonState != lastButtonState) {
            lastButtonState = currentButtonState;
            
            // Detectar flanco descendente (botón presionado)
            if (currentButtonState == LOW) {
                ledState = !ledState;  // Alternar estado del LED
                digitalWrite(LED_PIN, ledState);
                
                Serial.printf("Botón presionado - LED %s\n", 
                            ledState ? "ENCENDIDO" : "APAGADO");
            }
        }
    }
    
    // Lectura del sensor digital
    bool sensorState = digitalRead(SENSOR_PIN);
    
    // Control del relé basado en el sensor
    static bool lastSensorState = HIGH;
    if (sensorState != lastSensorState) {
        digitalWrite(RELAY_PIN, !sensorState);  // Relé activo en bajo
        
        Serial.printf("Sensor: %s - Relé: %s\n",
                     sensorState ? "ACTIVO" : "INACTIVO",
                     !sensorState ? "ENCENDIDO" : "APAGADO");
        
        lastSensorState = sensorState;
    }
    
    // Mostrar estado del sistema cada 2 segundos
    static unsigned long lastReport = 0;
    if (millis() - lastReport > 2000) {
        Serial.println("=== Estado del Sistema ===");
        Serial.printf("LED (GPIO %d): %s\n", LED_PIN, 
                     digitalRead(LED_PIN) ? "ON" : "OFF");
        Serial.printf("Botón (GPIO %d): %s\n", BUTTON_PIN, 
                     digitalRead(BUTTON_PIN) ? "LIBRE" : "PRESIONADO");
        Serial.printf("Sensor (GPIO %d): %s\n", SENSOR_PIN, 
                     digitalRead(SENSOR_PIN) ? "DETECTADO" : "LIBRE");
        Serial.printf("Relé (GPIO %d): %s\n", RELAY_PIN, 
                     digitalRead(RELAY_PIN) ? "ACTIVO" : "INACTIVO");
        Serial.println("========================\n");
        
        lastReport = millis();
    }
    
    delay(10);  // Pequeña pausa para estabilidad
}

Ejercicios Prácticos

1

Control Básico LED-Botón

Principiante 20 min Hardware

Objetivo: Implementar un sistema básico de control donde un botón físico controle el estado de un LED.

Materiales necesarios:

  • ESP32 DevKit
  • LED de 5mm
  • Resistencia de 220Ω
  • Pulsador normalmente abierto
  • Resistencia de 10kΩ (pull-up externa opcional)
  • Protoboard y cables

Conexiones: LED en GPIO2, botón en GPIO21 con pull-up interno

2

Semáforo Inteligente

Intermedio 35 min Lógica

Objetivo: Crear un semáforo automatizado con tres LEDs que simule el comportamiento real de un semáforo urbano.

Funcionalidades:

  • Secuencia automática: Verde → Amarillo → Rojo
  • Tiempos configurables para cada color
  • Botón de emergencia para cambiar a modo manual
  • Indicador de estado por Serial Monitor

Aplicación: Control de tráfico, sistemas de seguridad industrial

3

Sistema Multi-Sensor

Avanzado 50 min IoT

Objetivo: Desarrollar un sistema de monitoreo que lea múltiples sensores digitales y controle actuadores basados en lógica condicional.

Características:

  • 4 entradas digitales para sensores
  • 4 salidas para actuadores (LEDs, relés)
  • Lógica de control programable
  • Dashboard web para monitoreo remoto
  • Registro de eventos en memoria

Aplicación: Automatización industrial, domótica

Aplicaciones en Mecatrónica Industrial

Sistemas de Control Digital

Los GPIOs del ESP32 son fundamentales en aplicaciones industriales donde se requiere control preciso y monitoreo en tiempo real de procesos mecatrónicos.

Control de Actuadores:
  • Relés de potencia - Control de motores grandes
  • Solenoides - Válvulas neumáticas/hidráulicas
  • Indicadores LED - Estado de procesos
  • Alarmas audibles - Notificaciones críticas
Lectura de Sensores:
  • Sensores de proximidad - Detección de objetos
  • Finales de carrera - Límites de movimiento
  • Sensores de seguridad - Paradas de emergencia
  • Encoders incrementales - Posición y velocidad
Casos de Uso Específicos
Control de Banda Transportadora
Sensores de posición y control de velocidad variable
Brazo Robótico
Control de servos y lectura de finales de carrera
Sistema de Climatización
Control automático basado en sensores ambientales

Troubleshooting y Buenas Prácticas

Problemas Comunes

GPIO no responde

Causas: Pin no configurado, conexiones incorrectas, pin reservado para flash

Solución: Verificar configuración pinMode(), revisar conexiones físicas, evitar GPIOs 6-11

Lecturas inestables

Causas: Ruido eléctrico, falta de pull-up/pull-down, cables largos

Solución: Usar resistencias pull-up/down, condensadores de filtro, cables cortos

Debounce de botones

Problema: Múltiples lecturas en una sola pulsación

Solución: Implementar delay o filtro temporal de 50-100ms

Buenas Prácticas

Configuración Segura
  • Definir pines como constantes (#define)
  • Configurar todos los pines en setup()
  • Usar pull-up interno cuando sea posible
  • Verificar voltajes de operación (3.3V)
Programación Eficiente
  • Evitar delay() largos en loop()
  • Usar millis() para temporizaciones
  • Implementar máquinas de estado
  • Comentar el código adecuadamente

Referencias y Recursos Adicionales