Módulo 12

Conectividad Wi-Fi/Bluetooth completa

Proyecto Final Integral

ESP32 Mecatrónica IoT UNAM

Introducción Teórica

En la era de la Internet de las Cosas (IoT), la conectividad Wi-Fi y Bluetooth desempeñan un papel fundamental. La ESP32, una serie de microcontroladores de bajo costo con Wi-Fi y Bluetooth integrados, ha revolucionado el mundo de la mecatrónica e IoT, proporcionando una solución todo en uno para diversas aplicaciones.

En el campo de la mecatrónica, la ESP32 puede utilizarse para controlar y monitorizar sistemas de forma remota, realizar actualizaciones OTA, recopilar datos de sensores y tomar decisiones basadas en esos datos. En la industria, se utiliza en aplicaciones desde automatización de procesos hasta control de calidad, telemetría y seguridad.

Explicación Técnica Detallada

La ESP32 es una serie de microcontroladores de 32 bits con una CPU dual-core que puede funcionar a frecuencias de hasta 240 MHz. Posee una amplia gama de periféricos incluyendo Wi-Fi, Bluetooth y varias interfaces de E/S.

Configuración Wi-Fi

Para configurar la ESP32 para Wi-Fi, se utilizan las bibliotecas:

  • WiFi.h - Biblioteca principal
  • ESPAsync_WiFiManager - Gestión avanzada

Permite configurar como estación (STA), punto de acceso (AP) o ambas.

Configuración Bluetooth

Para configurar Bluetooth se utiliza:

  • BluetoothSerial.h - Bluetooth clásico
  • BLEDevice.h - Bluetooth Low Energy

Comunicación usando Serial Port Profile (SPP).

Ejemplo básico Wi-Fi
#include 

const char* ssid = "tu_red_wifi";
const char* password = "tu_password";

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    // Inicializar conexión Wi-Fi
    WiFi.begin(ssid, password);
    Serial.print("Conectando a WiFi");
    
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println();
    Serial.println("¡WiFi conectado!");
    Serial.print("Dirección IP: ");
    Serial.println(WiFi.localIP());
    Serial.print("RSSI: ");
    Serial.println(WiFi.RSSI());
}

void loop() {
    // Verificar conexión
    if(WiFi.status() != WL_CONNECTED) {
        Serial.println("Conexión perdida, reconectando...");
        WiFi.reconnect();
    }
    delay(10000);
}

Ejercicios Prácticos Visuales

1

Conexión Wi-Fi Básica

Básico 15 min

Objetivo: Configurar la ESP32 para conectarse a una red Wi-Fi y mostrar información de conexión.

Materiales:

  • ESP32 DevKit
  • Cable USB
  • Arduino IDE configurado
Código Completo:
WiFi Connection
#include 

const char* ssid = "MI_RED_WIFI";
const char* password = "MI_PASSWORD";

void setup() {
    Serial.begin(115200);
    
    WiFi.begin(ssid, password);
    
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Conectando a WiFi...");
    }
    
    Serial.println("Conectado!");
    Serial.println(WiFi.localIP());
}

void loop() {
    Serial.println("Estado: Conectado");
    delay(5000);
}
2

Comunicación Bluetooth

Intermedio 20 min

Objetivo: Configurar ESP32 para comunicación Bluetooth con dispositivo móvil.

Materiales:

  • ESP32 DevKit
  • Smartphone con Bluetooth
  • App terminal Bluetooth
Código Bluetooth Serial:
Bluetooth Classic
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {
    Serial.begin(115200);
    SerialBT.begin("ESP32-Mecatronica"); // Nombre Bluetooth
    Serial.println("El dispositivo está listo para emparejar");
}

void loop() {
    if (Serial.available()) {
        SerialBT.write(Serial.read());
    }
    if (SerialBT.available()) {
        Serial.write(SerialBT.read());
    }
    delay(20);
}
3

Control LED por Wi-Fi

