Aquí puedes acceder a la primera parte de Ethernet Shield con Arduino.
En el artículo de hoy veras otra aplicación de la tarjeta de expansión ethernet para Arduino o también conocida como Ethernet Shield.
Recuerda que estas placas son un aditivo para nuestro microcontrolador. Tiene una similitud a las mejoras o complementos para una computadora de escritorio.
Precisamente este artículo trata sobre el control de varios LEDs mediante un servidor web basado en Arduino utilizando el Ethernet Shield.
Te aseguro que al terminar estas líneas, tendrás nociones sobre:
- Protocolo HTTP.
- Principales tipos de mensajes HTTP.
- Interpretar peticiones HTTP.
- Por último, veras cómo armar tu propio servidor web para control de LEDs.
Si quieres partir de la base con un ejemplo mas sencillo, te comento que tienes el artículo anterior donde puedes montar un servidor web en Arduino con Ethernet Shield.
Allí se muestra como implementar un monitor de temperatura y humedad. Utiliza el navegador del móvil o del ordenador y permite conocer parámetros útiles de forma simple y rápida.
También se muestran las bases para el control del Ethernet Shield y el uso de la librería Ethernet que serán útiles a la hora de equipar servidores en Arduino.
Si no tienes conocimientos sobre HTML puedes revisar el artículo de introducción a HTML5 donde se muestran los principios fundamentales de este lenguaje.
Bueno, sin más vacilación, se levanta el telón :)

Indice de contenidos
¿Qué es HTTP?
El Protocolo de transferencia de hipertexto (en inglés, Hypertext Transfer Protocol o HTTP) es el protocolo de comunicación que permite las transferencias de información en la World Wide Web.
Cuidado, no confundir HTTP y HTML.
HTML se trata del lenguaje con el que se define el contenido de las páginas web, mientras que HTTP es el que hace posible la comunicación entre navegadores y servidores.
En realidad, la mayoría de los servidores utilizan HTTPS, que es la versión segura de HTTP. La principal diferencia entre estos radica en que en HTTPS los datos se envían encriptados.
HTTP es un protocolo orientado a transacciones y sigue el esquema petición-respuesta entre un cliente y un servidor.
Por ejemplo:
Supón que necesitas información sobre Arduino UNO y decides revisar en internet. De seguro abres tu navegador, te diriges al buscador de Google, escribes algo como “programar Arduino UNO” y presionas la tecla ENTER.

En ese momento tu navegador realiza una petición enviando un mensaje al servidor de Google. Ese mensaje lleva las palabras claves que escribiste en el buscador.
El servidor, por su parte, toma el mensaje recibido y envía una respuesta con los datos solicitados. En este caso serían los resultados de la búsqueda realizada.

Todo este proceso de comunicación se realiza utilizando el protocolo HTTP.
El navegador por su parte recibe el mensaje y te muestra la información solicitada de forma visual.
Mensajes HTTP
Como comente anteriormente, HTTP se basa en el envío de mensajes. Esos mensajes son en texto plano, eso significa que son fáciles de leer e interpretar. Un mensaje HTTP está compuesto por varias líneas, como si fuera un archivo de texto.
Existen dos tipos de mensajes HTTP:
- Petición: mensajes enviados por los clientes al servidor.
- Respuesta: mensajes enviados por el servidor a los clientes en respuesta a una petición.
En la siguiente imagen se muestra la estructura de ambos tipos de mensajes, donde cada fila representa una línea de texto plano.

