Comunicação Wireless UDP com ESP
Neste material, iremos aprender a fazer uma comunicação Wireless UDP entre dois ESP8266 para transmissão de informações. O grande diferencial do ESP é sua comunicação Wireless com suporte a WiFi, então nada mais justo que aprender a usar isto. Lembrando que este código também funciona para o ESP32.
[toc]
Protocolo UDP
O protocolo UDP, da camada de transporte, nos permite de forma rápida e descomplicada, o envio de informações através da rede. A simplicidade de usar o UDP é compensada ao fato de não ser uma comunicação orientada à conexão, como por exemplo o TCP, logo, não há garantia que os pacotes sejam recebidos de forma ordenada ou se quer sejam recebidos. Usa-lo para aplicações simples é recomendado, já que não são dados críticos; a perda de pacotes (improvável, porém possa acontecer) não é tão prejudicial ao sistema. Iremos transmitir de um Cliente para um Host.
Esta comunicação simples pode ser feita para transmitir dados até um banco de dados em um computador ou informações para outros Micro controladores. As aplicações são as mais diversas e variadas possíveis, novamente, o limite é sua imaginação.
Lembre-se, serão dois ESP8266, um cliente e outro host. Os dois códigos estarão logo abaixo!
Veja como é rápido o processo de envio e recebimento dos dados. O cliente pisca quando envia o pacote e o host pisca após receber o pacote, é tão rápido que os dois parecem piscar juntos:
Mãos à obra
Componentes necessários
- 2 – ESP8266 (Usaremos dois NodeMCU).
- LEDs Onboard.
Hardware
Acenderemos o LED_BUILTIN do NodeMCU para indicar a transmissão de dados. Este LED OnBoard, está conectado ao pino D4 do NodeMCU.
Código do projeto
Cliente
#include <ESP8266WiFi.h>//Biblioteca do WiFi. #include <WiFiUdp.h>//Biblioteca do UDP. WiFiUDP udp;//Cria um objeto da classe UDP. long x;//Variavel para ser enviada. void setup() { pinMode(D4, OUTPUT);//Habilita o LED onboard como saida. digitalWrite(D4, 1);//Desliga o LED. WiFi.mode(WIFI_STA);//Define o ESP8266 como Station. } void loop() { connect();//Sub-rotina para conectar-se ao host. send();//Sub-rotina para enviar os dados ao host. delay(500);//Aguarda meio segundo. } void connect()//Sub-rotina para verificar a conexao com o host. { if (WiFi.status() != WL_CONNECTED)//Caso nao esteja conectado ao host, ira se conectar. { WiFi.begin("NodeMCU", "");//Conecta à rede do host. delay(2000);//Espera ate que a conexao seja feita. } } void send()//Sub-rotina para enviar dados ao host. { if (WiFi.status() == WL_CONNECTED)//Só ira enviar dados se estiver conectado. { x = random(0, 1000);//Gera um numero aleatorio entre 0 e 1000. udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA. udp.println(x);//Adiciona-se o valor ao pacote. udp.endPacket();//Finaliza o pacote e envia. digitalWrite(D4, 0);//- delay(5);//- digitalWrite(D4, 1);//Pisca o led rapidamente apos enviar. } else//Caso nao esteja com uma conexao estabelicida ao host, piscara lentamente. { digitalWrite(D4, 0); delay(250); digitalWrite(D4, 1); } }
Host
#include <ESP8266WiFi.h>//Biblioteca do WiFi. #include <WiFiUdp.h>//Biblioteca do UDP. WiFiUDP udp;//Cria um objeto da classe UDP. String req;//String que armazena os dados recebidos pela rede. void setup() { pinMode(D4, OUTPUT);//Habilita o LED onboard como saida. digitalWrite(D4, 1);//Desliga o LED. Serial.begin(115200);//Habilita a comunicaçao serial para a string recebida ser lida no Serial monitor. WiFi.mode(WIFI_AP);//Define o ESP8266 como Acess Point. WiFi.softAP("NodeMCU", "");//Cria um WiFi de nome "NodeMCU" e sem senha. delay(2000);//Aguarda 2 segundos para completar a criaçao do wifi. udp.begin(555);//Inicializa a recepçao de dados UDP na porta 555 } void loop() { listen();//Sub-rotina para verificar a existencia de pacotes UDP. } void listen()//Sub-rotina que verifica se há pacotes UDP's para serem lidos. { if (udp.parsePacket() > 0)//Se houver pacotes para serem lidos { req = "";//Reseta a string para receber uma nova informaçao while (udp.available() > 0)//Enquanto houver dados para serem lidos { char z = udp.read();//Adiciona o byte lido em uma char req += z;//Adiciona o char à string } //Após todos os dados serem lidos, a String estara pronta. Serial.println(req);//Printa a string recebida no Serial monitor. digitalWrite(D4, 0);//- delay(5);//- digitalWrite(D4, 1);//Pisca o LED rapidamente apos receber a string. } }
Entendendo a fundo
Software
Recomendamos que vocês a leiam esta referência sobre WiFi, praticamente todos comandos disponíveis estão explicados AQUI.
Cliente
-Enviando dados para o destino
udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA. udp.println(x);//Adiciona-se o valor ao pacote. udp.endPacket();//Finaliza o pacote e envia.
Nesta parte, usamos 3 funções do UDP, entre elas estão:
-Função WiFiUDP::beginPacket()
udp.beginPacket("192.168.4.1", 555);
Estamos enviando o pacote para o IP “192.168.4.1” que é o IP padrão do host no ESP8266, na porta 555.
-Função WiFiUDP::println()
udp.println(x);
Adicionamos o valor da variável X ao pacote.
-Função WiFiUDP::endPacket()
udp.endPacket();
Por ultimo, fechamos o pacote para finalmente ser enviado ao destino.
Para melhor entendimento, veja esta figura:
- Vermelho = beginPacket();
- Verde = print();
- Azul = endPacket();
Host
-Função WiFiUDP::parsePacket()
udp.parsePacket();
Esta função faz a verificação de novos dados no buffer. Se houver dados novos para serem lidos, a função irá retornar um numero maior que zero.
Desafio
O desafio agora é você fazer uma mensagem de retorno para quem enviou uma mensagem ao host, por exemplo, quando o cliente 1 enviar dados ao host, o host responda “OK”. Também faça um Print do IP de quem foi recebido o dado. Na referencia do WiFi (citado acima), há os comandos necessários!
Finalizando
Com a possibilidade de comunicação entre dispositivos pelo WiFi ou Wireless Ponto-a-Ponto, podemos fazer projetos muito legais e redes de dispositivos para se comunicarem. Não se esqueça de ver a parte 2 do material, sobre TCP! Dúvidas? Sugestões? Críticas? Comente abaixo!
Eu poderia fazer isso sem que os ESP estejam conectados no mesmo WiFi?
Poderia fornecer como o cliente recebe uma mensage do host? e como o host envia uma mensagem ao cliente? Obrigada!
boa noite, tem como me dar um dica.
Usando o codigo exemplo da pagina, o cliente mando um mensagem para servidor o servidor recebeu compara e o led pisca ok, agora se eu mandar um string para o servidor o servidor compara e manda uma resposta
como serio o codigo de resposta??
“servidor enviando um string para o cliente”
“como o cliente conseguiria ler essa string e fazer a comparação”
Exemplo: cliente manda a string “dados” para o servidor, o servidor compara (if) se verdadeiro manda a resposta com outra string “correto”, o cliente recebe a string e compara (if)
obs: estou usando o codigo da pagina como suporte, comunicação UDP
Obrigado desde já.
Obrigado, José Morais!
Boa noite, José Morais!
Tutorial excelente! Onde posso baixar a biblioteca ESP8266WiFi.h?
Para programar meu ESP-32S, estou utilizando a IDE do Arduino já configurada para o ESP-32S.
Atenciosamente,
Paulo Araújo
Essa já vem baixada junto de quando você instala as placas do ESP8266 na IDE.
é possivel conectar um esp32 com esp8266 ?
Claro!
Boa tarde, parabéns pela publicação
Tenho uma duvida, seria possível enviar uma mensagem pelo caminho “inverso”?. Gostaria de enviar uma informação partindo do Host para o cliente.
Sim, não há nenhuma limita no que enviar, quanto enviar, de onde enviar e etc.
Teria algum exemplo dessa aplicação?
Bastaria apenas inverter o códigos mantendo as configurações de Acess Point e Station?
Obrigado
Ola José Morais Muito bom!
Me tire uma duvida, em uma rede pulblica de wifi como e possivel fazer a conexão ?
exemplo eu faço o meu login na rede para acessar a internet, como faço no esp01?
Para se conectar em um roteador externo, basta usar o WiFi.begin(“nome da rede”, “senha da rede”);
Fala meu amigo, acompanhando seus exemplos aprendi muito mesmo, mais gostaria de criar um código que a conversa vai ser entre 2 esp8266, o cliente vai receber uma string (números e letras) via serial e vai enviar via TCP para o Host (esp8266) que por sua vês o Host vai gravar via serial tbm a mesma string e dar um enter (quebra de linha), poderia me ajudar com essa programação? Whats (41) 99929-9190. Vlw
Boa noite, cara, é possível o cliente enviar um dado ao host, o host por sua vez processa esse dado e devolve um outro dado para o cliente?
É sempre melhor perguntar por que não seria possível… Sim, é possível, servidores normalmente fazem isso (receive > process > return)
Consegui fazer a comunicação entre os 2, porém as vezes a estação fica resetando. já ouviu falar da estação resetar ao receber pacote UDP?
Não, isso é alguma falha no seu código.
como eu faria para ler um sensor, exemplo o dht11, é exibir duas strings difrentes, uma pra temperatura e outra para umidade?
ola amigo. tenho uma duvida , tenho algumas placas esp8266 , e possível ocultar o wifi pois não queria ficar com vários wifi aparecendo, desde já obrigado
Sim, no próprio WiFi.begin() tem um parametro para ocultar.
Bom dia José, ainda estou dificildades para fazer a comunicação entre um client ( esp8266-12e ) , o qual tem 2 inputs ( botão e um potenciômetro) . Que por sua vez irão comandar dois host separadamente. Estes por sua vez tem um motor de passo e outro host tem um trava eletrica , ambos são comandados também por esp8266-12e. A minha dúvida é como mandar comando do client via protocolo udp para cada um desses host. Desta maneira queria acionar a trava ao pressionar o botão e controlar o motor de passo através do potenciômetro. Mas uma vez agradeço a paciência por responder tantas perguntas. Muito obrigado
O envio continua semelhante, você só precisa encaixar ao seu código. (udp.print(), udp.println(), udp.write())
Boa tarde José, então eu poderia criar duas variaveis no código fonte do cliente para armazenar ( X e Y ) os valores do inputs . E enviar para os hosts , porém usarei a função WIFIUDP.read() para ler a variável especificada na função . Seria este o caminho?.
Consigo fazer essa mesma conexão com um ESP01 conectado ao arduino?
Sim
Muito Bom. Um dos poucos tutoriais que eu fiz e funcionou de primeira! Parabens!!!!
Eu modifiquei um pouco o projeto para acender o led do esp quando pressiono o botao no outro esp.
e percebi que quando envio “1” eu recebo “72” e quando envio “0” recebo “71”. Parece que nao estao falando a “mesma lingua” . Como posso fazer para eles se “entenderem” Ex: enviar 100 e receber 100?
az = StrToFloat(req); //az variavel int
Serial.println(az);
faça isso que da certo
Show de bola, é exatamente isso…….. Agora estou em busca de 1 host e 4 client
Parabéns!!
José Morais, você tem uma forma de passar conhecimento muito simples e eficiente, igual e em alguns casos ate superior a de muitos professores de faculdades publica e privada que já estudei…
Gosto de ler seus artigos, sou fã de novas tecnologias na área da informática e eletrônica!
Continue assim!
Muito obrigado, sempre foco em passar o simples e direto em vez de ficar enchendo “linguiça” nos códigos, o que acaba perdendo o foco do assunto e deixa tudo mais complicado.
Copiei e colei seu código, mas o cliente não se conecta ao servidor.
Segui um exemplo (http://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/soft-access-point-examples.html) e vi que os dois módulos WiFi estão funcionando como AccessPoint corretamente. O problema é que não consigo utilizar um NodeMCU para se conectar na rede do outro.
Como você debugga a conexão dos nós?
Wireshark
Boa noite! As funções servem para a ESP8266-01 integrado ao arduino ?
Sim
opa , como eu faço esse esquema com o esp 32 ?
Se usar o Arduino Core, creio que seja exatamente a mesma coisa!
Pois é, mas não deu certo eles nem conectam um ao outro
Então você fez algo errado. Os IP’s e Portas estão corretos? Faça alguns testes com aplicativos ou programas que enviam pacotes TCP/UDP e verifique se o ESP32 esta aceitando/recebendo os pacotes!
Parabéns pelo artigo! Me ajudou muito!
vc sabe o alcance máximo entre os dois ?
Isso depende muito do local e até configurações do WiFi Host. Entretanto, em testes simples a campo aberto, pode chegar em 40-80 metros. Penso que o fator mais importante é o Host, tanto que se você usar uma antena que direcione o sinal, pode obter 10KM ou mais!
Ótimo artigo. Aguardando a parte 2, onde o cliente irá receber uma resposta de um determinado envio
Show seu turorial e muito boa a explicação, e se eu quiser acionar um botão no cliente e acender o led no host poderia ser pelo próprio wifudp?
Sim! Você pode transmitir uma String como “ON” para o Host, e quando o Host ler “ON”, irá acender o LED, bastando apenas adicionar a verificação no Host!
Parabéns pela didática e explicação.
Acredito que usando essas mesmas funções e características que você usou podemos fazer 3 ou mais ESP, comunicando-se em rede tipo mesh, com vários esps, podemos?
Abraços.
Valeu.
Sim! Ainda é possível usar o WiFiScan para procurar “gateways” e fazer um Mesh interessante, já que o ESP suporta AP+STA. Já fiz testes com 4 conexoes simultaneas, mas apenas um Host recebendo informações.
Boa tarde José , extremamente didático a explicação. Mas este exemplo de fazer 4 conexões simultâneas teria alguma material feito?. É possível fazer a comunicação entre um client e 4 host?. Poderia compartilhar ? . Desculpe a quantidade de perguntas , por ser iniciante no assunto iot . As sua explicação foram as mais simples e fácil de entender. Agradeço a paciência.
Sim, é possível fazer com quantos nós (clientes/hosts) você desejar. Não tenho nada pronto para compartilhar, mas a ideia é a mesma. Dê uma estudada em TCP/UDP (redes e etc) que já pode te ajudar…
Boa tarde José , caso eu queria por exemplo um client comunicar-se com dois host ( H1 e H2) . Como que faço para enviar comando separadamente? . Analisando o seu código fonte eu poderia criar uma rede wifi para cada host , através do comando wifi.softAP. E o client conectaria-se a essas duas redes. Caso esse não seja o raciocínio correto poderia me corrigir?. Obrigado pela atenção….ah agradeço pela resposta anterior…
Se fizer os hosts separados, o cliente vai ter que se conectar a cada uma (individualmente claro) e transmitir após isso. Se houver a possibilidade de todos ficarem na mesma rede, é mais simples e rápido.
Tutorial bastante didático, excelente! aguardando a segunda parte.
Obrigado, a segunda parte já esta em desenvolvimento e também irei criar uma terceira…