Arquitectura del Sketch Básico
Arquitectura del Sketch Básico
Descripción General
Sección titulada «Descripción General»Esta sección presenta la arquitectura completa del “Sketch Básico” que combina conexión Wi-Fi, comunicación MQTT y temporización no bloqueante. Al finalizar esta sección, podrás:
- Entender la estructura de proyecto multi-archivo de un sketch ESP32 en PlatformIO
- Implementar el sketch básico canónico de Wi-Fi + MQTT que sirve como base para todos los proyectos del curso
- Organizar el código ESP32 en módulos funcionales (Wi-Fi, MQTT, sensores, main)
Requisitos Previos
Sección titulada «Requisitos Previos»- Implementación de conexión Wi-Fi (01-09)
- Configuración del cliente MQTT (01-10)
- Configuración del IDE PlatformIO (01-05)
Conceptos Clave
Sección titulada «Conceptos Clave»La Arquitectura del Sketch Básico
Sección titulada «La Arquitectura del Sketch Básico»Todos los proyectos IoT de este curso siguen el mismo patrón arquitectónico:
┌──────────────────────────────────────────────────┐│ main.cpp ││ setup() → init serial → conectar WiFi → ││ init MQTT → init sensores ││ loop() → mantener MQTT → leer sensores → ││ publicar datos → retardos no bloqueantes│└──────────────────────────────────────────────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼┌─────────────────┐ ┌──────────┐ ┌──────────────┐│ wifi_mqtt.h │ │credentials.h│ │ sensor.h ││ - Conectar WiFi │ │ - SSID │ │ - leer datos ││ - Callback MQTT │ │ - Contraseña│ │ - procesar ││ - Reconexión │ │ - Broker │ │ - formatear │└─────────────────┘ └──────────┘ └──────────────┘Esta separación de responsabilidades significa:
- El código Wi-Fi/MQTT es reutilizable entre proyectos
- Las credenciales están aisladas en un solo archivo (excluido del control de versiones)
- La lógica de sensores es modular e intercambiable
- main.cpp es el orquestador, no la implementación
Estructura de Archivos (PlatformIO)
Sección titulada «Estructura de Archivos (PlatformIO)»basic-sketch/ ├── platformio.ini # Placa, framework, librerías └── src/ ├── main.cpp # Orquestación de setup() y loop() ├── wifi_mqtt.h # Funciones de conexión Wi-Fi y MQTT └── credentials.h # SSID, contraseña, dirección del brokerPasos de Implementación
Sección titulada «Pasos de Implementación»Paso 1: Crear el Proyecto
Sección titulada «Paso 1: Crear el Proyecto»- Crea un nuevo proyecto PlatformIO:
esp32-basic-sketch - Placa:
Espressif ESP32 Dev Module - Framework:
Arduino - Agrega a
platformio.ini:
[env:esp32dev]platform = espressif32board = esp32devframework = arduinomonitor_speed = 115200upload_speed = 921600
lib_deps = knolleary/PubSubClient @ ^2.8 bblanchon/ArduinoJson @ ^7.0Paso 2: Crear credentials.h
Sección titulada «Paso 2: Crear credentials.h»#ifndef CREDENTIALS_H#define CREDENTIALS_H
// Wi-Ficonst char* ssid = "YourWiFiSSID";const char* password = "YourWiFiPassword";
// Broker MQTTconst char* mqttServer = "192.168.1.100";const int mqttPort = 1883;const char* mqttUser = ""; // Dejar vacío si no hay autenticaciónconst char* mqttPassword = "";
#endifPaso 3: Crear wifi_mqtt.h
Sección titulada «Paso 3: Crear wifi_mqtt.h»#ifndef WIFI_MQTT_H#define WIFI_MQTT_H
#include <Arduino.h>#include <WiFi.h>#include <PubSubClient.h>
// Declaraciones anticipadasvoid connectToWiFi();void connectToMQTT();void mqttCallback(char* topic, byte* payload, unsigned int length);void sendMQTTValues();
// Objetos de cliente Wi-Fi y cliente MQTTWiFiClient wifiClient;PubSubClient mqttClient(wifiClient);
// Identificador del clienteconst char* clientId = "esp32-basic";
// Topics MQTTconst char* topicPublish = "esp32/data";const char* topicSubscribe = "esp32/commands";
void connectToWiFi() { Serial.print("Connecting to Wi-Fi"); WiFi.begin(ssid, password);
int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 40) { delay(500); Serial.print("."); attempts++; }
if (WiFi.status() == WL_CONNECTED) { Serial.println(); Serial.println("Wi-Fi connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } else { Serial.println(); Serial.println("Wi-Fi connection failed!"); Serial.println("Restarting in 2 seconds..."); delay(2000); ESP.restart(); }}
void mqttCallback(char* topic, byte* payload, unsigned int length) { Serial.print("MQTT message arrived ["); Serial.print(topic); Serial.print("]: ");
String message = ""; for (unsigned int i = 0; i < length; i++) { message += (char)payload[i]; } Serial.println(message);
// Enrutamiento por topic if (String(topic) == "esp32/commands") { if (message == "ON") { Serial.println("Command: ON"); // Agrega tu lógica de ON aquí } else if (message == "OFF") { Serial.println("Command: OFF"); // Agrega tu lógica de OFF aquí } }}
void connectToMQTT() { mqttClient.setServer(mqttServer, mqttPort); mqttClient.setCallback(mqttCallback);
while (!mqttClient.connected()) { Serial.print("Attempting MQTT connection...");
if (mqttClient.connect(clientId, mqttUser, mqttPassword)) { Serial.println("connected!");
// Suscribirse a los topics mqttClient.subscribe(topicSubscribe);
// Publicar estado en línea mqttClient.publish("esp32/status", "online"); } else { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" retrying in 5 seconds"); delay(5000); } }}
#endifPaso 4: Crear main.cpp
Sección titulada «Paso 4: Crear main.cpp»#include <Arduino.h>#include "credentials.h"#include "wifi_mqtt.h"
// Constantesconst unsigned long PUBLISH_INTERVAL = 5000; // Publicar cada 5 segundosconst int LED_PIN = 2; // LED integrado en la mayoría de los DevKits
// Variables globalesunsigned long previousMillis = 0;int ledState = LOW;
void setup() { Serial.begin(115200); delay(1000);
Serial.println("ESP32 Basic Sketch"); Serial.println("=================");
// Inicializar hardware pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW);
// Conectar a Wi-Fi connectToWiFi();
// Conectar a MQTT connectToMQTT();}
void loop() { unsigned long currentMillis = millis();
// 1. Mantener la conexión MQTT (debe llamarse con frecuencia) if (!mqttClient.connected()) { // Verificar Wi-Fi primero if (WiFi.status() != WL_CONNECTED) { connectToWiFi(); } connectToMQTT(); } mqttClient.loop();
// 2. Parpadeo de LED no bloqueante (indicador de estado) digitalWrite(LED_PIN, ledState);
// 3. Publicación periódica de datos if (currentMillis - previousMillis >= PUBLISH_INTERVAL) { previousMillis = currentMillis;
// Alternar el LED en cada publicación ledState = !ledState;
// Publicar datos del sensor sendMQTTValues(); }}
void sendMQTTValues() { // Simular datos del sensor (reemplazar con lecturas reales) int temperature = random(20, 35); int humidity = random(40, 80);
// Crear payload JSON String payload = "{\"temperature\":"; payload += temperature; payload += ",\"humidity\":"; payload += humidity; payload += "}";
// Publicar en el topic MQTT if (mqttClient.publish(topicPublish, payload.c_str())) { Serial.print("Published: "); Serial.println(payload); } else { Serial.println("Publish failed!"); }}Paso 5: Descripción del Flujo Completo
Sección titulada «Paso 5: Descripción del Flujo Completo»- Encendido: El ESP32 inicia y ejecuta
setup() - Inicio Serial: El puerto serial se abre a 115200 baudios
- Inicio del LED: El pin del LED integrado se configura como salida
- Conexión Wi-Fi: Se conecta a la red Wi-Fi (reintenta hasta 40 veces = ~20 segundos)
- Conexión MQTT: Se conecta al broker MQTT y se suscribe al topic de comandos
- Inicio del Loop: Entra al bucle principal
- Mantenimiento MQTT: Llama a
client.loop()para procesar mensajes entrantes y mantener viva la conexión - Verificación del Temporizador: Cada 5 segundos, publica datos simulados del sensor
- Alternancia del LED: El LED integrado se alterna con cada publicación (indicador visual de latido)
Paso 6: Probar el Sketch Completo
Sección titulada «Paso 6: Probar el Sketch Completo»- Carga el sketch en el ESP32
- Abre el Monitor Serial (115200 baudios)
- Observa la secuencia de conexión
- Verifica que los mensajes “Published” aparezcan cada 5 segundos
- Desde una línea de comandos, suscríbete para recibir datos:
Ventana de terminal mosquitto_sub -h 192.168.1.100 -t "esp32/data" - Envía un comando:
Ventana de terminal mosquitto_pub -h 192.168.1.100 -t "esp32/commands" -m "ON"
Verificación
Sección titulada «Verificación»- El Monitor Serial muestra la secuencia completa de conexión (Wi-Fi → MQTT)
- Los datos se publican cada 5 segundos en el topic MQTT correcto
- El LED integrado se alterna con cada publicación (confirmación visual)
- El suscriptor MQTT recibe los payloads JSON correctamente
- El envío de un comando mediante
mosquitto_pubse recibe en el callback - La desconexión y reconexión del broker se recupera automáticamente
Solución de Problemas
Sección titulada «Solución de Problemas»El sketch no inicia, solo aparece “Connecting to Wi-Fi”
Sección titulada «El sketch no inicia, solo aparece “Connecting to Wi-Fi”»Causas: Credenciales Wi-Fi incorrectas o el router no es alcanzable.
Soluciones:
- Verifica el SSID y la contraseña en
credentials.h - Verifica que el router esté encendido y transmitiendo
- Verifica que el ESP32 esté dentro del alcance
- Verifica 2.4 GHz vs 5 GHz: el ESP32 solo soporta 2.4 GHz
MQTT conectado pero no se publican mensajes
Sección titulada «MQTT conectado pero no se publican mensajes»Causas:
- El temporizador del intervalo de publicación no se reinicia
- El cliente MQTT se desconectó sin detección
Soluciones:
- Verifica que
PUBLISH_INTERVALesté configurado a un valor razonable (5000 ms) - Verifica que
mqttClient.connected()devuelva true - Asegúrate de que
mqttClient.loop()se llame en cada iteración - Usa el valor de retorno de
mqttClient.publish()para detectar fallas
El ESP32 se desconecta del Wi-Fi después de algunas horas
Sección titulada «El ESP32 se desconecta del Wi-Fi después de algunas horas»Causas:
- Tiempo de espera del arrendamiento DHCP del router
- Interferencia de radio Wi-Fi
- Problemas de fuente de alimentación
Soluciones:
- Habilita la reconexión automática:
WiFi.setAutoReconnect(true)ensetup() - Agrega una verificación periódica del estado de Wi-Fi en
loop() - Implementa un temporizador de vigilancia (watchdog, integrado en el ESP32) que reinicie si la conexión se pierde por más de 5 minutos
Buenas Prácticas
Sección titulada «Buenas Prácticas»- Comienza cada proyecto nuevo desde este Sketch Básico: Proporciona infraestructura comprobada de Wi-Fi, MQTT y temporización
- Usa la estructura multi-archivo: Separa credenciales, Wi-Fi/MQTT y lógica de sensores en archivos diferentes
- Implementa el patrón no bloqueante: Nunca uses
delay()para temporización en código de producción - Agrega un LED de estado: Un LED de latido (que se alterna en cada publicación de datos) proporciona retroalimentación visual inmediata
- Registra todos los cambios de estado de conexión: Esto ayuda a diagnosticar problemas en campo de forma remota
- Usa
random()o datos ficticios inicialmente: Haz que la capa de comunicación funcione antes de agregar sensores reales
Resumen
Sección titulada «Resumen»- La arquitectura del Sketch Básico separa responsabilidades en
main.cpp,wifi_mqtt.hycredentials.h - La función
loop()mantiene MQTT, verifica temporizadores, publica datos y maneja callbacks - La lógica de reconexión de Wi-Fi y MQTT asegura robustez ante interrupciones de red
- La temporización no bloqueante con
millis()permite múltiples tareas concurrentes - Esta arquitectura es la base de todos los proyectos posteriores del curso
Referencias
Sección titulada «Referencias»
¿Desarrollas un producto IoT comercial?
Ofrecemos servicios ODM de ESP32, del diseño a la fabricación. Del prototipo a la producción: el equipo detrás de este tutorial puede construirlo contigo.
Hablemos →