En este momento estás viendo Como hacer un servidor web con arduino

Como hacer un servidor web con arduino

En este post vamos a mostrar como montar un servidor web con Arduino.

Para ello usaremos la placa MKR1000, que como vimos en el post Conociendo la placa Arduino MKR1000, esta placa tiene capacidad de conexión a WiFi. Aunque también podríamos usar el shield WiFi101 que usa la misma librería, en conjunto con otra placa Arduino.

La librería WiFi101

Esta libreria permite usar el Arduino WiFi Shield 101 y la placa MKR1000. Estas son poderosas soluciones IoT con autenticación criptográfica, desarrolladas por ATMEL, que conecta tu Arduino a Internet por WiFi. La conexión de la placa o el shield a una red WiFi es simple, no se necesita ninguna configuración adicional además del SSID (nombre de la red) y la contraseña.

Puede servir como un servidor aceptando conexiones entrantes o como cliente que hace conexiones salientes. La libreria admite cifrado WEP y WPA2, además de conexiónes SSL (el método connectSSL() es necesario cuando el servidor sólo proporciona conexiones HTTPS).  La biblioteca WiFi101 es muy similar a la Ethernet y la biblioteca WiFi, y muchas de las llamadas a funciones son las mismas.

Los ejemplos que mostraremos a continuación están basados en los ejemplos de la librería WiFi101, disponibles en arduino.cc y en el IDE de arduino.

 Ejemplo 1 – Mostrar valores analógicos

#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "elNombreDeTuRedWifi"; // el nombre de tu red wifi
char pass[] = "laContraseñaDeTuRedWifi"; // la contraseña de tu red wifi
int keyIndex = 0;  // El key Index number de tu red (nesesario solo para WEP)

int status = WL_IDLE_STATUS;
WiFiServer server(80); //Indica el puerto del servidor que atendera las conexiones

void setup() {
  Serial.begin(9600);  // Inicia la comunicacion serie 
  pinMode(6, OUTPUT); // set the LED pin mode
  
  if (WiFi.status() == WL_NO_SHIELD) {  // Si no se detecta el hardware wifi no se continua
    Serial.println("WiFi shield not present");
    while (true);  // No continua, se queda en el while
  }
  
  while ( status != WL_CONNECTED) {  // intenta conectarse a la red wifi
    Serial.print("Intentando conectarse a la red: ");
    Serial.println(ssid);  // imprime el nombre de la red (SSID);

    // conecta a una red WPA/WPA2. Hay que cambiar esta linea si se quiere conectar a una red WEP
    status = WiFi.begin(ssid, pass);  // se conecta a la red wifi, devuelve el estado de la conexion
    delay(10000);  // espera 10 segundos por la coneccion
  }
  server.begin();  // inicia el servidor web en el puerto especificado
  printWiFiStatus();  // ya conectado se imprime el estatus
}

void loop() {
  WiFiClient client = server.available();   // escuchamos por clientes
  if (client) {                       // si se tiene un cliente,
    Serial.println("Nuevo cliente");  // imprime un mensaje en el puerto serie
    boolean currentLineIsBlank = true;// una peticion http termina con una linea en blanco
    while (client.connected()) {      // lazo mientras el cliente este conectado
      if (client.available()) {       // Si hay algunos bytes que leer del cliente,
        char c = client.read();       // lee el byte, y
        Serial.write(c);              // lo imprime en el monitor serie
        // si el byte es el caracter de nueva linea
        // Y si la línea actual está en blanco,
        // este es el fin de la solicitud de cliente, entonces envia una respuesta:
        if (c == '\n' && currentLineIsBlank) {
          // los encabezados HTTP siempre comienzan con un codigo de respuesta (por ejemplo HTTP/1.1 200 OK)
          // y el typo de contenido asi el cliente sabe que viene, despues una linea en blanco:
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // la conexion sera cerrada despues de enviada la respuesta
          client.println("Refresh: 5");  // refresca la pagina automaticamente cada 5 segundos
          client.println();  //fin del encabezado
          
          // aqui va el codigo html que define lo que mostrara la pagina web
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("</body>");
          client.println("<h1>Puertos analogicos</h1>");
          // Muestra el valor de cada pin de entrada analogica
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("Entrada analogica A");
            client.print(analogChannel);
            client.print(" es igual a: ");
            client.print(sensorReading);
            client.println("<br />");
          }
          client.println("</body>");
          client.println("</html>");
          break;  // sale del lazo del while:
        }
        if (c == '\n') {
          currentLineIsBlank = true;  // esta comenzando una nueva linea
        }
        else if (c != '\r') {
          
          currentLineIsBlank = false;  // estas recibiendo un caracter en la linea
        }
      }
    }
    delay(1);  // da al navegador tiempo para recibir los datos
    // cierra la coneccion:
    client.stop();
    Serial.println("client disonnected");
  }
}