Petición HTTP
En la primera línea de un mensaje de petición se encuentran los campos para:
- Método de petición: es una palabra que identifica la acción requerida por el servidor.
- Recurso: es el recurso del sitio web sobre el que se desea operar. Puede ser una página web, una imagen u otro archivo.
- Versión HTTP: es la versión HTTP soportada por el cliente.
Existen una serie de métodos de petición que pueden utilizarse. Cada uno de ellos indica la acción a realizar sobre el recurso indicado. Los métodos más conocidos son GET y POST.
El método GET permite solicitar un recurso. Por ejemplo, cuando ingresas a una página web o intentas abrir una imagen de un sitio el navegador realiza peticiones GET.
El método POST permite enviar datos para que sean procesados por el servidor. Por ejemplo, cuando rellenas un formulario en un sitio web y presionas en el botón “enviar” el navegador realiza una petición POST para enviar tus datos.
Respuesta HTTP
En caso de ser un mensaje de respuesta la primera línea cuenta con:
- Versión HTTP: versión HTTP soportada por el cliente.
- Código de respuesta: un número que envía el servidor al cliente indicando el resultado de su petición.
- Frase: una frase asociada al código de respuesta.
A partir de la segunda línea ambos tipos de mensajes tienen la misma estructura.
Cabeceras HTTP o head HTTP
En la segunda línea comienzan las cabeceras, una por cada línea. Cada una se compone por un nombre de cabecera seguido de dos puntos (:), un espacio en blanco y el valor. Una línea en blanco es utilizada para indicar el final de las cabeceras.
Las cabeceras más comunes son:
- Host: indica el servidor al que va dirigida la petición.
- User-Agent: describe al cliente que realiza la petición.
- Content-Length: indica la longitud del cuerpo del mensaje.
- Accept-Language: indica el idioma aceptado.
- Content-Type: tipo de contenido presente en el cuerpo del mensaje
Por último está el cuerpo del mensaje. Este campo es opcional y típicamente contiene los datos que se intercambian entre el cliente y el servidor. Puede ser un archivo de texto, una página web, una imagen u otro tipo de recurso.
Ejemplo de comunicación HTTP
Para comprender como ocurre el intercambio de información entre cliente y servidor utilizando el protocolo HTTP veras algunos ejemplos.
Primer ejemplo de petición HTTP
El cliente inicia la comunicación con una petición HTTP tipo GET.
1 2 3 4 5 6 7 |
GET /index.html HTTP/1.1 Host: www.algunsitioweb.com User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0 Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive |
Simplemente observando el mensaje podemos obtener la siguiente información:
- Se trata de una petición GET del recurso /index.html
- Utiliza la versión 1.1 de HTTP.
- La petición se realiza al servidor www.algunsitioweb.com
- Se hace desde un ordenador con sistema operativo Ubuntu
- Utiliza el navegador web Mozilla.
Todo esto nos indica que la petición fue realizada escribiendo “www.algunsitioweb.com/index.html” en la barra de direcciones del navegador.
Puedes obtener mucha más información analizando todas las cabeceras, aquí solo he destacado algunas.
Primer ejemplo respuesta HTTP
Una posible respuesta del servidor a esa petición sería:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
HTTP/1.1 200 OK Date: Fri, 6 Nov 2020 20:52:37 GMT Content-Type: text/html Content-Length: 95 Connection: close <html> <head> <title>Título del sitio</title> </head> <body> <h1>Página principal</h1> </body> </html> |
- El mensaje de respuesta utiliza la versión 1.1 de HTTP
- Retorna el código 200 (este código indica que la operación se realizó satisfactoriamente).
- Las cabeceras indican la fecha en el servidor (Date); que el cuerpo del mensaje contiene información HTML (Content-Type); y que la longitud del mismo es de 33 bytes (Content-Length).
- Después de la línea en blanco (en el cuerpo del mensaje) se encuentra el recurso solicitado, es decir, el contenido de la página web.
Segundo ejemplo «petición HTTP tipo POST«
1 2 3 4 5 6 7 8 9 10 11 12 13 |
POST / HTTP/1.1 Host: 192.168.1.125 Connection: keep-alive Content-Length: 7 Origin: http://192.168.1.125 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Referer: http://192.168.1.125/ Accept-Encoding: gzip, deflate Accept-Language: es-US,es-419;q=0.9,es;q=0.8 MOTOR=0 |
- Se trata de una petición tipo POST al recurso “/”
- Utiliza la versión 1.1 del protocolo HTTP.
- La petición va destinada al servidor 192.168.1.125 y contiene un mensaje de 7 bytes.
- La petición fue realizada desde un ordenador con sistema operativo Ubuntu
- Utiliza el navegador web Chrome.
- El cuerpo del mensaje se encuentra después de la línea, en blanco (MOTOR=0).
Es responsabilidad del servidor interpretar el mensaje enviado por el cliente, es decir, el servidor es quien decide la acción a realizar. Por ejemplo, en este caso podría ser un mensaje indicando apagar un motor de DC.
Segundo ejemplo respuesta HTTP
La respuesta del servidor dependerá de la interpretación realizada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
HTTP/1.1 200 OK Date: Fri, 31 Dec 2003 23:59:59 GMT Content-Type: text/html Content-Length: 97 <html> <head> <title>Operación realizada</title> </head> <body> <h1>Motor detenido </h1> </body> </html> |
En este caso la respuesta es similar al ejemplo anterior, solo que más simple.
Diferencias entre GET y POST
La principal diferencia entre las peticiones de tipo GET y POST es que cuando realizas una petición GET la información viaja en la URL. Es decir, que el recurso solicitado se especifica en la barra de direcciones.
Por otra parte, cuando se realizan peticiones POST la información viaja en el cuerpo del mensaje. En otras palabras, no se muestran los datos enviados en la barra de direcciones del navegador. Esta diferencia es la que implica el hecho de que GET se utilice para acceder a los recursos y POST para modificarlos.
Veamos ahora como utilizar lo aprendido en un ejemplo práctico.
Control de LEDs con servidor web en Arduino y Ethernet Shield
En este ejemplo veras cómo implementar un servidor web en Arduino que permita controlar un grupo de LEDs.
Puedes reemplazar los LEDs con relés y controlar las luces del portal o el sistema de riego del jardín.
Para este proyecto necesitarás:
- 1x Router *
- 1x Ordenador
- 2x Cables de red (cables ethernet)
- 1x Arduino Mega **
- 1x Shield Ethernet
- 5x Resistencias de 1 kΩ
- 5x LEDs (no importan los colores)
- 1x placa de prototipos
- Cables para conexiones
* Puede ser cualquier router, aunque si es uno con Wifi integrada mucho mejor.
** Si no dispones de un Arduino MEGA puedes utilizar un Arduino UNO sin problemas
Circuito eléctrico con Arduino y Ethernet Shield
Lo primero que debes hacer es conectar el Ethernet shield y Arduino. Al tratarse de un módulo tipo shield esta tarea se simplifica enormemente, ya que solo es necesario hacer coincidir los pines del Arduino con los del módulo.
Te recuerdo que hay una primera parte sobre teoría y ejemplos básicos para el Ethernet shield con Arduino.
Después se conectan los LEDs y se utiliza en cada caso una resistencia de 1 kΩ para limitar la corriente.
En la siguiente imagen representa la conexión completa.

