Aquí puedes acceder a la segunda parte de Ethernet Shield con Arduino.
A lo mejor te estás preguntando qué es eso del Ethernet Shield con Arduino y para qué me puede servir.
Probablemente te suene a tarjeta de red o cable de red de esos que utilizamos en nuestras casas o en el trabajo para conectar el ordenador de sobremesa, la Play o el Smart TV a la red local.
Y no vas mal encaminado.
Ya hablé en otro artículo sobre los shields de Arduino. En concreto del EchidnaShield. Digamos que son placas electrónicas que se pueden acoplar a un Arduino UNO o Arduino MEGA y añaden nuevas funcionalidades.
Viene a ser como una librería pero en hardware.
En este caso, Ethernet Shield lo que añade es conectividad a través de Ethernet. Vamos, como si tuvieras una tarjeta de red conectada a tu Arduino.
Imagínate todo lo que puedes hacer con un Arduino conectado a Internet.
Bueno, esto no es algo nuevo en este blog. Ya nos has leído y oído hablar del ESP8266. Este microcontrolador también se puede conectar a Internet pero utilizando la red WiFi.
En este artículo hablaré de todo esto. Así que ponte cómodo, prepara el cable de red que empezamos.
Indice de contenidos
Conocimientos básicos sobre redes
Antes de empezar con el Ethernet Shield es importante tener claros ciertos conceptos básicos sobre redes.
Ojo, no pretendo explicarte en profundidad todo el funcionamiento de una red, simplemente quiero que comprendas los principios básicos de una red local que puedes implementar en tu hogar.
Una red de área local o LAN (por sus siglas en inglés Local Area Network) es una red de equipos que abarca un área reducida, ya puede ser una casa, un departamento o un edificio. Típicamente está integrada por dispositivos conectados por WiFi y/o Ethernet a un dispositivo en común (usualmente un router). A esta topología se le conoce como estrella y es la más común en los hogares.
En la siguiente imagen puedes ver una red típica de un hogar. El router actúa como eje central de la red, ya que todos los dispositivos se conectan a él mediante Wifi (tablets, teléfonos, ESP8266, etc.) o Ethernet (ordenadores, teléfonos IP, Arduino con Ethernet Shield, etc). Además, el router funciona como puerta de enlace entre los dispositivos e internet.
Otro caso de LAN es cuando configuras un ESP8266 como punto de acceso (access point) y le conectas varios dispositivos Wifi. En ese caso el ESP8266 es el centro de la conexión.
La ventaja de tener una red LAN es que todos los dispositivos presentes en la red pueden interactuar entre ellos sin la necesidad de una conexión a internet. Por eso, es una buena opción si quieres montar tu propia red de sensores o actuadores sin conexión a internet.
Para que una red LAN funcione correctamente todos los dispositivos deben:
- Tener una dirección MAC (MAC Address) única.
- Tener una dirección IP (IP Address) única.
- Conocer la máscara de red (netmask).
- Conocer la puerta de enlace (conocida en inglés como gateway), es decir, la dirección IP del router.
La dirección MAC (también es conocida como dirección física) es un código de 6 bytes propio de todo dispositivo de red. Cuando digo todo dispositivo me refiero a todos: tu teléfono, tu ordenador, tableta, smartwatch y cualquier equipo que se conecte a una red cuenta con su propia dirección MAC.
Usualmente los dispositivos traen una dirección MAC fija, pero en algunos casos, como los ESP8266 y los Ethernet Shield, es posible especificar mediante software.
La dirección IP es un código de 4 bytes que identifica a un dispositivo dentro de una red. Eso no significa que sea propia de cada dispositivo. Sino que, según la configuración de la red, se le asigna una dirección IP u otra a un dispositivo.
Usualmente una dirección IP se escribe separando cada uno de los bytes con un punto, por ejemplo:
192.168.10.4
10.2.27.8
192.168.4.56
La máscara de red, al igual que la dirección IP, está compuesta por 4 bytes que permiten conocer cómo se deben asignar las direcciones IP en la red.
Si una red utiliza como máscara 255.255.0.0 significa que los dos primeros bytes de la dirección IP serán iguales para todos los dispositivos. Por ejemplo, pueden existir dispositivos con las siguientes direcciones:
10.2.2.3
10.2.7.6
10.2.7.5
Como puedes ver los dos primeros bytes se mantienen iguales para todos los dispositivos.
La puerta de enlace no es otra cosa que la dirección IP del router. Aunque esta puede tener cualquier dirección lo usual es que su dirección IP sea la primera de la red. Por ejemplo, para el caso anterior la puerta de enlace debería ser 10.2.0.1.
Existen dos formas de asignar la dirección IP, máscara de subred e indicar la puerta de enlace a un dispositivo:
- Utilizar una dirección IP estática: eso implica que debemos configurar manualmente los parámetros de red a nuestro dispositivo. Sin embargo, nos ofrece la ventaja de que nuestro dispositivo siempre tendrá la misma dirección IP.
- Utilizar dirección IP dinámica (DHCP): en este caso es el router el encargado de indicarle todos los parámetros al dispositivo. Este proceso ocurre de forma automática, pero implica que nuestros dispositivos no siempre tendrán la misma dirección IP.
Para este proyecto utilizaremos el primer método, ya que necesitamos conocer la dirección IP del Arduino para acceder a él a través de la red. Si utilizáramos la asignación dinámica cada vez que el router se enciende el Arduino puede tomar una IP diferente.
Arquitectura cliente-servidor
Ya conoces los conceptos básicos pero aún no se ha hablado de cómo se comunican los dispositivos a través de una red.
Para la comunicación entre dispositivos se suele emplear un modelo cliente-servidor. En este modelo, un dispositivo (el servidor) está a la espera de mensajes u órdenes provenientes de otros dispositivos (clientes). Cuando el servidor recibe un mensaje, lo procesa y envía una respuesta al cliente.
Es algo similar a lo que ocurre en una clase de un colegio durante un repaso.
El profesor se para frente a los estudiantes y pregunta:
– ¿alguna duda muchachos?
Entonces un estudiante pregunta:
– ¿profesor, cómo se calcula el área de un rectángulo?
Y el profesor le responde:
– multiplicando su altura por su ancho.
En este caso el profesor hace de servidor, está a la espera de una pregunta proveniente de algún estudiante. Cuando algún alumno hace una pregunta el profesor la analiza y luego la responde.
Una vez realizado este proceso la comunicación termina y el profesor vuelve a estar a la espera de alguna nueva pregunta.
Otro ejemplo de servidor es el buscador de Google. Cuando escribes la palabra a buscar, estas enviando un mensaje.
El servidor toma las palabras del mensaje, revisa su base de datos y envía las coincidencias.
En en practico de este post el servidor será el Arduino conectado a un Ethernet Shield. Y en lugar de tener una base de datos, se utiliza un sensor para determinar la temperatura y la humedad.
El cliente será el navegador de cualquier dispositivo que se encuentre conectado a la red local. Es decir, que puedes conectarte desde el teléfono o el ordenador siempre y cuando estos pertenezcan a la misma red que la placa Arduino.
Si quieres conocer un poco más sobre la operación de los sitios webs puedes revisar el artículo del blog donde se muestra el funcionamiento de un sitio web.
Ethernet Shield
Un Ethernet Shield permite conectar nuestro Arduino UNO o Arduino MEGA a una red mediante un cable ethernet (el típico cable que se utiliza para conectar el ordenador a internet). Eso significa que puedes conectar Arduino a internet o a una red local fácilmente.
Existen dos versiones de este Shield:
- La primera versión, Ethernet Shield V1 está basada en el chip ethernet de Wiznet W5100.
- La segunda versión, Ethernet Shield 2, se basa en el chip ethernet de Wiznet W5500
Ambos módulos son capaces de establecer comunicaciones TCP y UDP. También admiten mantener varias conexiones abiertas simultáneamente y permiten a Arduino actuar como servidor o cliente utilizando la librería Ethernet.
Principales componentes del módulo Ethernet Shield
En la siguiente imagen se muestran los principales componentes presentes en ambas versiones de los módulos Ethernet Shield:
- Conector ethernet (RJ45): utilizado para conectar el sistema a la red.
- Regulador de voltaje: utilizado para la alimentación de la placa.
- Botón de reinicio: este botón reinicia tanto el controlador ethernet como la placa Arduino.
- Expansión de pines: conectores que expanden todos los pines del Arduino, por lo tanto, es posible conectar otro módulo u otro Shield encima de este.
- Chip W5100 o W5500: chip principal del módulo.
- Ranura para tarjeta micro-SD: esta ranura puede utilizarse para colocar una tarjeta que almacena archivos de texto, imágenes o cualquier otra información.
Para utilizar la tarjeta es necesario emplear la librería SD
El Ethernet Shield V2 cuenta además con varios conectores Tinkerkit:
- Dos conectores para entradas analógicas, conectados a A2 y A3.
- Dos conectores para salidas analógicas, conectados a los pines digitales 5 y 6.
- Dos conectores para la interfaz TWI (I2C), uno para entrada y el otro para salida.
Los módulos Ethernet Shield también cuentan con un grupo de LEDs indicadores:
- ON o PWR: indica que la placa Arduino y el Shield están alimentados
- 13: conectado al pin 13 del Arduino (solo en la versión 2)
- LINK: indica la presencia de un enlace de red y pestañea cuando se transmiten o se reciben datos.
- 100M: indica que la conexión es de 100 Mb/s. Cuando está apagado significa que la red es de 10 Mb/s (este LED solo está presente en la versión 1)
- ACT: pestañea cuando hay actividad de transmisión o recepción (solo en la versión 2)
- RX: pestañea cuando se reciben datos (sólo en la versión 1)
- TX: pestañea cuando se transmiten datos (sólo en la versión 1)
Como conectar Ethernet Shield con Arduino UNO y Arduino MEGA
Conectar un Ethernet Shield a un Arduino UNO o un Arduino MEGA es muy simple. Basta colocarlo sobre la placa haciendo coincidir los conectores, tal y como se muestra en la figura.
Cuando se emplea un Arduino MEGA es necesario ser un poco más cuidadoso. Una buena guía es comprobar que el conector ICSP del Arduino y el Shield coincidan.
Ya sea un Arduino UNO o MEGA se utiliza el bus SPI para la comunicación con el shield. Este bus corresponde a los pines digitales 11, 12 y 13 en un Arduino UNO y a los pines 50, 51 y 52 de un Arduino MEGA. En ambas placas el pin digital 10 es empleado como SS para el chip ethernet y el pin digital 4 es utilizado como SS para la tarjeta micro-SD.
En el Arduino MEGA el pin digital 53 se corresponde con la señal SS del puerto SPI. Aunque en este caso no se utiliza para tal propósito, es necesario que este pin NO sea configurado como entrada (INPUT), de lo contrario el bus SPI no funcionará.
Librería Ethernet
La librería Ethernet está especialmente diseñada para trabajar con ambas versiones del Ethernet Shield o cualquier otro módulo basado en los chips W5100, W5200 o W5500.
En esta librería se dispone de un grupo de clases para operar con el módulo Ethernet, entre estas destacan:
- Ethernet: inicializa la librería ethernet y configura la red.
- EthernetServer: permite recibir y enviar datos a un cliente conectado, es decir, a una aplicación en otro equipo. Ya puede ser un navegador web o una aplicación móvil creada por ti.
- EthernetClient: es utilizada cuando la placa funciona como cliente de otro servidor o cuando un servidor recibe.
En este tutorial voy a utilizar las clases Ethernet y EthernetServer. Antes comenzar con el proyecto, veras a las funciones principales de estas clases.
Principales funciones de la clase Ethernet
Ethernet es una clase estática, lo que quiere decir que no hace falta crear una instancia u objeto de la clase. Es como las librerías Serial o Wire.
Directamente escribes la clase (Ethernet) y luego llamas a la función correspondiente. Veamos alguna de estas funciones.
Ethernet.init()
Esta función permite configurar el pin digital utilizado como SS para controlar el módulo ethernet. En nuestro caso, como estamos empleando un Ethernet Shield no es necesario utilizar esta función, ya que la clase Ethernet utiliza de forma predeterminada el pin 10.
La sintaxis sería:
1 2 |
Ethernet.init(SSpin); |
Donde:
- SSpin: representa el pin utilizado para controlar el chip del Ethernet Shield.
Ethernet.begin()
Esta función inicializa la librería ethernet y configura los parámetros de red necesarios para el módulo. Se puede llamar de cinco maneras diferentes dependiendo del número de parámetros que admita.
Una función que puede ser llamada de diferentes maneras dependiendo el número de parámetros, se dice que es una función o un método sobrecargado.
Primera sobrecarga de la función admite cinco parámetros.
1 |
Ethernet.begin(mac, ip, dns, gateway, subnet); |
Donde:
- mac: dirección MAC del Ethernet Shield.
- ip: dirección IP que se asignará al Ethernet Shield.
- dns: dirección IP del servidor DNS (usualmente es la dirección IP del router).
- gateway: puerta de enlace (dirección IP del router)
- subnet: máscara de subred.
Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Dirección física del Arduino byte ethernet_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Dirección IP a utilizar por el Arduino IPAddress ip(10, 2, 1, 105); // Dirección IP del router IPAddress dns(10, 2, 1, 1); IPAddress gateway(10, 2, 1, 1); // Máscara de Subred IPAddress subnet(255,255,255,0); // Inicializar librería ethernet y configurar parámetros de red Ethernet.begin(ethernet_mac, ip, dns, gateway, subnet); |
Segunda sobrecarga de la función admite cuatro parámetros.
En este caso no se especifica la máscara de subred. La librería asumirá de forma automática 255.255.255.0 como máscara de subred.
1 |
Ethernet.begin(mac, ip, dns, gateway); |
Donde:
- mac: dirección MAC del Ethernet Shield.
- ip: dirección IP que se asignará al Ethernet Shield.
- dns: dirección IP del servidor DNS (usualmente es la dirección IP del router).
- gateway: puerta de enlace (dirección IP del router)
Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Dirección física del Arduino byte ethernet_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Dirección IP a utilizar por el Arduino IPAddress ip(10, 2, 1, 105); // Dirección IP del router IPAddress dns(10, 2, 1, 1); IPAddress gateway(10, 2, 1, 1); // Inicializar librería ethernet y configurar parámetros de red Ethernet.begin(ethernet_mac, ip, dns, gateway); |
Tercera sobrecarga de la función admite tres parámetros. En este caso no se especifican la máscara de subred ni la puerta de enlace.
La librería tomará de forma automática 255.255.255.0 como máscara de subred.
Para determinar la puerta de enlace la librería toma la dirección IP y le cambia el último byte a 1. Por ejemplo:
Si se utiliza la dirección IP 192.168.4.23 entonces la placa Arduino asumirá como puerta de enlace la 192.168.4.1 (solo se ha cambiado el último byte).
La sintaxis de la función sería la siguiente:
1 |
Ethernet.begin(mac, ip, dns); |
Donde:
- mac: dirección MAC del Ethernet Shield.
- ip: dirección IP que se asignará al Ethernet Shield.
- dns: dirección IP del servidor DNS (usualmente es la dirección IP del router).
Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Dirección física del Arduino byte ethernet_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Dirección IP a utilizar por el Arduino IPAddress ip(192, 168, 2, 87); // DNS -> Dirección IP del router IPAddress dns(192, 168, 2, 1); // Inicializar librería ethernet y configurar parámetros de red // - máscara de red: 255.255.255.0 // - puerta de enlace: 192.168.2.1 Ethernet.begin(ethernet_mac, ip, dns); |
Cuarta sobrecarga de la función admite solo dos parámetros.
En este caso, al igual que en los anteriores, la librería asume 255.255.255.0 como máscara de subred.
La librería asume las direcciones de la puerta de enlace y el DNS igual que en la sobrecarga anterior, es decir, tomando la dirección IP y cambiando su último byte por 1.
La sintaxis es la siguiente:
1 |
Ethernet.begin(mac, ip); |
Donde:
- mac: dirección MAC del Ethernet Shield.
- ip: dirección IP que se asignará al Ethernet Shield.
Ejemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 |
// Dirección física del Arduino byte ethernet_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Dirección IP a utilizar por el Arduino IPAddress ip(192, 168, 10, 8); // Inicializar librería ethernet y configurar parámetros de red // - máscara de red: 255.255.255.0 // - puerta de enlace: 192.168.10.1 // - dns: 192.168.10.1 Ethernet.begin(ethernet_mac, ip); |
Quinta sobrecarga de la función admite un solo parámetro
En este caso, el router de la red es el encargado de asignar los parámetros de red al Arduino. Este proceso ocurre de forma automática y transparente para nosotros.
1 |
Ethernet.begin(ethernet_mac); |
Donde:
- mac: dirección MAC del Ethernet Shield.
Ejemplo de uso:
1 2 3 4 |
// Dirección física del Arduino byte ethernet_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; Ethernet.begin(ethernet_mac); |
Ethernet.hardwareStatus()
Esta función nos indica qué chip controlador de ethernet que utiliza el módulo empleado.
Su sintaxis es muy simple.
1 |
chip = Ethernet.hardwareStatus(); |
Donde:
- chip: es el tipo de chip presente en el módulo ethernet.
Esta función puede retornar alguno de los siguientes valores:
Valor | Significado |
EthernetNoHardware | No se ha detectado chip |
EthernetW5100 | Detectado chip controlador W5100 |
EthernetW5200 | Detectado chip controlador W5200 |
EthernetW5500 | Detectado chip controlador W5500 |
Ethernet.linkStatus()
Esta función nos permite verificar si el enlace de red está activo, es decir, que permite comprobar si el cable está dañado o mal conectado.
Su sintaxis es:
1 |
status = Ethernet.linkStatus(); |
Donde:
- status: indica el estado del enlace de red.
En la siguiente tabla tienes los valores que puede retornar esta función.
Valor | Significado |
Unknown * | No se puede determinar el estado del enlace |
LinkON | Enlace activo |
LinkOFF | Cable defectuoso o desconectado |
* Este valor solo es retornado cuando se utiliza un Ethernet Shield V1, ya que el chip W5100 no es compatible con esta función.
Principales funciones de la clase EthernetServer
La clase EthernetServer puede ser utilizada para que una placa Arduino se comporte como un servidor, es decir, para que acepte mensajes desde otros dispositivos y envíe o ejecute respuestas consecuentes. Esta es precisamente la clase que nos permitirá implementar un servidor web dentro de nuestro Arduino.
Al contrario de la clase Ethernet la clase EthernetServer no es una clase estática. Eso significa que es necesario crear un objeto o instancia para poder trabajar con ella.
EthernetServer()
Esta es la función que nos permite declarar un objeto tipo EthernetServer.
Su sintaxis sería:
1 |
EthernetServer server = EthernetServer(puerto); |
Donde:
- puerto: es el puerto que utiliza el servidor para comunicarse con los clientes.
Teniendo en cuenta que la función EthernetServer() es el constructor de la clase, también es posible ejecutarla con la siguiente sintaxis.
1 |
EthernetServer server(puerto); |
Cualquiera de las dos sintaxis es igualmente válida.
begin()
Esta función inicia el proceso del servidor, es decir, indica al objeto que esté preparado para recibir conexiones entrantes.
La sintaxis de la función es:
1 |
server.begin(); |
Donde:
- server: el objeto EthernetServer utilizado
Esta función no admite parámetros y tampoco retorna ningún valor.
available()
Mediante esta función se comprueba si existe algún cliente conectado al servidor con datos disponibles para leer.
La sintaxis de la función es:
1 |
cliente = server.available() |
Donde:
- server: es el objeto utilizado
- cliente: es una instancia de la clase EthernetClient que permite leer y enviar datos a la aplicación cliente.
Principales funciones de la clase EthernetClient
La clase EthernetClient la puedes utilizar para dos cosas:
- Cuando quieres que tu Arduino se comporte como un cliente, dicho de otra manera, deseas conectarte a un servidor.
- Cuando utilizas la placa Arduino como servidor y quieres comunicarte con un cliente que se ha conectado a la placa.
En este caso Arduino actúa como servidor solo se utiliza la segunda funcionalidad.
A continuación, veras las funciones que necesitas conocer para utilizar Arduino como servidor.
remoteIP()
Esta función permite conocer la dirección IP del cliente.
1 |
IP = client.remoteIP(); |
Donde:
- cliente: es el objeto EthernetClient que representa al cliente.
- IP: dirección IP del cliente.
Ejemplo de uso:
1 2 3 4 |
// obtener cliente connectado al servidor EthernetClient client = server.available(); // Obtener dirección IP del cliente IP = client.remoteIP(); |
available()
Esta función retorna la cantidad de bytes disponibles para leer desde el cliente, es decir, indica cuántos bytes ha enviado el cliente a nuestro servidor en el Arduino.
1 |
int len = client.available(); |
Donde:
- cliente: es el objeto EthernetClient que representa al cliente
- len: es la cantidad de bytes disponibles para leer.
Ejemplo de uso:
1 2 3 4 |
int len = client.available(); Serial.print("Datos enviados por el cliente: "); Serial.println( len ); |
read()
La función read() permite recibir datos del cliente. Funciona igual que cuando leemos datos del monitor serie con la clase Serial.
1 |
c = client.read(); |
Donde:
- cliente: es el objeto EthernetClient que representa al cliente
- c: es el byte leído desde el cliente
Ejemplo de uso:
1 2 3 |
c = client.read(); Serial.print(c); |
print() y println()
Es posible utilizar las funciones print() y println() tal y como se utilizan con la clase Serial. La diferencia es que en este caso la información es enviada al cliente y no al monitor serie.
Por ejemplo, si se desea enviar el valor de la función millis() se podría hacer de la siguiente manera:
1 2 |
client.print("Tiempo:"); client.print( millis() ); |
Muestra la temperatura y humedad en una web con Ethernet Shield y Arduino
Ya tienes la teoría necesaria y conoces las librerías que permiten aplicarla, ahora queda armar el monitor de temperatura y humedad.
Con él podrás saber la temperatura y la humedad desde tu móvil, tu ordenador o cualquier dispositivo que posea un navegador web.
Para este proyecto necesitarás:
- 1x Router *
- 1x Arduino MEGA **
- 1x Shield Ethernet ***
- 1x Sensor DHT11 o DHT22
- 2x Cables de red
- 1x Ordenador
* 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
*** Cualquier versión del Shield es válida.
Si ya lo tienes todo comenzamos el montaje.
Montaje del circuito Ethernet Shield con Arduino
Empezamos conectando el Ethernet Shield con el Arduino. Teniendo en cuenta que se trata de un Shield esto es fácil, simplemente es necesario hacer coincidir los conectores del módulo ethernet con los del Arduino.
Después se conecta el sensor DHT11. En este caso yo he utilizado el pin digital 5 para conectarlo.
En la imagen siguiente puedes ver el esquema del circuito. Ten en cuenta que encima está el Ethernet Shield.
Aquí puedes ver como me quedo el montaje utilizando un Ethernet Shield V1.
Con las conexiones listas es hora de preparar el código para conectar el Arduino a la red.
Código Ethernet Shield con Arduino
Incluye las librerías necesarias.
1 2 3 4 |
#include <SPI.h> #include <Ethernet.h> #include <Adafruit_Sensor.h> #include <DHT.h> |
Se han incluido las librerías Ethernet y SPI, ya que son necesarias para el control del Ethernet Shield. Estas librerías ya vienen instaladas con el IDE de Arduino.
También se han incluido Adafruit_Sensor y DHT para el uso del sensor DHT11 y se han declarado dos constantes para indicar el tipo de sensor a utilizar y el pin digital empleado para la comunicación.
1 2 |
#define DHTPIN 5 // pin digital conectado al sensor DHT. #define DHTTYPE DHT11 // tipo de sensor DHT |
Lo próximo es definir la dirección física o MAC a utilizar. Esta viene usualmente impresa en una etiqueta por la parte inferior del Ethernet Shield.
En caso de que tu módulo no cuente con dicha etiqueta puedes utilizar la misma del ejemplo.
1 |
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xA0, 0x88 }; |
Los números en la etiqueta están escritos en hexadecimal, por tanto cuando los escribas en el código es necesario anteponerles “0x”.
Lo siguiente es definir una dirección IP estática, de esta forma el servidor (placa Arduino) siempre tendrá la misma dirección IP. Para hacer esto vamos a encender el router y conectar el ordenador por el puerto ethernet.
Cuando hacemos esto el router configura automáticamente los parámetros de red del ordenador. Para verificar dichos parámetros es necesario ir a la configuración de red:
- Si eres usuario de Linux o MacOS puedes abrir un terminal y ejecutar el comando ifconfig. Este te permite ver la configuración de red del sistema. Aquí puedes obtener la dirección IP y la máscara de red.
- Si eres usuario de Windows puedes abrir la consola y ejecutar el comando ipconfig. De esta forma obtienes la dirección IP y la máscara de red.
La dirección IP a configurar en el Arduino debe ser igual a la obtenida por el ordenador cambiando el último byte. Por ejemplo, en este caso he obtenido la dirección 192.168.1.101 y he decidido utilizar la dirección 192.168.1.123.
1 2 |
// dirección ip IPAddress ip(192,168,1,123); |
Hay que ser muy cuidadosos al asignar la dirección, ya que si se configura una dirección inválida el Arduino no será capaz de comunicarse con la red.
Ahora se crea una instancia de la clase EthernetServer que espera conexiones utilizando el puerto 80. Se utiliza el puerto 80, ya que este es el destinado para comunicación web con el protocolo HTTP.
1 |
EthernetServer server = EthernetServer(80); |
Se declara un objeto DHT para gestionar el sensor de DHT11, es decir, para leer la temperatura y la humedad.
También se declaran dos variables tipo float para almacenar esos valores y una variable tipo long para determinar los intervalos de lectura del sensor.
1 2 3 |
DHT dht(DHTPIN, DHTTYPE); float temperature, humidity; long last_read = 0; |
Función setup()
En la función setup() se inicializa sensor DHT y el monitor serie. Después se inicializa el Ethernet Shield utilizando la MAC y la IP previamente definidas.
1 2 3 4 5 6 7 8 9 10 11 12 |
void setup() { //Inicializar sensor DHT11 dht.begin(); // Inicializar puerto serie a 9600 baudios Serial.begin(9600); Serial.println("Servidor Web Ethernet Temperatura & Humedad"); // Iniciar la conexión Ethernet Ethernet.begin(mac, ip); |
A continuación, se procede a verificar el estado.
- Se emplea la función Ethernet.hardwareStatus() para determinar si el Ethernet Shield está conectado correctamente.
- Con la función Ethernet.linkStatus() se comprueba el estado del cable de red.
Finalmente se inicializa el servidor web.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Verificar que el Ethernet Shield está correctamente conectado. if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield no presente :("); while (true) { delay(1); // do nothing, no point running without Ethernet hardware } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("El cable Ethernet no está conectado o está defectuoso."); } // Iniciar el servidor server.begin(); } |
Función loop()
En la función loop() se comprueba el tiempo transcurrido desde la última lectura del sensor de temperatura. Si este tiempo es mayor a ocho segundos se actualizan los valores de temperatura y humedad ejecutando la función updateDHT().
Luego de verificar y actualizar la información se comprueba si algún cliente ha realizado alguna solicitud al servidor. Para esto se ejecuta la función listenForClients().
1 2 3 4 5 6 7 8 9 10 |
void loop() { if ( millis() - last_read > 8000) { // actualizar cada 8 segundos updateDHT(); last_read = millis(); } listenForClients(); } |
Función updateDHT()
La función updateDHT() simplemente lee los valores de temperatura y humedad del sensor y comprueba que sean válidos. En ese caso, actualiza las variables globales temperature y humidity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void updateDHT() { float h = dht.readHumidity(); //Obtener temperatura en grados celcius float t = dht.readTemperature(); if ( isnan(h) || isnan(t) ) { Serial.print( F("Error de lectura en el lector DHT11!!!") ); return; } // actualizar las variables globales. temperature = t; humidity = h; } |
Función listenForClients()
La función listenForClients() comprueba si existe alguna solicitud de algún cliente y en respuesta envía la temperatura y la humedad de forma tal que se pueda visualizar en cualquier navegador.
Para comprobar si existe alguna solicitud se utiliza la instrucción server.available() y se comprueba que el objeto retornado sea válido.
1 2 3 4 5 |
void listenForClients() { // listen for incoming clients EthernetClient client = server.available(); if (client) { |
Si se ha detectado una solicitud se imprime al monitor serie la dirección IP del cliente que realizó la realizó y entonces es leída.
Teniendo en cuenta que una solicitud HTTP termina con una línea en blanco es necesario leer caracteres desde el cliente hasta obtener dos caracteres de fin de línea (‘\n’) consecutivos. Toda la solicitud es mostrada en el monitor serie.
Si entre los dos caracteres existe uno que sea de retorno de carro (‘\r’), también se considera como el fin de la solicitud.
Una vez se detecte el fin de la solicitud se envía la cabecera HTTP seguida de los datos de temperatura y humedad en formato HTML.
Si no tienes experiencia con HTML puedes leer el artículo sobre HTML 5 que está en el blog. También te recomiendo investigar editores WYSIWYG (en inglés, «lo que ves es lo que obtienes») como Quackit.
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 |
boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); if (c == '\n' && currentLineIsBlank) { // Enviar cabecera de respuesta http // protocolo HTTP 1.1 client.println("HTTP/1.1 200 OK"); // Formato del contenido 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"); client.println(); // Enviar página web en HTML client.println("<!DOCTYPE HTML>"); client.println("<html>"); // Enviar temperatura client.print( "Temperatura: " ); client.print( temperature, 0 ); client.println( "°C<br/>" ); // Enviar humedad client.print( "Humedad relativa: " ); client.print( humidity, 0); client.println( " %<br/>" ); client.println("</html>"); 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; } } } |
Finalmente se espera un tiempo para que el navegador reciba la información y se cierra la conexión con el cliente.
1 2 3 4 5 6 7 |
// esperar un tiempo para que el navegador reciba la información delay(1); client.stop(); // cerrar la conexión Serial.println("client desconectado"); } } |
Aquí tienes todo el código para que hagas las modificaciones pertinentes y 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 |
/* Servidor Web Servidor web sencillo utilizando Ethernet Shield que muestra la temperatura y la humedad leída desde un sensor DHT11. */ #include <SPI.h> #include <Ethernet.h> #include <Adafruit_Sensor.h> #include <DHT.h> #define DHTPIN 5 // pin digital conectado al sensor DHT. #define DHTTYPE DHT11 // tipo de sensor DHT // dirección MAC. byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xA0, 0x88 }; // dirección ip IPAddress ip(192,168,1,123); // with the IP address and port you want to use // (port 80 is default for HTTP): EthernetServer server = EthernetServer(80); DHT dht(DHTPIN, DHTTYPE); float temperature, humidity; long last_read = 0; void setup() { //Inicializar sensor DHT11 dht.begin(); // Inicializar puerto serie a 9600 baudios Serial.begin(9600); Serial.println("Servidor Web Ethernet Temperatura & Humedad"); // Iniciar la conexión Ethernet Ethernet.begin(mac, ip); // Verificar que el Ethernet Shield está correctamente conectado. if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield no presente :("); while (true) { delay(1); // do nothing, no point running without Ethernet hardware } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("El cable Ethernet no está conectado o está defectuoso."); } // Iniciar el servidor server.begin(); } void loop() { if ( millis() - last_read > 8000) { // actualizar cada 8 segundos updateDHT(); last_read = millis(); } listenForClients(); } void updateDHT() { float h = dht.readHumidity(); //Obtener temperatura en grados celcius float t = dht.readTemperature(); if ( isnan(h) || isnan(t) ) { Serial.print( F("Error de lectura en el lector DHT11!!!") ); return; } // actualizar las variables globales. temperature = t; humidity = h; } void listenForClients() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.print("nuevo cliente conectado desde "); Serial.println( client.remoteIP() ); boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); if (c == '\n' && currentLineIsBlank) { // Enviar cabecera de respuesta http // protocolo HTTP 1.1 client.println("HTTP/1.1 200 OK"); // Formato del contenido 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"); client.println(); // Enviar pagina web en HTML client.println("<!DOCTYPE HTML>"); client.println("<html>"); // Enviar temperatura client.print( "<h1>Temperatura: " ); client.print( temperature, 0 ); client.println( "°C<br/>" ); // Enviar humedad client.print( "Humedad relativa: " ); client.print( humidity, 0); client.println( " %<br/></h1>" ); client.println("</html>"); break; } if (c == '\n') { // comienza una nueva línea currentLineIsBlank = true; } else if (c != '\r') { // se ha escrito un caracter en la nueva linea currentLineIsBlank = false; } } } // esperar un tiempo para que el navegador reciba la información delay(1); client.stop(); // cerrar la conexión Serial.println("client desconectado"); } } |
Prueba de funcionamiento
Una vez el código sea cargado al Arduino lo alimentamos y lo conectamos al router mediante un cable ethernet.
Para comprobar el funcionamiento necesitas conectar el ordenador al router utilizando otro cable ethernet.
Ahora es necesario abrir el navegador e ir a la barra de direcciones, escribimos la dirección IP del Arduino (en mi caso sería 192.168.1.123) y presionamos la tecla ENTER.
Si todo marcha bien, en el navegador se mostrará la temperatura y la humedad censadas por el DHT11.
En la siguiente imagen puedes ver el resultado obtenido.
En caso de que el router cuente con Wifi entonces puedes acceder también desde el navegador de tu teléfono móvil. Aquí puedes ver el resultado obtenido en el mío.
Conclusión tutorial Ethernet Shield con Arduino
En este artículo te he hablado de las teoría básica sobre redes de datos. Algo fundamental cuando quieres utilizar un Ethernet Shield con Arduino.
Luego hemos visto las características más importantes sobre el Ethernet Shield a nivel de hardware.
Para poder trabajar con el Ethernet Shield de Arduino se recomienda utilizar la librería Ethernet y las tres clases principales de esta librería: Ethernet, EthernetServer y EthernetClient.
Hemos visto un ejemplo muy simple para mostrar la temperatura y humedad a través de una página web.
Pero se pueden hacer muchas cosas más. Te animo a que hagas tus propias pruebas y proyectos con el Ethernet Shield y las compartas aquí abajo, en los comentarios.
Gracias a Shutterstock por ceder los derechos de las imágenes.