Shield Ethernet W5100 – Primeiros passos na criação de um Servidor Web com Arduino
Em uma das nossas publicações anteriores ensinamos como você deve proceder para criar um Servidor Web com o NodeMCU. Neste tutorial, iremos utilizar um Shield Ethernet W5100 para criar um Servidor Web que terá como função fornecer uma página web contendo informações enviadas pelo Arduino UNO.
[toc]
O que é um Servidor Web?
Ao navegarmos pelo gigante universo de possibilidades da internet, podemos não nos dar conta do que existe por trás disso tudo.
A internet é uma união de redes de computadores em nível mundial conversando entre si através de um conjunto próprio de protocolos de comunicação, como por exemplo, o TCP/IP, que por sua vez, consiste em um protocolo para transmissão de informações orientado à conexão, ou seja, cuja função consiste em permitir que as maquinas se comuniquem e gerenciem o estado atual da transmissão.
– Os Servidores
Um dos protagonistas desse universo são os servidores. A grosso modo, esses servidores são computadores responsáveis por fornecer e receber dados dos diversos clientes, atuando como centralizadores de informação.
Indo um pouco a fundo, um servidor consiste em um software dentro um computador centralizador. Através de uma rede particular ou da internet, esse servidor pode receber dados de clientes bem como fornecê-los.
O estabelecimento das relações entre o conjunto Servidor/Cliente é baseado em um sistema de recebimento, processamento e resposta, no qual, o servidor recebe, processa e responde a requisições feitas por um Cliente através de algum protocolo de comunicação.
– O HTTP – Protocolo de Transferência de Hipertexto
Um dos principais exemplos da relação Servidor/Cliente é a relação entre os computadores que atuam como servidores hospedando sites e os navegadores que utilizamos em nossos computadores ou celulares, os clientes. Neste tipo de relação, utiliza-se para estabelecer a comunicação, o procotolo o HTTP (Hypertext Transfer Protocol), o qual, é responsável pelo tratamento dos pedidos e respostas entre cliente e servidor na World Wide Web ou em uma rede local. Nesse contexto, chamamos os servidores de Servidores Web.
– HTML – Linguagem de Marcação de Hipertexto
As informações que o Servidor Web envia para seu navegador a partir de uma requisição HTTP feita pelo mesmo, pode ocorrer em alguns determinados formatos que precisarão ser interpretados. Um desses formatos é o HTML (HyperText Markup Language), que por sua vez, é uma linguagem utilizada na construção de páginas na Web.
O Shield Ethernet W5100
Como sabemos, os shields compatíveis com o Arduino UNO são placas de circuito que podem ser conectadas sobre o mesmo, encaixando-se perfeitamente, com o intuito de expandir suas capacidades em determinada vertente.
Neste tutorial, apresentamos o Shield Ethernet W5100, que por sua vez, consiste em um shield dotado de dois módulos, um módulo Ethernet que irá permitir a conexão do Arduino UNO, em um primeiro momento, com uma rede local e um módulo para cartão SD.
Sendo assim, perceba que é perfeitamente possível utilizar este módulo somente para ler/escrever dados em um cartão de memória ou apenas para conectar o Arduino UNO a uma rede local.
Neste tutorial iremos utilizar apenas o módulo Ethernet do shield em questão, pois, iremos elaborar uma pagina simples para ser apresentada ao usuário através do navegador, no entanto, o módulo de cartão SD é muito útil para conter arquivos necessários para a construção de uma página mais rica em informações, como por exemplo, imagens.
Mãos à obra – Criando um Servidor Web com o Arduino UNO e o Shield Ethernet W5100
Nesta seção iremos demonstrar todos os passos que você deve seguir para aprender a criar um Servidor Web.
Componentes necessários
Para reproduzir este projeto, você irá precisar dos seguintes componentes:
Montando o projeto
Gostaríamos de sugerir que você tenha bastante cuidado no momento em que for encaixar o Shield Ethernet W5100 no Arduino UNO, pois, além da possibilidade de entortar os pinos do shield, você também pode se machucar.
Lembre-se que o shield ethernet W5100 possui uma série de pinos em sua parte inferior, tanto nas laterais como em sua parte dianteira, portanto, antes de pressionar o mesmo sobre o Arduino UNO, certifique-se de que os pinos estejam levemente posicionados em suas respectivas entradas para que então você possa ir realizando o encaixe lentamente.
Realizando as conexões
Para reproduzir este projeto, garanta que o seu Shield Ethernet W5100 esteja ligado corretamente a uma das portas LAN presentes no seu modem ou roteador.
Programando
Este programa foi elaborado a partir do código-exemplo da biblioteca Ethernet.h denominado WebServer.
Antes de utilizar este código, leia a seção Entendendo a fundo para adaptar os trechos necessários para o funcionamento da sua aplicação.
#include <SPI.h> #include <Ethernet.h> byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 25, 16); EthernetServer server(80); void setup() { Ethernet.begin(mac, ip); server.begin(); } void loop() { EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); 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>Servidor Web VDS</title>"); client.println("</head>"); client.println("<body>"); client.println("<h1>Meu primeiro Servidor Web</h1>"); client.println("<p>Esperamos que voce tenha gostado deste tutorial</p>"); client.println("</body>"); client.println("</html>"); break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } delay(1); client.stop(); } }
Colocando para funcionar
Veja como ficou nosso primeiro Servidor Web.
Entendendo a fundo
Software
– Incluindo as bibliotecas a serem utilizadas no projeto
Inicialmente, observe que foi necessário incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h é a responsável pela comunicação dos módulos do Shield Ethernet W5100 com o Arduino UNO utilizando o protocolo SPI e a biblioteca Ethernet.h atua possibilitando a conexão do conjunto, em um primeiro momento, com uma rede local.
#include <SPI.h> #include <Ethernet.h>
– Definindo o endereço MAC do Arduino UNO
O próximo passo consiste em definir o endereço MAC que será atribuído ao Arduino UNO.
Na prática, o endereço MAC pode ser qualquer um, desde que seja único na rede. Como sugestão, copie a sentença abaixo.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
– Definindo o endereço IP do Arduino UNO
Além do endereço MAC definido anteriormente, torna-se necessário definir um endereço IP para o nosso Arduino UNO. Isso é imprescindível para que seja possível estabelecer a conexão entre o mesmo e a rede.
Este endereço deve estar disponível na sua rede local para que possa ser utilizado
Existem várias maneiras de encontrar um endereço válido na sua rede local, de modo que, demonstraremos uma forma bastante simples de realizar este procedimento, confira abaixo:
- Acesse um computador que esteja conectado na sua rede local
- Abra o Prompt de Comando do Windows (supondo que o sistema operacional seja Windows)
- Digite ipconfig
Neste momento, um conjunto de informações será disponibilizado, no entanto, o dado que requer sua atenção é justamente o endereço IP da máquina que você está utilizando (ele estará apresentado pelo nome IPV4).
Primeiramente, repare que o endereço IP destacado possui quatro partes separadas por pontos. Para encontrarmos um possível endereço disponível em nossa rede local, basta modificarmos a última parte do endereço encontrado, como por exemplo, o endereço 192.168.25.16 . Geralmente, este procedimento é suficiente para encontrar possíveis endereços disponíveis em redes locais pequenas, como as das nossas casas.
IPAddress ip(192, 168, 25, 16);
– Criando o objeto server
Neste momento, cria-se um objeto chamado server, que por sua vez, será responsável por representar o Servidor Web no código do Arduino UNO.
Note que ao criarmos o objeto, passamos o número 80 como parâmetro, pois estamos determinando a porta que o Servidor Web utilizará para enviar as páginas web que serão criadas posteriormente.
A título de curiosidade, quando digitamos o endereço de algum site no navegador, ele automaticamente procura a porta 80 do servidor no qual está se conectando, de modo que, se o serviço responsável por disponibilizar as páginas da web para o cliente estiver em outra porta, devemos especificar esta no endereço do site citado, por exemplo: www.exemplo.com.br:1234
EthernetServer server(80);
– Iniciando a comunicação com a rede local e o Servidor Web
Na função setup() iniciamos a conexão com a rede local através da função Ethernet.begin() (passando como parâmetro os endereços MAC e IP definidos anteriormente) e também iniciamos o Servidor Web por meio da sentença server.begin() (lembre-se que server é o objeto criado para representar o Servidor Web no código).
Ethernet.begin(mac, ip); server.begin();
Veja como ficou nossa função setup():
void setup() { Ethernet.begin(mac, ip); server.begin(); }
– Respondendo as requisições de um navegador
Verificando se existe requisição de conexão
Primeiramente, na função loop(), temos a sentença server.available() que verifica se existe tem algum cliente tentando fazer uma conexão. Como dito anteriormente, vamos chamar de cliente, o navegador que está tentando fazer a conexão com o Servidor Web através do endereço IP do mesmo. Repare que foi criada uma variável para conter o valor retornado pela função server.available().
EthernetClient client = server.available();
Em seguida, temos uma função if() cujo conteúdo será executado apenas no caso de termos um cliente tentando se conectar ao Servidor Web criado e iniciado anteriormente.
if (client) { ***** Conteúdo da função if() ***** }
Supondo que temos um cliente tentando se conectar com o nosso Servidor Web, primeira sentença do conteúdo da função if() apresentada anteriormente consiste na declaração de uma variável de controle booleana que será utilizada na leitura da requisição feita pelo navegador.
boolean currentLineIsBlank = true;
Posteriormente, temos uma função while(), que por sua vez, fará com que a execução do programa fique restrita ao seu conteúdo enquanto o parâmetro passado para mesma for verdadeiro. O parâmetro citado corresponde à sentença client.connected(), responsável por retornar verdadeiro ou falso, caso o cliente esteja conectado ou não com o Servidor Web, respectivamente.
Portanto, enquanto o cliente estiver conectado com o nosso servidor, o programa ficará preso na função while().
while (client.connected()) { ***** Conteúdo da função while() }
Imagine que a conexão do cliente (navegador) com o nosso Servidor Web tenha sido estabelecida. Neste momento o programa irá se preparar para receber a requisição feita pelo cliente, que por sua vez, é dada em forma de um grande texto, logo, utilizamos a função if() juntamente com a sentença client.available() para verificar se ainda existe alguma informação proveniente do navegador para ser lida. Caso exista, o conteúdo desta função será executado.
if (client.available()) { ***** Conteúdo da função if() ***** }
Lendo a requisição do cliente
Caso exista alguma informação para ser lida, utilizamos a sentença client.read() para ler caractere por caractere do grande texto de requisição citado anteriormente, de modo que, a cada passagem por esta sentença (lembre-se que isso é feito de maneira cíclica), um novo caractere será armazenado na variável do tipo char c.
char c = client.read();
Após preenchermos a variável c com um determinado caractere da requisição, fazemos uma série de comparações deste com alguns parâmetros específicos para saber se o Arduino UNO recebeu o pacote de informações inteiro ou não.
O objetivo aqui não é entender tudo que esta vindo do cliente mas simplesmente entender que existe uma solicitação acontecendo e que após o término da mesma, vamos devolver como resposta uma pagina da web, sendo assim, devemos esperar que venha o texto completo de solicitação, até a ultima linha.
Caso a condição desta primeira função de tratamento da variável c seja verdadeira, quer dizer que recebemos o pacote completo e que o conteúdo desta função if() será executado.
if (c == '\n' && currentLineIsBlank) { ***** Conteúdo da função if() ***** }
Enviando informações para o navegador
Neste momento, nós iremos criar as funções necessárias para que o nosso Arduino UNO envie uma página da web como resposta à solicitação do navegador. As instruções que utilizaremos para enviar informações ao navegador serão baseadas na sentença client.println().
Primeiramente, enviamos um cabeçalho padrão informando ao navegador que estamos mandando uma página da web utilizando o protocolo HTTP, feita utilizando a linguagem HTML.
client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println();
– Usando HTML para montar a página web
HTML é uma linguagem, porém, não exatamente uma linguagem de programação mas sim uma linguagem de marcação, ou seja, através desta nós enviamos comandos para um navegador, que por sua vez, irão orientar o mesmo na montagem da pagina.
Uso de tags em HTML
Em um primeiro momento, nós devemos saber que a linguagem HTML é composta por elementos que iremos chamar de tags. Estes consistem em comandos que são enviados para o navegador para informarmos alguma coisa ao mesmo, para pedirmos que ele mostre algo, para definirmos o formato de fonte que queremos, se é negrito, qual cor, entre outros.
Todos as tags em HTML são declaradas entre os sinais de maior e menor <nome_da_tag>. Torna-se importante ressaltar que muitas tags possuem uma abertura e um fechamento (este possui o mesmo nome da tag, porém, com uma “/” antes do respectivo nome, por exemplo, </nome_da_tag>), de modo que, tudo o que está entre a abertura e o fechamento de uma determinada tag será afetado pelo comando gerado pela função da mesma.
A estrutura da página em HTML
Vamos começar a entender a estrutura de uma pagina em HTML. Primeiramente, qualquer pagina em HTML precisa possuir a tag <html> cuja função é indicar para o navegador que estamos começando um bloco de programação utilizando a linguagem HTML (opcionalmente podemos utilizar também a tag <!DOCTYPE HTML> para informar o tipo documento, de modo que, se não colocarmos isto, o navegador entenderá da mesma forma) e o fechamento da mesma </html>, que por sua vez, indica o fim do bloco citado.
client.println("<!DOCTYPE HTML>"); client.println("<html>"); . . ***** Conteúdo da página ***** . . client.println("</html>");
Dentro do bloco citado anteriormente, temos o conteúdo da página que queremos enviar para o navegador, de modo que, neste, devemos ter pelo menos dois blocos, um responsável pelas informações gerais do documento, limitado pelo uso do par <head></head> e o outro, por sua vez, deve conter o corpo da página e está entre as tags <body> e </body>.
client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<head>"); . . ***** Bloco 1 ***** . . client.println("</head>"); client.println("<body>"); . . ***** Bloco 2 ***** . . client.println("</body>"); client.println("</html>");
Definido o título para a página
Neste momento, vamos utilizar apenas uma tag dentro do bloco 1, denominada <title>, cuja função consistirá em definir um título para a página (este título aparecerá na aba do navegador). Para executarmos a ação proposta, devemos colocar o título desejado entre o par <title></title>.
client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<head>"); client.println("<title>Servidor Web VDS</title>"); client.println("</head>"); client.println("<body>"); . . ***** Bloco 2 ***** . . client.println("</body>"); client.println("</html>");
Veja como ficou o título da nossa página:
Escrevendo o corpo da página web
Quanto ao corpo da página, a primeira coisa que faremos será colocar um título visível na própria página. Para realizar este procedimento, utilizaremos a tag <h1>, que por sua vez, consiste em uma tag de cabeçalho, cuja função consiste em apresentar um determinado texto em um modelo predefinido. Lembre-se que os textos que tiverem fora do par <h1></h1> serão apresentados fora do padrão citado.
client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<head>"); client.println("<title>Servidor Web VDS</title>"); client.println("</head>"); client.println("<body>"); client.println("<h1>Meu primeiro Servidor Web</h1>"); client.println("</body>"); client.println("</html>");
Veja como está nossa página até agora
Opções de cabeçalhos
Devemos ressaltar que não há nenhum problema em utilizar vários cabeçalhos iguais, portanto, você pode tranquilamente criar vários textos utilizando o cabeçalho h1, pois, ele apenas indica uma certa formatação. Além do cabeçalho que já utilizamos, temos também os cabeçalhos h2,h3,h4,h5,h6, os quais, nesta ordem, possuem fontes cada vez menores.
Escrevendo um texto simples
Por fim, utilizaremos uma tag voltada para a escrita de textos simples. Esta pode ser referenciada no código pelo par <p></p>.
client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<head>"); client.println("<title>Servidor Web VDS</title>"); client.println("</head>"); client.println("<body>"); client.println("<h1>Meu primeiro Servidor Web</h1>"); client.println("<p>Esperamos que voce tenha gostado deste tutorial</p>"); client.println("</body>"); client.println("</html>");
Veja nosso resultado final:
– Verificando se a requisição foi finalizada
Após o desenvolvimento da nossa página, saímos da função if() utilizada para saber se a requisição foi finalizada e encontramos outras duas funções if() que cumprem o teste das condições não contempladas pela primeira, ou seja, atuam no tratamento da variável c enquanto a requisição não foi finalizada.
if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; }
Por fim utilizamos a função delay() para garantir que o navegador receba esta informação que estamos mandando e também a sentença client.stop() para parar a conexão.
delay(1); client.stop();
Considerações finais
Neste tutorial, demonstramos como você pode dar os primeiros passos na criação de um Servidor Web utilizando um Arduino UNO e um Shield Ethernet W5100. Esta foi apenas a primeira parte de uma série de artigos sobre a criação de Servidores Web, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.
10 Comments
Deixe uma pergunta, sugestão ou elogio! Estamos ansiosos para ter ouvir!Cancelar resposta
Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.
Tem como eu usar esse ethernet shields para controlar a iluminação da minha casa a distancia, digamos de outra cidade, por exemplo.
e teria uma usando o cartão sd?
olá bom dia adorei a explicação no entanto tenho uma duvida, como faço para que esta pagina conecte a uma base de dados e como o arduino pode ler as informações vinda da base de dados? obrigada
oi bom dia gostei da explicação mas teria uma utilizando um cartao sd
Boa tarde, muito boa sua explicação, parabéns, eu tenho um problema que acho que vc pode me ajudar. Fiz um projeto onde tenho 3 paginas html, utilizo bootstrap, js e ajax ( estou aprendendo )como pluguns, para não ficar pesado na mem do arduino UNO, estou criando tudo em um sd card do ethernet W5100, qdo executo o arduino, só consigo chamar a página index.htm, as demais dentro dela não funciona, acho que é problema de path, mas não conheço de programação web, estou aprendendo apenas para suprir minha necessidade, caso vc tenha disponibiklidade em me ajudar, posto aqui o cenário, desde já, grato
Olá, tenho uma dúvida. Segui o tutorial e deu certo, mas não consigo abrir mais de uma página ao mesmo tempo. Li em algum lugar que este Ethernet shield suporta até 04 conexões simultâneas. ..o que poderia ser ?
Ola Daniel, show, parabéns pelo portal, tenho uma duvida como fazer para colocar mais de um sensor tipo 10 sensores? valeu Claudio
Boa explicação Daniel, parabéns, eu estou em duvida de como comunicar o usar paginas mais complexas no cartão do memória, fazer com que o Arduíno buscasse as paginas presentes no cartão de memória, acho que daria um bom tutorial para ser feito.
Muito obrigado Wagner
muito boa explicação.