void printWiFiStatus() {
  // Imprime el SSID de la red a la cual estas conectado:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  // imprime la direccion IP de la placa o shield con que estas conectado:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  // Imprime la intensidad de la señal recibida:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Al abrir el monitor serie veremos que se imprime el estatus de la conexión con la dirección IP del servidor (esto puede tardar algunos segundos).

Y al colocar la direccion IP en el navegador veremos la pagina web de nuestro servidor.

Y en el monitor serie veremos el intercambio de datos cada 5 segundos.

Y ahora que sabemos como mostrar información de nuestra placa en nuestro servidor, veremos como enviar información a nuestra placa arduino desde el servidor, y para ello nos apoyaremos en el atributo method de la etiqueta <form>.

Usando el método GET para enviar datos

Usando formularios y el método de envio “GET” en html logramos que en el URL y en la primera línea de la cabecera de petición del cliente aparezca la pareja nombre<->valor del dato enviado con la sintaxis siguiente: GET /?nombre=valor HTTP/1.1 . Por tanto, una manera sencilla de comprobar si se ha pulsado un determinado botón, o enviado otro valor a través de un formulario es detectar si en la cadena anterior aparece el “nombre=valor” buscado. El lenguaje Arduino dispone para los objetos String de mucha instrucciones, y en particular la funcion “startsWith()” nos sirvió para esto, aunque podríamos usar otra.

Ejemplo 2 – Encender y apagar un led

#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "elNombreDeTuRedWifi"; // el nombre de tu red wifi
char pass[] = "laContraseñaDeTuRedWifi"; // la contraseña de tu red wifi
int keyIndex = 0;  // El key Index number de tu red (nesesario solo para WEP)

int status = WL_IDLE_STATUS;
WiFiServer server(80); //Indica el puerto del servidor que atendera las conexiones

void setup() {
  Serial.begin(9600);  // Inicia la comunicacion serie 
  pinMode(6, OUTPUT); // configura el pin 6 como salida
  
  if (WiFi.status() == WL_NO_SHIELD) {  // Si no se detecta el hardware wifi no se continua
    Serial.println("WiFi shield not present");
    while (true);  // No continua, se queda en el while
  }
  
  while ( status != WL_CONNECTED) {  // intenta conectarse a la red wifi
    Serial.print("Intentando conectarse a la red: ");
    Serial.println(ssid);  // imprime el nombre de la red (SSID);

    // conecta a una red WPA/WPA2. Hay que cambiar esta linea si se quiere conectar a una red WEP
    status = WiFi.begin(ssid, pass);  // se conecta a la red wifi, devuelve el estado de la conexion
    delay(10000);  // espera 10 segundos por la coneccion
  }
  server.begin();  // inicia el servidor web en el puerto especificado
  printWiFiStatus();  // ya conectado se imprime el estatus
}

void loop() {
  WiFiClient client = server.available();   // Pregunta por la clientes en el servidor

  if (client) {                             // si se tiene un cliente,
    Serial.println("Nuevo cliente");        // imprime un mensaje en el puerto serie
    String currentLine = "";                // se crea una cadena para recibir los datos del cliente
    while (client.connected()) {            // lazo mientras el cliente este conectado
      if (client.available()) {             // Si hay algunos bytes que leer del cliente,
        char c = client.read();             // lee el byte, y
        Serial.write(c);                    // lo imprime en el monitor serie
        if (c == '\n') {                    // si el byte es el caracter de nueva linea

          // Y Si la línea actual está en blanco,
          // este es el fin de la solicitud de cliente, entonces envia una respuesta:
          if (currentLine.length() == 0) {
            // los encabezados HTTP siempre comienzan con un codigo de respuesta (por ejemplo HTTP/1.1 200 OK)
            // y el tipo de contenido asi el cliente sabe que viene, despues una linea en blanco:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println(); //fin del encabezado

            // el contenido va a continuacion del encabezado anterior:
            // aqui va el codigo html que define lo que mostrara la pagina web
            client.print("<h1>Controlando un led desde una pagina web</h1>");
            client.print("<p>Pulsa los botones para encender o apagar el led abordo de la placa MKR1000</p>");
            client.print("<form>");          
            client.print("<button type='submit' name='LED6' value='1'>Encender</button>");
            client.print("<button type='submit' name='LED6' value='0'>Apagar</button>");
            client.print("</form>");
            // la respuesta HTTP termina con otra linea en blanco:
            client.println();
            break;  // sale del lazo del while:
          }
          else {      // si se recibe una nueva linea, entonces vacia currentLine:
            currentLine = "";
          }
        }
        else if (c != '\r') {    // si recibes un caracter diferente al caracter de retorno de carro,
          currentLine += c;      // añadelo al final de currentLine
        }
      
        // Revisa si la solicitud del cliente fue "GET /?LED6=1" o "GET /?LED6=0":
        if (currentLine.startsWith("GET /?LED6=1")) {
          digitalWrite(6, HIGH);               // GET /H enciende el LED
        }
        if (currentLine.startsWith("GET /?LED6=0")) {
          digitalWrite(6, LOW);                // GET /L apaga el LED
        }
      }
    }
    // cierra la coneccion:
    client.stop();
    Serial.println("Cliente desconectado");
  }
}

void printWiFiStatus() {
  // Imprime el SSID de la red a la cual estas conectado:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  // imprime la direccion IP de la placa o shield con que estas conectado:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  // Imprime la intensidad de la señal recibida:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
  // imprime como ver la pagina en el navegador:
  Serial.print("Para ver esta pagina en accion, abre esta url en el navegador: http://");
  Serial.println(ip);
}

Al abrir el monitor serie veremos que se imprime el estatus de la conexión y nos indica la dirección IP del servidor (esto puede tardar algunos segundos).

Y al colocar la direccion IP en el navegador veremos la pagina web de nuestro servidor, donde podremos encender y apagar el LED 6 de la placa MKR1000 presionando los botones.

Y en el monitor serie veremos el intercambio de datos cada vez que presionamos los botones.

Y esto es todo por ahora. Si aún no te has suscrito a nuestro boletín, suscríbete y te mantendré informado de  la últimas publicaciones y entregas especiales. Y si tienes alguna pregunta o comentario acerca del post no dudes en hacerla.

Deja una respuesta