Construyendo un servidor web simple con M5Stack ATOM S3 y ATOMIC PoE W5500
13 Feb 2025
0 Comentarios
El M5Stack ATOM S3 es una unidad de microcontrolador compacta y versátil, particularmente útil para proyectos de Internet de las Cosas (IoT). Combinarlo con un módulo Ethernet abre un mundo de posibilidades para aplicaciones conectadas a la red. Este artículo proporciona una guía completa para construir un servidor web simple en el M5Stack ATOM S3 utilizando el módulo Ethernet, explicando el código en detalle y explorando posibles mejoras.
Requisitos de Hardware:
-
M5Stack ÁTOMO S3
-
Módulo Ethernet M5Stack (o compatible)
-
Cable USB Tipo-C para programación
-
Cable Ethernet para conexión de red
Requisitos de Software:
-
Arduino IDE (con soporte para placa ESP32)
-
Biblioteca M5Stack para ATOM S3
#include "M5AtomS3.h" #include#include #define SCK 5 #define MISO 7 #define MOSI 8 #define CS 6 byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x99}; // Dirección MAC (a menudo sobrescrita por DHCP) IPAddress ip(192, 168, 1, 177); // Dirección IP estática (no utilizada en este ejemplo habilitado para DHCP) EthernetServer server(80); // Crear un objeto de servidor en el puerto 80 (HTTP) configuración vacía() { configuración automática = M5.config(); AtomS3.begin(cfg); AtomS3.Display.setTextColor(VERDE); AtomS3.Display.setTextDatum(middle_center); AtomS3.Display.setFont(&fonts::Orbitron_Light_24); AtomS3.Display.setTextSize(1); SPI.begin(SCK, MISO, MOSI, -1); // Inicializar la comunicación SPI para Ethernet Ethernet.init(CS); // Inicializa el chip Ethernet con el pin CS AtomS3.Display.drawString("Init...", AtomS3.Display.width() / 2, 60); while (Ethernet.begin(mac) != 1) { // Intentar obtener una dirección IP a través de DHCP Serial.println("Error al obtener la dirección IP a través de DHCP, intentando de nuevo..."); retraso(1000); } // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("No se encontró el escudo Ethernet. Lo siento, no se puede ejecutar sin hardware. :("); mientras (verdadero) { delay(1); // no hacer nada, no tiene sentido ejecutar sin hardware Ethernet } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("El cable Ethernet no está conectado."); } server.begin(); // Iniciar el servidor Serial.print("el servidor está en "); Serial.println(Ethernet.localIP()); // Imprimir la dirección IP asignada AtomS3.Display.setTextSize(0.5); AtomS3.Display.clear(); AtomS3.Display.drawString(Ethernet.localIP().toString().c_str(), AtomS3.Display.width() / 2, 60); // Mostrar IP en la pantalla } bucle vacío() { EthernetClient client = server.available(); // Verificar si hay una nueva conexión de cliente if (cliente) { // Si un cliente está conectado Serial.println("nuevo cliente"); boolean currentLineIsBlank = true; while (client.connected()) { // Mientras el cliente esté conectado if (client.available()) { // Si el cliente ha enviado datos char c = client.read(); // Leer un carácter del cliente Serial.write(c); // Imprimir el carácter en el Monitor Serial if (c == '\n' && currentLineIsBlank) { // Verificar el final de la solicitud HTTP // Send HTTP response client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Conexión: cerrar"); client.println("Refrescar: 5"); // Refrescar la página cada 5 segundos client.println(); // Línea vacía para señalar el final del encabezado cliente.println(""); client.println(""); client.print("¡Hola M5Stack LAN Module!"); cliente.println(""); break; // Salir del bucle while interno (solicitud procesada) } si (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } retraso(1); client.stop(); // Cerrar la conexión del cliente Serial.println("cliente desconectado"); } }
✔ ¡Copiado!
Explicación Detallada:
- Incluye: El código comienza incluyendo las bibliotecas necesarias: M5AtomS3.h para el ATOM S3, SPI.h para la comunicación SPI (utilizada por el módulo Ethernet), y M5_Ethernet.h para la funcionalidad Ethernet.
- Define: Las declaraciones #define definen los pines SPI utilizados por el módulo Ethernet. Estos son cruciales para una comunicación adecuada.
- Dirección MAC: byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x99}; declara una dirección MAC. Aunque está incluida, a menudo es reemplazada por el servidor DHCP cuando el dispositivo se conecta a la red.
- Dirección IP: IPAddress ip(192, 168, 1, 177); define una dirección IP estática. Sin embargo, en este ejemplo, se utiliza DHCP, por lo que esta IP estática no está realmente asignada al dispositivo. Es un marcador de posición.
- Servidor Ethernet: EthernetServer server(80); crea una instancia de la clase EthernetServer, que escucha conexiones entrantes en el puerto 80 (el puerto HTTP estándar).
- función set up():
- auto cfg = M5.config(); AtomS3.begin(cfg);: Inicializa el hardware M5 ATOM S3.
-
Las siguientes líneas configuran la visualización para la salida de texto: estableciendo color, alineación, fuente y tamaño.
-
SPI.begin(SCK, MISO, MOSI, -1); inicializa la comunicación SPI utilizando los pines definidos. El -1 indica que no se gestiona ningún pin de selección de chip específico por la propia biblioteca SPI.
-
Ethernet.init(CS); inicializa el chip Ethernet utilizando el pin de selección de chip (CS) especificado.
-
AtomS3.Display.drawString("Init...", AtomS3.Display.width() / 2, 60); muestra "Init..." en la pantalla del ATOM S3 para indicar que la inicialización está en progreso.
-
El bucle while (Ethernet.begin(mac) != 1) intenta obtener una dirección IP a través de DHCP. Continúa reintentando cada segundo hasta que se recibe una IP válida. Aquí es donde el ATOM S3 obtiene su dirección de red.
-
El código luego verifica si el hardware de Ethernet está presente y si se ha establecido un enlace (conexión por cable). Si no, el programa se detiene. Esto es importante para un funcionamiento robusto.
-
server.begin(); inicia el servidor Ethernet, preparándolo para aceptar conexiones entrantes.
-
La dirección IP asignada (obtenida a través de DHCP) se imprime en el Monitor Serial y se muestra en la pantalla del ATOM S3.
7. bucle()
función:
- EthernetClient client = server.available(); verifica si algún cliente se ha conectado al servidor. server.available() devuelve un objeto EthernetClient si hay un cliente disponible, o null si no lo hay.
- El bloque if (client) se ejecuta si un cliente está conectado.
- boolean currentLineIsBlank = true; es una bandera utilizada para detectar el final de una solicitud HTTP.
- El bucle while (client.connected()) continúa mientras el cliente permanezca conectado.
- if (client.available()) verifica si el cliente ha enviado algún dato.
- char c = client.read(); lee un solo carácter de la solicitud del cliente.
- Serial.write(c); imprime el carácter recibido en el Monitor Serial para depuración.
- El código luego analiza la solicitud HTTP. La condición if (c == '\n' && currentLineIsBlank) verifica el final de la solicitud HTTP. Una línea en blanco (\n\r\n o \n\n) típicamente significa el final de los encabezados.
Si se detecta el final de la solicitud, el servidor envía una respuesta HTTP:
-
HTTP/1.1 200 OK
: Una respuesta HTTP estándar que indica éxito. *Content-Type: text/html
: Especifica que el cuerpo de la respuesta es HTML. *Connection: close
: Informa al cliente que la conexión se cerrará después de que se envíe la respuesta. Este es un enfoque simple; se podrían usar conexiones persistentes para una comunicación más eficiente. *Refresh: 5
: Este encabezado instruye al navegador a refrescar la página cada 5 segundos. Esto crea un efecto dinámico. * Una línea vacía (client.println();
) es crucial; separa los encabezados HTTP del contenido real. * El contenido HTML se envía a continuación:
. Este es el HTML simple que se mostrará en el navegador. *¡Hola M5Stack LAN Module!
break;
sale del bucle internowhile (client.connected())
porque la respuesta ha sido enviada. * El código luego maneja la lógica para detectar el final de la solicitud HTTP.if (c == '\n')
verifica si hay un carácter de nueva línea, indicando el inicio de una nueva línea en la solicitud.currentLineIsBlank
se establece entrue
cuando se encuentra una nueva línea.else if (c != '\r')
verifica si el carácter no es un retorno de carro. Si no es un retorno de carro, significa que hay datos en la línea actual, por lo quecurrentLineIsBlank
se establece enfalse
. Esta lógica detecta efectivamente la línea en blanco que señala el final de los encabezados HTTP. *delay(1);
proporciona un pequeño retraso, permitiendo al navegador tiempo para procesar los datos recibidos. *client.stop();
cierra la conexión con el cliente. *Serial.println("client disconnected");
imprime un mensaje en el Monitor Serial indicando que el cliente se ha desconectado.
Mejoras y Desarrollo Adicional:
-
Contenido Dinámico: El HTML actual es estático. Puedes generar contenido dinámico utilizando variables y lógica dentro de tu código de Arduino. Por ejemplo, podrías mostrar lecturas de sensores, controlar actuadores o mostrar la hora actual.
-
Manejo de Diferentes Solicitudes: El código actualmente responde a cualquier solicitud con el mismo HTML. Puedes implementar lógica para manejar diferentes métodos HTTP (GET, POST, etc.) y diferentes URLs, lo que te permitirá crear una interfaz web más compleja.
-
HTML Formularios y Entrada de Usuario: Agrega formularios HTML a tu página web para permitir que los usuarios ingresen datos. Luego puedes procesar estos datos en el ATOM S3 y usarlos para controlar tus dispositivos.
-
WebSockets: Para la comunicación en tiempo real, considera usar WebSockets en lugar de HTTP. WebSockets permiten la comunicación bidireccional entre el cliente y el servidor, lo cual es esencial para aplicaciones interactivas.
-
Seguridad: Para entornos de producción, la seguridad es crucial. Implementa mecanismos de autenticación y autorización para proteger tu dispositivo y datos.
-
Sistema de Archivos Integración: Almacene archivos HTML, CSS y JavaScript en una tarjeta SD o memoria flash y sírvalos desde el ATOM S3. Esto le permite crear interfaces web más sofisticadas.
-
AJAX y JavaScript: Utiliza AJAX (JavaScript y XML Asincrónicos) para actualizar partes de la página web dinámicamente sin requerir una recarga completa de la página. Esto mejora la experiencia del usuario.
-
mDNS (DNS Multicast): Utiliza mDNS para darle a tu ATOM S3 un nombre legible por humanos en la red local, facilitando su acceso.
-
Manejo de Errores: Implementar un manejo de errores robusto para gestionar de manera adecuada situaciones como desconexiones de red o entradas de usuario inválidas.
-
OTA (Actualizaciones por aire): Implementa actualizaciones OTA para permitirte actualizar el firmware de tu ATOM S3 de forma remota.
Solución de problemas:
-
No IP Dirección: Verifique su conexión de red, asegúrese de que DHCP esté habilitado en su enrutador y verifique que el módulo Ethernet esté correctamente conectado al ATOM S3.
-
No se puede conectar: Verifique la dirección IP del ATOM S3, asegúrese de que esté en la misma red que su computadora y verifique que no haya cortafuegos bloqueando la conexión.
-
Problemas con el Monitor Serial: Asegúrate de que la velocidad en baudios en el Monitor Serial coincida con la velocidad en baudios utilizada en tu código (generalmente 115200).
Esta explicación ampliada proporciona una comprensión más completa del código y ofrece un punto de partida para desarrollar aplicaciones de servidor web más avanzadas en el M5Stack ATOM S3. Recuerda consultar la documentación de M5Stack y otros recursos en línea para obtener información y ejemplos más detallados.
Serie ATOM: Controladores Compactos y Versátiles
Etiquetas:
Deja un comentario
Todos los comentarios del blog se revisan antes de publicarlos.