Como puedes ver, he utilizado los pines digitales 2, 3, 5, 6 y 7 para conectar los LEDs. Tú puedes utilizar otros si lo prefieres, pero ten presente que tanto el bus SPI como el pin 10 son utilizados en la comunicación con el Shield Ethernet.
En la figura siguiente se aprecia el montaje.

Utiliza tres LEDs azules y dos rojos.
Ethernet Shield y su Arquitectura de red
Para este proyecto tendrás que montar una red similar a la que se muestra en la imagen.

Es decir, que tienes que conectar tanto el ordenador como el Arduino con el Shield Ethernet al router. En ambos casos debes utilizar cables de red ethernet.

En la siguiente imagen puedes ver el montaje realizado. En este caso he empleado un router TP-Link, el mismo que utilizo para conectarme a internet.

Si tu router admite conexiones Wifi entonces también podrás acceder al servidor y controlar los LEDs desde tu móvil.
Programar el servidor web en Arduino con Ethernet Shield
Con todo el sistema montado. Ahora solo queda darle vida programando la placa Arduino y el modulo Ethernet Shield.
De modo general en el Arduino se implementa un servidor web que solo admite dos tipos de peticiones: GET y POST.
Ante una petición GET el servidor responderá con una página web donde se muestra el estado actual de los LEDS y un grupo de botones para modificar el estado de estos.
Si se presiona uno de los botones de la página el navegador enviará una petición POST al servidor para cambiar el estado del LED correspondiente.
A continuación, por simplicidad, se analiza el código en partes.
Librerías, constantes y variables globales
Se empieza como de costumbre, incluyendo las librerías necesarias. En este caso solo es necesaria la librería Ethernet para el control del módulo de red.
1 2 |
// Programación del servidor web en Arduino con Ethernet Shield #include <Ethernet.h> |
Se declaran cinco constantes para definir los pines digitales a utilizar para controlar los LEDs. Una sexta constante indica la cantidad de LEDs que se utilizan.
1 2 3 4 5 6 7 |
// Constantes #define LED1 2 #define LED2 3 #define LED3 5 #define LED4 6 #define LED5 7 #define NUM_OF_LEDS 5 |
Los pines digitales son almacenados en un arreglo para facilitar su manejo.
1 |
const int leds[] = { LED1, LED2, LED3, LED4, LED5 }; |
Se declaran las constantes ip y mac con las direcciones IP y MAC del Arduino, respectivamente.
Si no tienes claro qué dirección IP o MAC asignarle a tu Arduino puedes revisar el artículo anterior sobre Ethernet Shield donde se muestra ese proceso paso a paso.
1 2 3 |
const IPAddress ip(192,168,1,125); // dirección IP const byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xA0, 0x88 };// dirección MAC |
Se define un objeto EthernetServer para la implementación del servidor web. Se utiliza el puerto 80 porque este es el predefinido para HTTP.
1 |
EthernetServer webServer(80); |
Función setup()
En la función setup() se inicializan todos los componentes necesarios. Se comienza configurando los pines de los LEDs como salida y en estado bajo (LOW).
1 2 3 4 5 6 7 |
void setup() { // Inicalizar LEDs for( int i = 0; i < NUM_OF_LEDS; i++ ){ pinMode( leds[i], OUTPUT ); digitalWrite(leds[i], LOW); } |
Luego se inicializa el puerto serie y el Ethernet Shield.
1 2 3 4 5 |
// Inicializar puerto Serial Serial.begin(9600); // Inicializar Ethernet Shield Ethernet.begin(mac, ip); |
Por último, se comprueba el estado del Ethernet Shield. Si este no presenta ningún problema se inicializa el servidor.
1 2 3 4 5 6 7 8 9 10 11 |
// Verificar Ethernet Shield if( Ethernet.hardwareStatus() == EthernetNoHardware ){ Serial.println("No se ha detectado Ethernet shield"); while(1); // no hacer nada } // Verificar cable Ethernet if (Ethernet.linkStatus() == LinkOFF) { Serial.println("El cable Ethernet no está conectado o está defectuoso"); } webServer.begin(); } |
Función loop()
En la función loop() simplemente se ejecuta la función checkForClients(). Es la encargada de atender las peticiones de los clientes.
1 2 3 |
void loop() { checkForClients(); } |
Función checkForClients()
La función comienza declarando una variable tipo String donde se almacenará el mensaje enviado por el cliente. También se crea un objeto EthernetClient utilizando la instrucción webServer.available().
1 2 3 4 |
void checkForClients(){ String sms_client; EthernetClient client = webServer.available(); |
Utilizando una instrucción if se comprueba la existencia de peticiones por parte de algún cliente. En caso de que se detecte alguna petición se indica mediante el monitor serie y se almacena el mensaje HTTP en la variable sms_client.
Para obtener el mensaje se van leyendo los caracteres enviados por el cliente hasta que se llegue a la línea en blanco que separa las cabeceras del cuerpo del mensaje. Para indicar que se ha encontrado el final de las cabeceras se asigna true a la variable ok.
Luego de haber leído los caracteres se verifica el valor de la variable ok. Si es false no se procesa la petición, ya que se considera un mensaje incompleto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
if( client ){ Serial.print( "Nuevo cliente conectado con ip " ); Serial.println( client.remoteIP() ); Serial.println("----------------------------------------------"); boolean currentLineIsBlank = true; boolean ok = false; while (client.connected()) { if (client.available()) { char c = client.read(); sms_client += c; Serial.print(c); if (c == '\n' && currentLineIsBlank) { // fin de la solicitud ok = true; break; } if (c == '\n') { // comienza una nueva línea currentLineIsBlank = true; } else if (c != '\r') { // se ha escrito un caracter en la nueva línea currentLineIsBlank = false; } } } if( !ok ) // mensaje HTTP inválido return; |
Si el mensaje es válido se comprueba el tipo de petición. En este caso solo se procesan dos tipos: GET y POST.
Para identificar el tipo de petición se implementó la función checkRequest(). Esta retorna false cuando el mensaje corresponde a GET y true para POST.
Si la petición es de tipo GET se invoca a la función responseToClient(), la cual envía un mensaje de respuesta al cliente a partir del estado de los LEDs.
En caso de ser una petición POST se lee el cuerpo del mensaje y se almacena en la variable payload. Luego se ejecuta la función makePOST() que interpreta el mensaje y actúa en consecuencia. También se ejecuta responseToClient() para que los cambios ocurridos sean actualizados en el navegador.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
int tipo_sms = checkRequest( sms_client ); if( tipo_sms == 0 ){ // es un GET responseToClient( client ); } else if( tipo_sms == 1 ){ // es un POST String payload = ""; // leer cuerpo del mensaje while( client.available() ){ char c = client.read(); payload += c; } Serial.print("payload: "); Serial.println(payload); makePOST(payload); responseToClient( client ); } |
Una vez se ha enviado la respuesta al cliente se realiza un pequeño retardo para que el navegador reciba los datos y por último se cierra la conexión con el cliente.
1 2 3 4 5 6 7 8 |
// esperar un tiempo para que el navegador reciba la información que envio el Ethernet shield delay(1); client.stop(); // cerrar la conexión Serial.println("----------------------------------------------"); Serial.println("client desconectado"); } } |
Función checkRequest()
La función checkRequest() recibe como parámetro un String con un mensaje HTTP y determina el método de petición. Para esto simplemente se comprueba si la palabra “GET” o “POST” se encuentra al principio del mensaje.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
int checkRequest( String &sms_client ){ // obtener la posición de GET int idx = sms_client.indexOf("GET"); if( idx == 0 ) return 0; idx = sms_client.indexOf("POST"); if(idx == 0) return 1; return -1; } |
Función responseToClient()
Esta función que recibe como parámetro un objeto EthernetClient y él envía una página web en formato HTML utilizando el protocolo HTTP con el estado de los LEDs y botones que permitan controlarlos.
Comienza enviando la versión HTTP y el resultado de su solicitud.
1 2 |
void responseToClient( EthernetClient &client ){ client.println("HTTP/1.1 200 OK"); |
Luego se envían las cabeceras indicando que es un mensaje HTML (Content-Type), que la conexión se cerrará después de ese mensaje (Connection) y que el navegador se debe refrescar cada 5 segundos (Refresh). Se termina la sección de cabeceras con una línea en blanco, tal y como se vio anteriormente.
1 2 3 4 5 6 7 8 |
// Formato del cuerpo del mensaje en HTML client.println("Content-Type: text/html"); // Cerrar conexión con el Ethernet shield al terminar la respuesta client.println("Connection: close"); // El navegador refresca la página cada 5 segundos client.println("Refresh: 5"); // Línea en blanco client.println(); |
Por último, envía la página web en formato HTML. Esta cuenta con cinco botones que muestran el estado actual de cada LED. Además, haciendo clic sobre un botón se puede cambiar el estado del LED.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// Enviar página web en HTML client.println( "<!DOCTYPE HTML>" ); client.println( "<html>" ); client.println( "<head>" ); client.println( " <title>Control LED con Arduino</title>"); client.println( "</head>" ); client.println( "<body>" ); client.println( " <h1>LEDs</h1>" ); client.println( " <p> Click para encender o apagar los LEDs </p>" ); for( int i = 0; i < NUM_OF_LEDS; i++ ){ client.println( " <form method=\"POST\">" ); client.print( " <label for=\"LED\">LED "); client.print(i+1); client.print(":</label>"); client.print( " <input type=\"submit\" name=\"LED"); client.print(i+1); client.print( "\" "); if( digitalRead(leds[i]) == HIGH ) client.print( "value=\"ON\">" ); else client.print( "value=\"OFF\">" ); client.println( " </form>" ); } client.println( "</body>" ); client.println("</html>"); } |
Más adelante se utiliza un navegador web para interactuar con la página y ver el código HTML generado.
Función makePOST()
La función makePOST() recibe el cuerpo de un mensaje de tipo POST y lo interpreta para identificar sobre qué LED tiene que actuar y qué operación realizar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void makePOST(String &sms){ int index = sms.indexOf("LED") + 1; int num_led; int state; while( !isdigit(sms[index]) ) index++; num_led = sms[index]-'0'; // obtener estado if( sms.indexOf("ON") != -1 ) state = HIGH; else state = LOW; // modificar estado if( state == LOW ) digitalWrite( leds[num_led-1], HIGH); else digitalWrite( leds[num_led-1], LOW); } |
Bueno, aquí tienes el código completo para que lo cargues a tu Arduino.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
// Programación del servidor web en Arduino con Ethernet Shield // Cabeceras #include <Ethernet.h> // Constantes #define LED1 2 #define LED2 3 #define LED3 5 #define LED4 6 #define LED5 7 #define NUM_OF_LEDS 5 const int leds[] = { LED1, LED2, LED3, LED4, LED5 }; const IPAddress ip(192,168,1,125); const byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xA0, 0x88 };// dirección MAC. EthernetServer webServer(80); void setup() { // Inicalizar LEDs for( int i = 0; i < NUM_OF_LEDS; i++ ){ pinMode( leds[i], OUTPUT ); digitalWrite(leds[i], LOW); } // Inicializar puerto Serial Serial.begin(9600); // Inicializar Ethernet Shield Ethernet.begin(mac, ip); // Verificar Ethernet Shield if( Ethernet.hardwareStatus() == EthernetNoHardware ){ Serial.println("No se ha detectado Ethernet shield"); while(1); // no hacer nada } // Verificar cable Ethernet if (Ethernet.linkStatus() == LinkOFF) { Serial.println("El cable Ethernet no está conectado o está defectuoso"); } webServer.begin(); } void loop() { checkForClients(); } void checkForClients(){ String sms_client; EthernetClient client = webServer.available(); if( client ){ Serial.print( "Nuevo cliente conectado con ip " ); Serial.println( client.remoteIP() ); Serial.println("----------------------------------------------"); boolean currentLineIsBlank = true; boolean ok = false; while (client.connected()) { if (client.available()) { char c = client.read(); sms_client += c; Serial.print(c); if (c == '\n' && currentLineIsBlank) { // fin de la solicitud ok = true; break; } if (c == '\n') { // comienza una nueva línea currentLineIsBlank = true; } else if (c != '\r') { // se ha escrito un caracter en la nueva línea currentLineIsBlank = false; } } } if( !ok ) // mensaje HTTP inválido return; int tipo_sms = checkRequest( sms_client ); if( tipo_sms == 0 ){ // es un GET responseToClient( client ); } else if( tipo_sms == 1 ){ // es un POST String payload = ""; // leer cuerpo del mensaje while( client.available() ){ char c = client.read(); payload += c; } Serial.print("payload: "); Serial.println(payload); makePOST(payload); responseToClient( client ); } // esperar un tiempo para que el navegador reciba la información que envio el Ethernet shield delay(1); client.stop(); // cerrar la conexión Serial.println("----------------------------------------------"); Serial.println("client desconectado"); } } int checkRequest( String &sms_client ){ // obtener la posición de GET int idx = sms_client.indexOf("GET"); if( idx == 0 ) return 0; idx = sms_client.indexOf("POST"); if(idx == 0) return 1; return -1; } void makePOST(String &sms){ int index = sms.indexOf("LED") + 1; int num_led; int state; while( !isdigit(sms[index]) ) index++; num_led = sms[index]-'0'; if( sms.indexOf("ON") != -1 ) state = HIGH; else state = LOW; // modificar estado if( state == LOW ) digitalWrite( leds[num_led-1], HIGH); else digitalWrite( leds[num_led-1], LOW); } void responseToClient( EthernetClient &client ){ // protocolo HTTP 1.1 client.println("HTTP/1.1 200 OK"); // Formato del cuerpo del mensaje en HTML client.println("Content-Type: text/html"); // Cerrar conexión al terminar la respuesta client.println("Connection: close"); // El navegador refresca la página cada 5 segundos client.println("Refresh: 5"); // Línea en blanco client.println(); // Enviar página web en HTML client.println( "<!DOCTYPE HTML>" ); client.println( "<html>" ); client.println( "<head>" ); client.println( " <title>Control LED con Arduino</title>"); client.println( "</head>" ); client.println( "<body>" ); client.println( " <h1>LEDs</h1>" ); client.println( " <p> Click para encender o apagar los LEDs </p>" ); for( int i = 0; i < NUM_OF_LEDS; i++ ){ client.println( " <form method=\"POST\">" ); client.print( " <label for=\"LED\">LED "); client.print(i+1); client.print(":</label>"); client.print( " <input type=\"submit\" name=\"LED"); client.print(i+1); client.print( "\" "); if( digitalRead(leds[i]) == HIGH ) client.print( "value=\"ON\">" ); else client.print( "value=\"OFF\">" ); client.println( " </form>" ); } client.println( "</body>" ); client.println("</html>"); } |
Funcionamiento del servidor web con Arduino y Ethernet Shield
Si ya tienes tu placa Arduino programada, el Ethernet shield, y el resto de componentes conectados es hora de comprobar que el sistema funciona correctamente.
Lo primero es energizar todo el sistema. Asegúrate de encender el router y alimentar el Arduino correctamente.
Ahora abre un navegador web en tu ordenador. Da lo mismo el que sea, aunque te recomiendo utilizar Mozilla Firefox o Chrome.

Una vez tengas el navegador abierto ve a la barra de direcciones y escribe la dirección IP que le asignaste al Arduino en el código. En mi caso sería 192.168.1.125.

Cuando la tecla ENTER sea presionada el navegador enviará una petición GET al servidor implementado en el Arduino.
En la siguiente figura se puede observar la salida del monitor serie donde se muestra la petición enviada por el navegador.

Para poder ver las peticiones enviadas al Arduino es necesario alimentarlo desde un puerto USB del ordenador y abrir el monitor serie.
Ten en cuenta que no es necesario alimentar el Arduino desde el ordenador para que el sistema funcione.
Al recibir la petición el Arduino evalúa el estado de los LEDs y envía una respuesta al navegador. En este último se debería cargar una página similar a la que se muestra en la siguiente figura.

Como puedes ver, la página cuenta con 5 botones, uno para cada LED. El texto de cada botón indica el estado actual de los LEDs. Presionando el botón se cambia el estado del LED correspondiente.
En la siguiente imagen se muestra el resultado obtenido después de presionar los botones correspondientes a los LEDs 1 y 4.

Si quieres ver el código fuente HTML de la página puedes hacer clic derecho y seleccionar la opción Ver código fuente de la página.

Esto abre una nueva pestaña donde se muestra el código HTML. Este código es el generado por el Arduino utilizando la función responseToClient().
Si no tienes experiencia en HTML será difícil entender por completo el código de la página web, sin embargo, puede ser interesante saber que cuentas con esta herramienta.

Como puedes ver cada botón pertenece a un formulario HTML (form), es por eso que al presionar uno de ellos el navegador envía una petición de tipo POST al Arduino. Por ejemplo, al presionar el botón correspondiente al LED 1 se envía la siguiente petición.

En el cuerpo de la petición se indica el estado actual del LED a modificar, es decir, que la instrucción LED1=OFF indica que el LED1 está actualmente apagado y debe encenderse.
Conclusión proyecto Ethernet Shield y Arduino
En este artículo se comenta cómo funciona el protocolo HTTP.
Luego, cómo utilizar HTTP con una placa Arduino y Ethernet Shield para implementar un servidor web que permita encender y apagar otros dispositivos.
Recuerda que aunque en el ejemplo se emplean LEDs, pueden ser intercambiados por relés.
Sin duda, serán viejos ayudantes electrónicos con mucho más potencial. Si te embarcas en esa travesía te recomiendo el artículo sobre control de relés con Arduino.
Pero entonces, el servidor web con Arduino y Ethernet shield ¿No es suficiente?
Pues, ningún problema.
Combina la interacción de LEDs con un monitor de temperatura y humedad puesto en marcha en la primera parte de este artículo.
Por ultimo, espero que este pequeño prototipo te halla abierto el apetito Maker.
Ya sabes, cualquier duda o sugerencia será bien recibida en la caja de comentarios.
Gracias a Shutterstock por ceder los derechos de las imágenes.