Encender y apagar un led por Ethernet

Objetivos

    • Montar un circuito con un LED y un Shield Ethernet.
    • Crear un servidor Web.
    • Mostrar un código básico HTML para activar o desactivar el LED.
    • Presentar el Port Forwarding y su razón de ser, cuando queremos acceder desde internet al servidor de nuestro Arduino.

Material requerido

 arduino
  • Arduino Uno o similar. Esta sesión acepta cualquier otro modelo de Arduino.
 Img_3_4
  •  Una Protoboard.
 Img_3_6-300x185
  • Algunos cables de Protoboard.
EtherShield-150x150
  • Un Un Shield Ethernet (W5100).
RJ45_Cable-300x192
  • Un cable rj45.
Img_3_5
  • Una resistencia de 330Ω.
RedLed_
  • Un led
concentrador
  • Acceso a la red local.

 

El HTML

Para continuar presentando como hacer ciertas cosas con Arduino y la conexión a Ethernet, necesitamos presentar algunas ideas al respecto, porque sin ellas cualquier intento de avanzar seria vano.
Por ejemplo, es muy útil disponer de un programa tipo, que nos permita manipular un LED conectado a nuestro Arduino mediante una página Web, y este es el objetivo de la sesión actual.
Para ello, vamos a presentar pequeños fragmentos de HTML que nos permitan hacerlo, sin entrar en grandes detalles del lenguaje, pero que vamos a emplear en nuestros programas.
EL primero, nos permite mostrar un checkbox en nuestra página y reconocer si se ha pinchado o no:

<!DOCTYPE html>
<html>
     <head>
       <title> Control de LEDs en Arduino</title>
     </head>
     <body>
       <h1>LED remoto</h1>
       <p>Haz click para conmutar el LED.</p>
       <form method="get">
           <input type="checkbox" name="LED2" value="2" onclick="submit();">LED2
      </form>
      </body>
</html>
  • Como norma general, lo que se presenta entre < > se llaman tags y describen algo en concreto, títulos, cabeceras, negritas….
  • Por ejemplo para expresar que es código HTML, debemos empezar con <html> y finalizar con </html>, lo mismo ocurre con los demás tags, como < head> cabecera, <body> cuerpo, o <p> párrafo, que cuando finalizan incorporan un tag con el símbolo “/” para indicar el fin del tag.

Hemos usado un método HTML para mostrar un checkbox y enviar un texto cuando se pulse.

Si copiáis ese código con un editor de textos y lo guardáis con extensión htm o html, cuando lo abras con el navegador veras:Img_63_1_

Img_62_2_-300x263

Fijate en la segunda imagen, que cuando pulsemos el checkbox, el navegador añadirá al final de la dirección IP, el texto ?LED2.

Utilizaremos este texto de respuesta para decidir si encendemos o apagamos el LED. Para ello usaremos la función  indexOf() que nos devuelve si un string está incluido o no en otro.

Diagrama del circuito

Vamos a usar un circuito con Arduino y un LED conectado al D2 con sus resistencia, en conjunción con la página web que hemos descrito en el apartado anterior. En función del status del checkbox encenderemos o apagaremos los LED.

Img_63_3

El programa de control

La mayor parte del programa va a ser similar al programa de la entrada anterior, con algunas modificaciones. Principalmente, será crear un variable para almacenar el status del LED, y un String para registrar la petición que nos hace el cliente Web:

String HTTP_req;     // stores the HTTP request
boolean LED_status=0;// state of LED, off by default

El resto es casi igual, excepto porque cambiamos el código HTML que enviamos en la respuesta, para presentar el fragmento del que hablamos más arriba, y porque hemos añadido una función processCheckbox() que hará el procesamiento del click (incluyendo enviar el HTML correspondiente a pulsado o no).

  • Fijaros que enviamos los comandos HTML, mediante client.print() a quien le pasamos los strings limitados por comillas. Pero como los comandos HTML también incluyen comillas, si los copiamos por las buenas tendríamos problemas.
  • La solución de C++ para esto es preceder el carácter a imprimir por un carácter de escape para que el compilador sepa que no es el fin del string, si no parte de él.
  • Por eso, si queremos mandar <form method=»get»> lo que tenemos que enviar con print es <form method=\»get\»>.

Aquí tenéis el programa:

#include <SPI.h>
#include <Ethernet.h>

byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,177);
EthernetServer server(80);

String HTTP_req; // Para guardar la petición
boolean LED2_status = 0;

void setup()
{   Ethernet.begin(mac, ip);  
    server.begin();           
    Serial.begin(9600);       
    pinMode(2, OUTPUT);       
}
void loop(){
  EthernetClient client = server.available();    // Comprobamos si hay peticiones
  if (client){  
      boolean currentLineIsBlank = true;
      while (client.connected()){ 
        if (client.available()){
          char c = client.read(); 
          HTTP_req += c;
          if(c=='\n' && currentLineIsBlank)
                    { 
           client.println("HTTP/1.1 200 OK");
           client.println("Content-Type: text/html");
           client.println("Connection: close");
           client.println();
           client.println("<!DOCTYPE html>");   
           client.println("<html>");
           client.println("<head>");
           client.println("<title>Control de LEDs en Arduino</title>");
           client.println("</head>");
           client.println("<body>");
           client.println("<h1>LED</h1>");
           client.println("<p>Haz click para conmutar el LED.</p>");
           client.println("<form method=\"get\">");
           processCheckbox(client);
           client.println("</form>");
           client.println("</body>");
           client.println("</html>");
           Serial.print(HTTP_req);
           HTTP_req = "";
           break;
         }
         if(c=='\n')
                currentLineIsBlank = true;
              else if (c != '\r')
                currentLineIsBlank = false;
     } 
   }   // WHile
   delay(10);      // dar tiempo
   client.stop(); // Cerra conexion
   }  // If client
}
void processCheckbox(EthernetClient cl)
  {  
  if (HTTP_req.indexOf("LED2=2") > -1)
     LED2_status = !LED2_status ;
     digitalWrite(2, LED2_status);
     if (LED2_status)
         cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \\ onclick=\"submit();\" checked>LED2");
     else
       cl.println("<input type=\"checkbox\" name=\"LED2\" value=\"2\" \\  onclick=\"submit();\">LED2");
   }