Comunicação Wireless TCP com ESP
Daremos inicio a segunda parte do nosso material sobre comunicações Wireless. No tutorial anterior, foi abordado sobre o protocolo UDP, que não é orientado à conexão. Desta vez, vamos aprender sobre o protocolo TCP, este por sua vez, é orientado à conexão, que nos garante a entrega de mensagens, ordenação do recebimento/envio, etc. O código aqui apresentado irá funcionar tanto para ESP8266 quanto para o ESP32, já que a diferença é mínima e funciona da mesma forma.
[toc]
Protocolo TCP
TCP (Transmission Control Protocol) é um protocolo para transmissão de dados voltado à conexão, ou seja, permite que as maquinas se comuniquem e gerenciem o estado atual da conexão com seus clientes e servidores. Uma característica importante do TCP é seu gerenciamento do status da rede e os dados, com isto, podemos saber se o dado enviado foi realmente entregue ao destinatário, também garante a entrega ordenada das informações sem que haja colisões e perdas inperceptíveis. Muitas aplicações usam o TCP para efetuar suas comunicações, sendo amplamente usado em todo tipo de situação, ao contrario do UDP que por não ser orientado à conexão, pode gerar erros em nossos sistemas.
Mãos à obra
Componentes necessários
- 1x ESP8266(Usaremos NodeMCU 8266) ou 1x ESP32.
- Aplicativo TCP Client no celular.
Obs: Você pode usar qualquer aplicativo ou programa para transmitir os pacotes TCP. Nós usaremos o primeiro encontrado na Play Store para ser fácil de vocês encontrarem caso queiram usar também. Link do TCP Client na Play Store
Código do projeto
#ifdef ESP8266//Se estiver usando ESP8266, automáticamente irá adicionar as bibliotecas do ESP8266. #include <ESP8266WiFi.h> #include <WiFiServer.h> #elif defined ESP32//Se estiver usando ESP32, fara a mesma operaçao. #include <WiFi.h> #endif WiFiServer sv(555);//Cria o objeto servidor na porta 555 WiFiClient cl;//Cria o objeto cliente. void setup() { Serial.begin(115200);//Habilita a comm serial. WiFi.mode(WIFI_AP);//Define o WiFi como Acess_Point. WiFi.softAP("NodeMCU", "");//Cria a rede de Acess_Point. sv.begin();//Inicia o servidor TCP na porta declarada no começo. } void loop() { tcp();//Funçao que gerencia os pacotes e clientes TCP. } void tcp() { if (cl.connected())//Detecta se há clientes conectados no servidor. { if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos. { String req = ""; while (cl.available() > 0)//Armazena cada Byte (letra/char) na String para formar a mensagem recebida. { char z = cl.read(); req += z; } //Mostra a mensagem recebida do cliente no Serial Monitor. Serial.print("\nUm cliente enviou uma mensagem"); Serial.print("\n...IP do cliente: "); Serial.print(cl.remoteIP()); Serial.print("\n...IP do servidor: "); Serial.print(WiFi.softAPIP()); Serial.print("\n...Mensagem do cliente: " + req + "\n"); //Envia uma resposta para o cliente cl.print("\nO servidor recebeu sua mensagem"); cl.print("\n...Seu IP: "); cl.print(cl.remoteIP()); cl.print("\n...IP do Servidor: "); cl.print(WiFi.softAPIP()); cl.print("\n...Sua mensagem: " + req + "\n"); } } else//Se nao houver cliente conectado, { cl = sv.available();//Disponabiliza o servidor para o cliente se conectar. delay(1); } }
Colando para funcionar
Devo lembrar que o IP padrão do ESP em modo Acess_Point é 192.168.4.1
1-) Precisamos nos conectar na rede WiFi criada pelo micro controlador.
2-) Logo, iremos adicionar o servidor com seu IP e PORTA no aplicativo. Lembre-se que você pode usar qualquer aplicativo ou programa de computador para isso.
3-) Após incluir os dados do servidor no aplicativo, podemos conectar-se e enviar os dados.
Obs: Também há dados disponíveis no Serial monitor, que o micro controlador escreveu, olhe como ficou.
Entendendo a fundo
Software
-Função WiFiClient::connected()
if (cl.connected())//Detecta se há clientes conectados no servidor. { }
Esta função retorna se há cliente conectado em nosso servidor. Também irá retornar que há clientes até que todos dados sejam lidos do buffer, se não, continuará aparecendo clientes conectados até que todos dados sejam lidos.
-Função WiFiClient::available()
if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos. { }
Esta função, retorna a quantidade de bytes disponiveis para a leitura no buffer do cliente. Pode ser usada para detectar se há dados, e também para efetuar a leitura byte a byte do buffer, afim de montar a String final.
-Função WiFiClient::print()
cl.print();
Usada para enviar a String para o cliente. Há várias maneiras de mandar uma informação para o cliente, desde write(), printf() até print() e println().
-Função WiFiServer::available()
cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.
Esta função, obtem um cliente que esta conectado ao servidor e tem dados disponiveis para a leitura. Pode ser entendida a grosso modo que diz ao cliente que há um servidor disponivel para enviar dados.
Desafio
O desafio desta vez, é tentar conectar multiplos clientes ao mesmo tempo em seu servidor. Este código não permite isto, então faça alterações e estude sobre as bibliotecas usadas para permitir multiplas conexões!
Fechamento
Neste tutorial, você aprendeu a efetuar uma troca simples de mensagens entre o Cliente (nosso celular) e o Servidor (ESP), pode ser usada de mesma forma para comunicação entre dois micro controladores. Na parte 3 deste material, aplicaremos as aulas passadas em um aplicativo em Android ou PC para se comunicar com nosso ESP8266/32. Não se esqueça de comentar sobre duvidas, elogios e criticas! Também aceitamos sugestões sobre a terceira parte deste material.
Estudante de Engenharia da Computação pela USC, pretende se aprimorar e fazer a diferença nesta imensa área da tecnologia. Apaixonado por IoT, sistemas embarcados, microcontroladores e integração da computação nos mais diversos fins práticos e didáticos.
36 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.
No posto anterior, copiei o código e deu erro, será que vocês podem me ajuda.
2020 e ainda nao achei os multiplos client
É só criar um vetor de clientes (objeto WiFiClient, WiFiUDP, etc) e manipula-los individualmente.
bom dia, José ! pode me ajudar, preciso fazer comunicação com TCP entre dois ESP32. Um vai ler o sensor e enviar para o outro que acionara alarmes.
Enviei o código, mas nem a rede mudou de nome. Continua sendo FaryLink… Vou continuar na busca, obrigado pela instrução.
Descobri que o meu erro era que colocava uma senha menor que 8 digitos, entao nao criava a rede.
#ifdef ESP8266//Se estiver usando ESP8266, automáticamente irá adicionar as bibliotecas do ESP8266.
#include
#include
#elif defined ESP32//Se estiver usando ESP32, fara a mesma operaçao.
#include
#endif
WiFiServer sv(555);//Cria o objeto servidor na porta 555
WiFiClient cl;//Cria o objeto cliente.
int ledPin = 2;
void setup()
{
Serial.begin(115200);//Habilita a comm serial.
WiFi.mode(WIFI_AP);//Define o WiFi como Acess_Point.
WiFi.softAP(“NodeMCU”, “”);//Cria a rede de Acess_Point.
sv.begin();//Inicia o servidor TCP na porta declarada no começo.
}
void loop()
{
pinMode (ledPin,OUTPUT);
tcp();//Funçao que gerencia os pacotes e clientes TCP.
}
void tcp()
{
if (cl.connected())//Detecta se há clientes conectados no servidor.
{
if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos.
{
int acao = -5;
String req = “”;
while (cl.available() > 0)//Armazena cada Byte (letra/char) na String para formar a mensagem recebida.
{
char z = cl.read();
req += z;
if (cl.available () > 0){
acao = z;
}
if (acao >’0′){
if (acao ==’1′) {
digitalWrite (ledPin,HIGH);
delay (2000);
}
else if (acao == ‘0’){
digitalWrite (ledPin,LOW);
delay (2000);
}
}
acao =-5;
}
//Mostra a mensagem recebida do cliente no Serial Monitor.
Serial.print(“\nUm cliente enviou uma mensagem”);
Serial.print(“\n…IP do cliente: “);
Serial.print(cl.remoteIP());
Serial.print(“\n…IP do servidor: “);
Serial.print(WiFi.softAPIP());
Serial.print(“\n…Mensagem do cliente: ” + req + “\n”);
//Envia uma resposta para o cliente
cl.print(“\nO servidor recebeu sua mensagem”);
cl.print(“\n…Seu IP: “);
cl.print(cl.remoteIP());
cl.print(“\n…IP do Servidor: “);
cl.print(WiFi.softAPIP());
cl.print(“\n…Sua mensagem: ” + req + “\n”);
}
}
else//Se nao houver cliente conectado,
{
cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.
delay(1);
}
}
coloquei mais um pedaço de um programa para desligar e ligar o led. vlu ! você explica bem pra caramba parabéns!!!
Você poderia fazer uma comunicação entre uma esp8266 e uma mega2560 para controlar uma impressora3d?
Vixe, não vou conseguir fazer um post sobre isso hehe, mas a comunicação pode ser por qualquer uma que de você desejar, como por exemplo: UART, I2C, SPI, e etc
esse codigo e em java ou na ide do arduino?
Arduino ide
Tem como usar o Esp8266 e uma impressora termica e transforma-la em impressora remota sem fio ? ate consegui , estou conhecendo agora o Esp8266 até consegui usar o wifimanager para configurar a parte da rede, mas nao tenho ideia de como faria o esp8266 receber via wifi a impressao e enviar para a impressora, olhando por cima, nao enviam a impressao pela usb, estao usando somente o xt e rx
coloquei o nome do meu pc e o ipv4 preferencial do meu pc, dados obtidos pela instrução ipconfig /all, estou achando que o problema tem a ver com a tal porta 8080 que não sei como configurar.
Bom Dia!
Estou tentando ha meses fazer funcionar a comunicação do meu Nodemcu ESP8266 com o meu Servidor local (UwAmp 3.1.0) e sem sucesso. O Apache está configurado na porta 8080 e está online, porque a porta 80 não permite, informa que está em uso, Obs: não tenho Skipe instalado no meu PC.
Para não poluir a pagina estou utilizando o exemplo do blog http://labdegaragem.com/profiles/blogs/esp8266-12e-banco-de-dados-mysql ,que foi feito com base no blog do José Cintra http://josecintra.com/blog/esp8266-bancos-dados-requisicoes-http/
O problema está na conexão, sempre para aqui.
if ( !client.connect(server, http_port) )
{
Serial.println(“Falha na conexao com o site “);
return false;
}
Parâmetros que utilizo:
const char http_site[] = “http://localhost:8080/mysql/”;
const int http_port = 8080; //estou achando que o problema está aqui
WiFiClient client;
IPAddress server(192,165,28,19); //aqui coloco meu IPV4
Obs: quando digito no explorer http://localhost:8080/weather/insert_weather.php , funciona!
por favor
ME AJUDE!, perde esse tempinho comigo.
ficarei muito Grato.
O ESP esta conectado na mesma rede? O IP do host esta correto?
Sim estão conectados na mesma rede, O IP do host esta correto? onde verificar esse IP, desculpe minha ignorância.
De verdade, vocês estão de parabéns!
Vida de silício é sensacional!
Estou em busca de fazer algo novo com o ESP8266 01!!
Estou tentando encontrar uma forma de quando o ESP8266 conectado a uma rede ler um BOTÃO FÍSICO conectado ao GPIO zero, ele envia uma função a outro ESP8266 que também esta conectado a mesma rede com outro IP que quando receber esta função desliga um led.
Ex: ESP(1) coloco nível lógico baixo no pino zero dele que esta configurado como entrada pullup ativo e ele envia a função \?function=pino_0_off\ ao IP de outro ESP(2) conectado a mesma rede com outro IP.
ESP(2) por sua vez ao receber esta função do ESP(1) apagara o led que esta conectado ao pino zero configurado nele como saida.
Aparentemente, esta usando alguma formatação WEB (parece HTTP GET), acho que isso gera overhead desnecessário tanto no MCU quanto na própria transmissão, já que poderia ser muito mais simples e rápido com “0=0” (pino 0 desligado) ou similar diretamente no socket do TCP e evitaria todo o header do HTTP e suas informações irrelevantes ao objeto central (status do pino). Se você não esta fazendo o uso de um site HTML pra uso de botões e etc, e esta apenas repassando informação entre MCU’s, use direto o socket.
Olá, sou iniciante, com Arduino e tenho uma dúvida. Poderia postar como é feita a ligação física do arduArd com o esp
Sei que este material não tem nada a ver com LabView, mas não custa nada perguntar, porque pode ser que você já trabalhou e tenha passado por um problema semelhante ao que estou passando. Estou tentando realizar um processamento de um sinal vindo de um módulo NODE MCU ESP 8266 usando LabView.
Então, estou usando o módulo Node MCU ESP 8266 para fazer a leitura analógica de um sinal que possui componentes de até 40 Hz de um sinal de eletroencefalograma para um trabalho de iniciação científica da universidade. Estava com um problema de corte do sinal que consegui resolver acrescentando um delay no código. Desta forma, o módulo é programado para servir como ponto de acesso onde o meu computador (cliente) acessa usando o protocolo TC/IP. Assim quando um cliente acessa meu módulo, o mesmo passa a enviar as informações que serão recebidas pelo computador. Fiz um programa no Labview para receber essas informações e mostrar os dados brutos num gráfico, mas preciso aplicar alguns filtros digitais neste software e avaliar o espectro de freqüência deste sinal. Vou colocar aqui tanto meu código em linguagem arduino que programei o módulo, quanto o .VI para você entender melhor. Eu poderia usar um protocolo UDP mas não conseguir programar meu módulo para usar esse protocolo.
A forma como eu reduzi a taxa de amostragem acho que não é a da mais elegante, mas não consegui achar outra forma que eu pudesse, por exemplo, mudar o prescaler que faz mudar a taxa de amostragem desse módulo. Vou postar uma figura de um sinal senoidal mostrado no gráfico do LabView antes de eu colocar o delay. E com o delay a forma está sem esses cortes na senoide, ou seja, está mostrando uma senoide normal.
Pelo o que pesquisei e conversei com alguns professores, a taxa de amostragem estava muito alta, assim, caso algum pacote de dados não fosse enviado corretamente o módulo não tinha tempo suficiente para reenviar o pacote e receber os novos dados para um novo pacote de dados. Então começava dar erro e cortar o sinal no gráfico.
Agora o problema está em aplicar alguns filtros digitais neste software e avaliar o espectro de freqüência deste sinal. Pelo o que entendi do LabView, para realizar essas tarefas o sinal precisa ter uma taxa de amostragem do sinal fixa. Então fiz uma pequena rotina para ver se pelo menos a taxa de amostragem do sinal pelo módulo era constante e verifiquei que já ali não era. Vi leituras de tempo entre 160 us até 180 us entre uma amostra e outra sem o delay de 4ms que está no código. Acho que no envio das informações pode ocorrer alguma variação e até no LabView alguma variação nesses valores, tomara que eu esteja enganado.
Para tentar resolver esse problema tentei usar alguns blocos do LabView que pudessem me auxiliar na resolução deste problema e foram basicamente 3: Build Waveform, Align and Resample Express VI, Resample Waveforms (single shot). Minha idéia foi reconstruir minha forma de onda com uma taxa de amostragem pré-determinada por mim. Mas acho que não sei usar essas ferramentas corretamente. Tentei de várias maneiras e infelizmente não obtive êxito.
O link para baixar meu programa .VI e programa arduino é: https://drive.google.com/drive/folders/1_FItfUE8IW52u7Ec4WdggadKnMH7QR5O?usp=sharing
Olá Eniovieiraa, eu estava passando pelos comentários e gostei muito do seu trabalho, entretanto não estou conseguindo abrir o arquivo no drive, poderia compartilhá-lo novamente? Obrigada!
Boa tarde. Gostaria de realizar somente uma leitura contínua da porta analógica do ESP8266 na tela do aplicativo. Como eu poderia proceder?
Apenas envie uma solicitação de leitura pelo APP ao ESP e então, mande o ESP retornar o valor analógico a partir disso.
Obrigado por postar o material e pelo esclarecimento! Funcionou aqui!
Olá, gostaria de enviar uma informação de um servidor Web(Php) para o ESP quando ocorrer uma interação no servidor(a interação pode ocorrer a qualquer momento, por isso não queria mandar o ESP ficar verificando a cada X segundos) e ainda não consegui, vc tem alguma ideia? Já consegui enviar informações do ESP pro Servidor e até mesmo requisitar informações do servidor usando o ESP, mas não consegui requisitar uma informação do ESP a partir do servidor. Desde já agradeço.
Creio que o mais simples seja uma condicional dentro do ESP que verifique se há dados, não há métodos de interrupção para isso (para que não precise fazer o Polling como você pediu), entretanto, a verificação é bem rápida e não deve atrapalhar seu código. Pelo servidor você só precisa usar um botão com Post/Get em um determinado link interno/similares como Form.
Parabéns pela clareza de explicação, coisa rara em tutoriais, estou começando em esp8266, sinto uma dificuldade em achar onde procurar materiais como descritivos das bibliotecas seus comandos, voce teria alguma sugestão dos locais onde poderia encontrar. Grato pela atenção.
Beleza!!!! Parabéns por seus artigos !!! Voce vai alem do trivial que vejo normalmente. Abraço
Jose Parabens pelos posts, tenho uma duvida, preciso comunicar entre um webserver (AP) e 2 clientes (nodemcu), onde terei um servidor que envia o comando para acionar duas lampadas acopladas a 2 cliente microcontroladores e os clientes respondem ao servidor o estado da lampadas pode me ajudar ?
Olá! obrigado pelo feedback. Posso te ajudar sim, mas isso creio que tomara mais tempo e dedicação, então, me chame no whats! 14 998202683
Muito bom. Parabéns …
hehe, obrigado!
Agradecido pelo compartilhamento do teu precioso conhecimento. Gostei da publicação. Linguagem bem acessível. Parabéns.
Obrigado pela avaliação!