Shield Ethernet W5100 – Acionamento remoto de relés com HTML
Dando prosseguimento ao conteúdo relacionado à criação de Servidores Web utilizando o Arduino UNO juntamente com o Ethernet Shield W5100. Anteriormente, vimos quais eram os procedimentos básicos para criar um Servidor Web, para efetuar a leitura de valores provenientes de elementos ligados tanto às entradas analógicas quanto às digitais e também para realizar o acionamento das portas de saída digital. Neste tutorial você aprenderá como criar uma aplicação na qual será possível criar uma interface, que por sua vez, será apresentada no seu navegador de internet, para que seja possível realizar acionamento de relés.
É importante, para o pleno entendimento desse tutorial, que o leitor tenha lido todos os tutoriais anteriores:
- Shield Ethernet W5100 – Criando um Servidor Web com Arduino
- Shield Ethernet W5100 – Monitorando sensores com um Servidor Web
- Shield Ethernet W5100 – Controlando saídas via Servidor Web
[toc]
Mãos à obra – Desenvolvendo o sistema de acionamento remoto de relés com HTML
Componentes necessários
Montando o projeto
Programando
#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(); pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); digitalWrite(2,HIGH); digitalWrite(3,HIGH); digitalWrite(4,HIGH); digitalWrite(5,HIGH); } void loop() { String req_str; EthernetClient client = server. available(); if (client) { req_str = ""; boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); req_str += c; if(c == '\n' && currentLineIsBlank) { unsigned int posicao_inicial = req_str.indexOf("GET") + 4; unsigned int posicao_final = req_str.indexOf("HTTP/") - 1; String parametro = req_str.substring(posicao_inicial,posicao_final); if(parametro != "/favicon.ico") { 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 lang=\"pt-br\">"); client.println("<head>"); client.println("<meta charset= \"UTF-8\"/>"); client.println("<title>Acionamento de relés</title>"); client.println("</head>"); client.println("<body>"); client.println("<h1>Sistema de acionamento de relés V.1</h1>"); client.println("<hr/>"); client.println("<h2>Portas digitais</h2>"); // client.println("<p>Porta D2:</p>"); client.println ("<form method=\"get\">"); criarformulario (client, parametro); client.println ("</form>"); client.println ("</body>"); client.println ("</html>"); } break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } } } delay(1); client.stop(); } } void criarformulario(EthernetClient client_aux, String parametro_aux) { for(int i = 0; i<2; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>PINO NÃO UTILIZADO (DESABILITADO)</br>"); } for(int i = 2; i<6; i++) { client_aux.println("Porta D" + String(i)+ " (Relé " + String (i - 1) + ") :"); if(parametro_aux.indexOf("D" + String(i)+ "=1") > -1) { client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" checked> LIGADA</br>"); digitalWrite(i,LOW); } else { client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\"> DESLIGADA</br>"); digitalWrite(i,HIGH); } } for(int i = 6; i<10; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>PINO NÃO UTILIZADO (DESABILITADO)</br>"); } for(int i = 10; i<14; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>EM USO PELO ETHERNET SHIELD W5100 (DESABILITADO)</br>"); } }
Colocando para funcionar
Entendendo a fundo
Software
Antes de começarmos com a explicação do código, gostaríamos de ressaltar que iremos apresentar apenas os detalhes dos tópicos não contemplados nos tutoriais anteriores, pois, desta maneira, será mais fácil focar nas partes referentes às atualizações feitas sobre o programa já existente, portanto, caso você tenha alguma dúvida sobre alguma parte do programa que não seja explicada neste momento, sugerimos que acesse o nossos materiais citados anteriormente.
– Definindo os pré-requisitos para o funcionamento do código
Inicialmente, devemos incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h, responsável pela comunicação dos módulos do shield com o Arduino UNO utilizando o protocolo SPI e a biblioteca Ethernet.h que atua possibilitando a conexão do conjunto, em um primeiro momento, com uma rede local.
Após a inclusão das bibliotecas citadas, devemos definir um endereço MAC (lembre-se que este pode ser qualquer um, desde que seja único em sua rede local) e um endereço IP (este deve ser um endereço válido e disponível dentro da sua rede local). Além disso, devemos criar o objeto que será responsável por representar o Servidor Web no código (aqui, chamamos este de server) e relacioná-lo com a porta 80.
#include <SPI.h> #include <Ethernet.h> byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192, 168, 25, 16); EthernetServer server(80);
– Definindo as configurações iniciais
Dentro da função setup(), devemos determinar o modo de operação dos pinos digitais que serão utilizados (estes terão o papel de saídas digitais) . Além disso, 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).
void setup() { Ethernet.begin(mac, ip); server.begin(); pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); digitalWrite(2,HIGH); digitalWrite(3,HIGH); digitalWrite(4,HIGH); digitalWrite(5,HIGH); }
Observe que além da execução dos procedimentos apresentados anteriormente, nós também optamos por colocar os pinos citados nível alto, pois, os relés do módulo que utilizamos são acionados com nível baixo em suas entradas, portanto, como queremos que eles comecem sem qualquer tipo de acionamento, devemos proporcionar 5 volts em seus respectivos pinos de entrada.
– Entendendo as requisições do navegador
Nos tutoriais anteriores, ressaltamos o mecanismo básico de funcionamento dos códigos voltados para a criação de Servidores Web, o qual, começa através de um procedimento padrão, que por sua vez, consiste em utilizar uma variável para obter caractere por caractere da requisição feita pelo navegador até que esta seja completamente recebida pelo Arduino UNO, de modo que, apenas a partir deste ponto inicia-se o processo de elaboração da página.
Em nosso último tutorial, apresentamos o modo de funcionamento do método GET, portanto, vamos utilizá-lo novamente no envio de informações provenientes dos formulários para o nosso Servidor Web. Entretanto, vamos seguir um caminho um pouco diferente para que você possa ver a existência de outras possibilidades. O primeiro passo neste procedimento será a declaração de uma variável local, do tipo String (esta servirá para armazenar a requisição feita pelo navegador).
void loop() { String req_str; . . .
Em seguida, criamos o processo no qual esta variável será preenchida com os caracteres da requisição.
if (client.available()) { char c = client.read(); req_str += c; . . .
Por fim, declaramos duas variáveis do tipo inteiro sem sinal e uma do tipo String, as quais, serão responsáveis por retirar o que nós chamamos em nosso tutorial anterior de parâmetro da requisição. Além disso, este trecho de código também cumpre o papel de determinar se o parâmetro é o texto /favicon.ico, de modo que, caso não seja (pois neste momento isto não é interessante para nós), seguimos adiante na construção da página.
A explicação das funções que compõem este passo estão demonstradas em nosso tutorial anterior. Você pode acessá-lo clicando aqui!
if(c == '\n' && currentLineIsBlank) { unsigned int posicao_inicial = req_str.indexOf("GET") + 4; unsigned int posicao_final = req_str.indexOf("HTTP/") - 1; String parametro = req_str.substring(posicao_inicial,posicao_final); if(parametro != "/favicon.ico") { . . .
– Enviando o cabeçalho da página
Após termos detectado que o parâmetro da requisição não é o fragmento de texto /favicon.ico, devemos primeiramente enviar o cabeçalho padrão para o navegador.
client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println();
– Desenvolvendo a nossa página
Para começar a desenvolver a nossa página, utilizamos primeiro a sentença <!DOCTYPE html> para informarmos ao navegador que estamos utilizando a versão 5 da linguagem HTML.
client.println("<!DOCTYPE html>");
Como sabemos, entre as tags <head> e </head>, fazemos algumas configurações pertinentes ao funcionamento da página que estamos desenvolvendo. As configurações citadas, correspondem à determinação do conjunto de caracteres que deverá ser utilizado pelo navegador (para apresentar caracteres acentuados) e à inclusão de um título na aba da página do navegador.
client.println("<head>"); client.println("<meta charset= \"UTF-8\"/>"); client.println("<title>Acionamento de relés</title>"); client.println("</head>");
No corpo da página, começamos escrevendo alguns títulos utilizando as tags de cabeçalho <h1> e <h2>.
client.println("<body>"); client.println("<h1>Sistema de acionamento de relés V.1</h1>"); client.println("<hr/>"); client.println("<h2>Portas digitais</h2>"); . . .
Em seguida, adicionamos o formulário e explicitamos que o método que será utilizado para o envio de dados na requisição feita pelo navegador será o GET. Entre as tags <form> e </form>, criamos uma função chamada criarformulario(), a qual, será responsável por criar a interface de comandos na página do navegador.
client.println ("<form method=\"get\">"); criarformulario (client, parametro); client.println ("</form>");
Por último, veja o código responsável pela criação da interface de comando, na íntegra.
client.println("<!DOCTYPE html>"); client.println("<html lang=\"pt-br\">"); client.println("<head>"); client.println("<meta charset= \"UTF-8\"/>"); client.println("<title>Acionamento de relés</title>"); client.println("</head>"); client.println("<body>"); client.println("<h1>Sistema de acionamento de relés V.1</h1>"); client.println("<hr/>"); client.println("<h2>Portas digitais</h2>"); client.println ("<form method=\"get\">"); criarformulario (client, parametro); client.println ("</form>"); client.println ("</body>"); client.println ("</html>");
– Função de criação do formulário
Como dissemos anteriormente, a função criarformulario() será a responsável pela criação da interface de comando que utilizaremos. Esta função é dividida em três blocos, de modo que, o primeiro deles é responsável por criar os checkboxes referentes às portas digitais 0 e 1. Repare que na instrução de criação dos checkboxes (cujo funcionamento já foi apresentado em nossos tutoriais) existe a palavra disabled, a qual, irá fazer com que o checkbox não seja clicável (justamente por não estarmos utilizando estes pinos).
for(int i = 0; i<2; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>PINO NÃO UTILIZADO (DESABILITADO)</br>"); }
O segundo bloco diz respeito à criação dos checkboxes de acionamento dos 4 relés existentes no módulo utilizado. Repare que a estrutura utilizada é a mesma que a anterior, no entanto, utilizamos a função indexOf() para descobrirmos se existe algum elemento do tipo “/?D_=1“ (parâmetro da requisição quando algum checkbox é selecionado). Em caso afirmativo, o checkbox é criado e marcado, em caso negativo, ele é apenas criado, porém sem estar selecionado. Consequentemente, também acionamos o relé (com nível lógico 0) ou não (com nível lógico 1), através da função digitalWrite().
for(int i = 2; i<6; i++) { client_aux.println("Porta D" + String(i)+ " (Relé " + String (i - 1) + ") :"); if(parametro_aux.indexOf("D" + String(i)+ "=1") > -1) { client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" checked> LIGADA</br>"); digitalWrite(i,LOW); } else { client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\"> DESLIGADA</br>"); digitalWrite(i,HIGH); } }
O terceiro e o quarto bloco são semelhantes ao primeiro, no entanto, na quarta estrutura de repetição for, apenas alteramos o texto para sinalizar que os pinos 10 a 13 estão sendo utilizados pelo Shield Ethernet W5100.
for(int i = 6; i<10; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>PINO NÃO UTILIZADO (DESABILITADO)</br>"); } for(int i = 10; i<14; i++) { client_aux.println("Porta D" + String(i)+ ":"); client_aux.println("<input type=\"checkbox\" name=\"D" + String(i) + "\" value=\"1\" onclick=\"submit()\" disabled>EM USO PELO ETHERNET SHIELD W5100 (DESABILITADO)</br>"); } }
Considerações finais
Neste tutorial, demonstramos como você pode fazer para criar um sistema de acionamento de relés para ser utilizado através de um navegador de internet. Para isto, utilizamos um Arduino UNO em conjunto com um Ethernet Shield W5100. Esta foi a quarta 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.
nao carrega para o arduino esse steck,sabe porque?
Muito bom artigo, mas não consigo conectar meu arduino de uma rede externa, fiz até um home no noip, mas não funciona em rede externa, abri porta de roteador, tirei firewall, conectei direto no modem e nada, teria como me ajudar nesta dificuldade minha.