Avanzado 35 min

Objetivo: Crear servidor web para controlar LED mediante interfaz web.

Materiales:

  • ESP32 DevKit
  • LED + Resistencia 220Ω
  • Protoboard y cables
Conexiones:
  • LED Ánodo → GPIO 2 (ESP32)
  • LED Cátodo → GND (a través de resistencia)
Código Servidor Web:
Web Server Control
#include 
#include 

const char* ssid = "TU_WIFI";
const char* password = "TU_PASSWORD";

WebServer server(80);
const int ledPin = 2;

void setup() {
    Serial.begin(115200);
    pinMode(ledPin, OUTPUT);
    
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Conectando...");
    }
    
    Serial.println(WiFi.localIP());
    
    server.on("/", handleRoot);
    server.on("/led/on", [](){
        digitalWrite(ledPin, HIGH);
        server.send(200, "text/plain", "LED Encendido");
    });
    server.on("/led/off", [](){
        digitalWrite(ledPin, LOW);
        server.send(200, "text/plain", "LED Apagado");
    });
    
    server.begin();
}

void handleRoot() {
    String html = "

Control LED ESP32

"; html += ""; html += ""; server.send(200, "text/html", html); } void loop() { server.handleClient(); }

Proyecto Aplicado Integral

Sistema de Riego Automatizado IoT

Desarrolla un sistema completo que combine Wi-Fi y Bluetooth para monitorear y controlar un sistema de riego inteligente.

Lista de Materiales:

  • ESP32 DevKit v1
  • Sensor de humedad del suelo
  • Válvula solenoide 12V
  • Relé 5V
  • Bomba de agua 12V
  • Display LCD 16x2 I2C
  • Fuente 12V/2A
  • Resistencias y cables
  • Caja protectora
  • Tubería y conectores
Código Proyecto Completo
#include 
#include 
#include 
#include 
#include 

// Configuración de red
const char* ssid = "RED_RIEGO";
const char* password = "password123";

// Objetos
WebServer server(80);
BluetoothSerial SerialBT;
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Pines
const int sensorPin = A0;    // Sensor humedad
const int relayPin = 2;      // Control bomba
const int ledPin = 4;        // LED estado

// Variables
int humedad = 0;
int umbralHumedad = 30;      // Porcentaje mínimo
bool riegoAutomatico = true;
bool bombaActiva = false;

void setup() {
    Serial.begin(115200);
    
    // Inicializar pines
    pinMode(relayPin, OUTPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(sensorPin, INPUT);
    
    // Inicializar LCD
    lcd.init();
    lcd.backlight();
    lcd.setCursor(0, 0);
    lcd.print("Sistema Riego");
    lcd.setCursor(0, 1);
    lcd.print("Iniciando...");
    
    // Conectar WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Conectando WiFi...");
    }
    
    // Inicializar Bluetooth
    SerialBT.begin("RiegoESP32");
    
    // Configurar servidor web
    setupWebServer();
    server.begin();
    
    Serial.println("Sistema iniciado");
    Serial.print("IP: ");
    Serial.println(WiFi.localIP());
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("IP: ");
    lcd.print(WiFi.localIP().toString().substring(10));
}

void loop() {
    // Leer sensor de humedad
    leerSensor();
    
    // Control automático
    if (riegoAutomatico) {
        controlAutomatico();
    }
    
    // Manejar comunicaciones
    server.handleClient();
    manejarBluetooth();
    
    // Actualizar display
    actualizarLCD();
    
    delay(1000);
}

void leerSensor() {
    int lectura = analogRead(sensorPin);
    humedad = map(lectura, 0, 4095, 100, 0); // Invertir escala
    
    // Enviar datos por Bluetooth
    if (SerialBT.hasClient()) {
        StaticJsonDocument<200> doc;
        doc["humedad"] = humedad;
        doc["bomba"] = bombaActiva;
        doc["automatico"] = riegoAutomatico;
        
        String jsonString;
        serializeJson(doc, jsonString);
        SerialBT.println(jsonString);
    }
}

void controlAutomatico() {
    if (humedad < umbralHumedad && !bombaActiva) {
        activarBomba();
    } else if (humedad > (umbralHumedad + 10) && bombaActiva) {
        desactivarBomba();
    }
}

void activarBomba() {
    digitalWrite(relayPin, HIGH);
    digitalWrite(ledPin, HIGH);
    bombaActiva = true;
    Serial.println("Bomba ACTIVADA");
}

void desactivarBomba() {
    digitalWrite(relayPin, LOW);
    digitalWrite(ledPin, LOW);
    bombaActiva = false;
    Serial.println("Bomba DESACTIVADA");
}

void setupWebServer() {
    server.on("/", []() {
        String html = generarHTML();
        server.send(200, "text/html", html);
    });
    
    server.on("/api/status", []() {
        StaticJsonDocument<200> doc;
        doc["humedad"] = humedad;
        doc["bomba"] = bombaActiva;
        doc["automatico"] = riegoAutomatico;
        doc["umbral"] = umbralHumedad;
        
        String response;
        serializeJson(doc, response);
        server.send(200, "application/json", response);
    });
    
    server.on("/bomba/on", []() {
        if (!riegoAutomatico) {
            activarBomba();
            server.send(200, "text/plain", "Bomba activada");
        } else {
            server.send(400, "text/plain", "Modo automático activo");
        }
    });
    
    server.on("/bomba/off", []() {
        desactivarBomba();
        server.send(200, "text/plain", "Bomba desactivada");
    });
    
    server.on("/modo/auto", []() {
        riegoAutomatico = true;
        server.send(200, "text/plain", "Modo automático");
    });
    
    server.on("/modo/manual", []() {
        riegoAutomatico = false;
        server.send(200, "text/plain", "Modo manual");
    });
}

void manejarBluetooth() {
    if (SerialBT.available()) {
        String comando = SerialBT.readString();
        comando.trim();
        
        if (comando == "STATUS") {
            SerialBT.printf("Humedad: %d%%, Bomba: %s\n", 
                           humedad, bombaActiva ? "ON" : "OFF");
        } else if (comando == "BOMBA_ON" && !riegoAutomatico) {
            activarBomba();
            SerialBT.println("Bomba activada");
        } else if (comando == "BOMBA_OFF") {
            desactivarBomba();
            SerialBT.println("Bomba desactivada");
        } else if (comando == "AUTO") {
            riegoAutomatico = true;
            SerialBT.println("Modo automático");
        } else if (comando == "MANUAL") {
            riegoAutomatico = false;
            SerialBT.println("Modo manual");
        }
    }
}

void actualizarLCD() {
    lcd.setCursor(0, 1);
    lcd.printf("H:%d%% %s %s", humedad, 
               bombaActiva ? "ON " : "OFF",
               riegoAutomatico ? "A" : "M");
}

String generarHTML() {
    return R"===(


    Sistema Riego IoT
    
    


    

🌱 Sistema de Riego Automático

💧 Humedad: )===" + String(humedad) + R"===(%
🚰 Bomba: )===" + (bombaActiva ? "ENCENDIDA" : "APAGADA") + R"===(
⚙️ Modo: )===" + (riegoAutomatico ? "AUTOMÁTICO" : "MANUAL") + R"===(

Control Manual


)===" ; }

Evaluación y Troubleshooting

Problemas Comunes

  • No conecta Wi-Fi: Verificar SSID y password
  • Bluetooth no empareja: Reiniciar ESP32 y dispositivo
  • Servidor web no responde: Verificar firewall
  • Sensor erróneo: Calibrar valores ADC

Criterios de Evaluación

  • Conexión estable Wi-Fi y Bluetooth
  • Interfaz web funcional
  • Control remoto por Bluetooth
  • Lectura precisa de sensores
  • Automatización correcta