Hoje vamos mostrar a
comunicação entre dois ESP’s, neste caso, o ESP32. Na nossa montagem, um dos
microcontroladores funciona como server, com um led no protoboard, no modo AP.
O segundo será o Client, ou seja, controle. Um botão ligado a este segundo ESP
que vai controlar o led que estará ligado ao server.
Neste projeto nós utilizamos o
Socket, um mecanismo de comunicação utilizado para implementar um modelo
cliente/servidor, que permite a troca de mensagens entre os processos de uma
máquina/aplicação servidor e de uma máquina/aplicação cliente.
Neste caso, o primeiro ESP,
que funciona como server, é o AP (Access Point), que terá conexão estabelecida
com o Client. Não é preciso ter um roteador! Se você quer controlar um drone,
um carrinho de controle remoto ou um aeromodelo, por exemplo, você pode usar o
ESP32 pra isso e esse dispositivo vai longe, principalmente se tiver algum tipo
de antena. Se for a rede LORA, então, alcança quilômetros, podendo chegar a 3,6
km de ESP para ESP.
Dando sequência, eu tenho um
led no server e um botão no Client. Eu fiz com um botão, mas a montagem serve
para quantos botões você quiser.
Pinagem
Aqui eu deixo a pinagem do
componente.
Montagem Server
Ligo um led no server, o nosso
receptor, e o inicio como Access Point. O Client, então, conecta nele.
Lembrando que neste caso estamos usando a porta D23.
Montagem Client
Na mesma porta D23, agora no
dispositivo Client, ligo a chave que equivale ao PushButton, e também um
resistor de Pull Down.
Código Fonte
Para este projeto temos três
arquivos: um do server, um do Client e um terceiro que usamos nestes dois casos,
que é o ESP32Socket.ino.
ESP32Socket.ino
//Arquivo principal. Neste arquivo vão os 'includes' e as configurações principais //que são compartilhadas entre os outros arquivos .ino #include <WiFi.h> #define SSID "ESP32Server" #define PASSWORD "87654321" #define SERVER_PORT 5000 //Protocolo que o Server e o Client utilizarão para se comunicar enum Protocol{ PIN, //Pino que se deseja alterar o estado VALUE, //Estado para qual o pino deve ir (HIGH = 1 ou LOW = 0) BUFFER_SIZE //O tamanho do nosso protocolo. IMPORTANTE: deixar sempre como último do enum }; //Diretiva de compilação que informará qual arquivo que queremos que seja compilado //Caso queira que o arquivo Client.ino seja compilado, remova ou comente a linha do '#define' //abaixo //Caso queira que o arquivo Server.ino seja compilado, deixe o '#define IS_SERVER' abaixo descomentado #define IS_SERVER
Iniciamos, então, pelo nome da
nossa rede: ESP32Server. Defini um número qualquer para o Password e defini o
porte que será utilizado pelo Socket, neste caso, o 5000. EM seguida, na
linguagem C você tem um recurso que chama enum
= enumeration, que aqui vai definir
qual pino será apertado com o botão, qual o valor desse pino e o tamanho do
buffer. Portanto, nós temos um buffer, que na verdade é um array. Então, ele
define uma sequência de protocolo. Primeiro, então ele define o pino, em
segundo vem o valor do pino, se esta está em 0 ou em 1, e, por fim, o tamanho
do buffer.
Esse enumeration vai servir de
índice do array do buffer que vai ser mandado para o server. Ele vai indicar
qual o botão, qual o valor botão, e, então, podemos ter diversos botões.
Outra coisa importante aqui é
a diretiva de compilação. Se eu defino uma constante (IS_SERVER), eu estou
dizendo que esse dispositivo é um servidor, que vai ter um IF para checagem e
compilação, caso proceda.
Server.ino
//Apenas vai compilar o código contido neste arquivo //caso IS_SERVER esteja definido #ifdef IS_SERVER //Cria o server na porta definida por 'SERVER_PORT' WiFiServer server(SERVER_PORT); void setup() { //Coloca este ESP como Access Point WiFi.mode(WIFI_AP); //SSID e Senha para se conectarem a este ESP WiFi.softAP(SSID, PASSWORD); //Inicia o server server.begin(); } void loop() { //Verifica se tem algum cliente se conectando WiFiClient client = server.available(); if (client) { //Se o cliente tem dados que deseja nos enviar if (client.available()) {//Criamos um buffer para colocar os dados uint8_t buffer[Protocol::BUFFER_SIZE]; //Colocamos os dados enviados pelo cliente no buffer int len = client.read(buffer, Protocol::BUFFER_SIZE); //Verificamos qual o pino que o cliente enviou int pinNumber = buffer[Protocol::PIN]; //Verificamos qual o valor deste pino int value = buffer[Protocol::VALUE]; //Colocamos o pino em modo de saída pinMode(pinNumber, OUTPUT); //Alteramos o estado do pino para o valor passado digitalWrite(pinNumber, value); } //Fecha a conexão com o cliente client.stop(); } } //Encerra o #ifdef do começo do arquivo #endif
Aqui no Server.ino começamos
com o #ifdef. Então, no caso de ser um servidor, o código todo que estiver
abaixo será compilado.
Nesta parte, então, criamos o
objeto, aqui o WiFiServer e passo o SERVER-PORT para ele.
Já no Setup, inicio esse ESP
como Access Point, seguindo os próximos passos do código, definimos o nome da
rede, entre outros detalhes, para permitir a entrada do Client.
Não é necessário definir nenhum
IP, pois o dispositivo já conta com um IP Default de sua própria Lib.
Ainda, no Loop, verificamos se
há um Client conectado e se este está disponível. Cria, então, um buffer size,
que vai receber o buffer que virá do Client. Define agora uma variável len, que
é o tamanho e faz o Cliente read, pois quando você está lidando com o Socket
não é Post and Get, que é HTTP. No caso do Socket, usamos READ and WRITE.
Prosseguindo, o server aponta
o pinNumber pela posição do buffer, define o value, que envolve a suposição se
o botão está ou não apertado, e delibera ainda, no pinMode, a saída, que no
caso é a porta D23.
Aqui fechamos o Client porque
traz uma certa segurança e damos um #endif, encerrando nossa diretiva de compilação.
Client.ino
//Apenas vai compilar o código contido neste arquivo //caso IS_SERVER NÃO esteja definido //(if n def, atenção para o 'n') #ifndef IS_SERVER //Pino que vamos fazer a leitura #define IN_PIN 23 void setup(){ //Colocamos o pino em modo de leitura pinMode(IN_PIN, INPUT); //Conectamos Access Point criado //pelo outro ESP WiFi.begin(SSID, PASSWORD); //Esperamos conectar while (WiFi.status() != WL_CONNECTED){ delay(500); } } void loop(){ //Variável que utlizaremos para conectar ao servidor WiFiClient client; //Se não conseguiu se conectar então retornamos if (!client.connect(WiFi.gatewayIP(), SERVER_PORT)){ return; } //Criamos um buffer para colocar os dados uint8_t buffer[Protocol::BUFFER_SIZE]; //Fazemos a leitura do pino int value = digitalRead(IN_PIN); //Colocamos no buffer o número do pino //cujo estado queremos enviar buffer[Protocol::PIN] = IN_PIN; //Colocamos no buffer o estado atual do pino buffer[Protocol::VALUE] = value; //Enviamos e finalizamos a conexão client.write(buffer, Protocol::BUFFER_SIZE); client.flush(); client.stop(); } //Encerra o #ifndef do começo do arquivo #endif
No Client.ino, reparem na
diretiva de compilação: #ifndef (se não está definido que ele é o server),
então, eu compilo todo o código até o ifend, ou seja, o final. Ele, então,
define onde está ligado o botão controlado pelo cliente.
No Setup, fazemos um pinMode,
conectamos Access Point criado pelo outro ESP pelo WiFi.begin e esperamos a
conexão.
No Loop, o WiFiCliente cria o
objeto. Caso este não esteja conecta a ponta de ligação, ele retorna. Caso
contrário, prossegue com os passos.
Segue criando o array a ser
enviado ao server, faz a leitura desse pino e coloca no buffer o número desse
pino. Informa o valor atual do pino, envia e encerra a conexão.
Fazendo um comentário a parte:
caso você queira montar um carrinho de controle remoto, então, você vai
precisar de vários botões. Portanto, você tem que focar neste código, na parte
de trata dos valores, números de pinos, para montar o array e escrever no
buffer size.
Retomando, o client.write
preenche o buffer e o client.flush que envia as informações para o server. Por
fim, o cliente.stop fecha a conexão com o socket.
Faça o download dos arquivos:
20 Comentários
Bacana o tutorial, estou brincando recentemente com esp32. Mas tive uma dúvida, nesse processo vc ensina como se fosse rede local. Caso eu queira fazer essa comunicação das duas placas atraves da internet para por exemplo, ter um esp em casa e outro no servico, para de casa acionar algo lá. Como faria? Seria comunicação TCP? Ou teria que ter um servidor intermediando as duas placas?
ResponderExcluirÉ necessário ter um gateway. Já vou soltar a primeira vídeo aula de como podemos implementar uma conexão desse tipo. Aguarde!
ExcluirEstarei aguardando e novamente parabéns pelo trabalho :)
ExcluirBacana o tutorial, estou brincando recentemente com esp32. Mas tive uma dúvida, nesse processo vc ensina como se fosse rede local. Caso eu queira fazer essa comunicação das duas placas atraves da internet para por exemplo, ter um esp em casa e outro no servico, para de casa acionar algo lá. Como faria? Seria comunicação TCP? Ou teria que ter um servidor intermediando as duas placas?
ResponderExcluirMuito bom !!!!
ResponderExcluirSó uma pergunta , no caso de criar 10 botões ...e apertar todos ao mesmo tempo , essa rotina funciona , ou teria que criar uma outra .
Parabéns pela sua dedicação em ajudar muita gente , a entender melhor essa nova tecnologia !!
abraços !
Olá Fernando!! Excelente trabalho e parabéns pela qualidade das apresentações e dos projetos. É possível utilizar o ESP32 como socket server com múltiplos clients , por exemplo, 4 ESP8622 como socket client? Obrigado. Parabéns !!!
ResponderExcluirFernando, boa noite!
ResponderExcluirParabéns pelo seu trabalho estou gostando muito dos materiais disponíveis.
Montei o circuito exatamente como foi orientado. Funcionou conforme apresentado, porem eles travam apos alguns acionamentos sequenciais, poderia me ajudar a solucionar este problema.
Obrigado.
Douglas aconteceu o mesmo comigo. Realmente não sei por onde começar para resolver. Eu testei a uma distância de 25m e funcionou bem, mas travava as vezes.
ExcluirMuito interessante essa ideia do ESP32 funcionar com AP, porém tenho algumas dúvidas, seguem abaixo:
ResponderExcluirCom relação a faixa de IP's fornecido pelo ESP32 nessa configuração, existe a possibilidade de alterarmos? Com relação a quantidade de conexões no ESP32 como AP existe algum limite de conexões, esse limite pode ser configurado?
Olá Fernando, sou novo com o esp32...suas aulas tanto material quanto didatica são excelentes, parabéns...
ResponderExcluirEstou com uma dúvida, nao sei pode me ajudar. Com o sockete é possivel comunicar com mais de um client no mesmo server?
Obrigado.
Hola ¿ como hacer para añadir mas leds?
ResponderExcluirAlguem pode me auxiliar:
ResponderExcluirAo compilar o Client , apresente a seguinte falha:
Arduino: 1.8.9 (Windows 7), Placa:"ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None"
C:\Users\Peralli\AppData\Local\Temp\arduino_cache_875040\core\core_bcd1c0059b11200c961ee01abaac88ff.a(main.cpp.o):(.literal._Z8loopTaskPv+0x4): undefined reference to `setup()'
C:\Users\Peralli\AppData\Local\Temp\arduino_cache_875040\core\core_bcd1c0059b11200c961ee01abaac88ff.a(main.cpp.o):(.literal._Z8loopTaskPv+0x8): undefined reference to `loop()'
C:\Users\Peralli\AppData\Local\Temp\arduino_cache_875040\core\core_bcd1c0059b11200c961ee01abaac88ff.a(main.cpp.o): In function `loopTask(void*)':
C:\Users\Peralli\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\cores\esp32/main.cpp:14: undefined reference to `setup()'
C:\Users\Peralli\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\cores\esp32/main.cpp:17: undefined reference to `loop()'
collect2.exe: error: ld returned 1 exit status
exit status 1
Erro compilando para a placa ESP32 Dev Module
Este relatório teria mais informações com
"Mostrar a saida detalhada durante a compilação"
opção pode ser ativada em "Arquivo -> Preferências"
MESMO PROBLEMA
ExcluirTeria alguma biblioteca que teria que instalar ?
ResponderExcluirOlá Fernando, comprei um ESP desses baratinhos da china e independente de qual programa eu carregar nele, ele sempre inicia em modo boot. o que pode ser? os mesmos programas carregados com o mesmo cabo em outro esp funciona normal.
ResponderExcluirMuito bom esse projeto. Parabéns. Apanhei para instalar foi não sabia que era possível carregar essas três abas simultaneamente e que precisava colocar o comando #define IS_SERVER como comentário no esp32 que é slave.
ResponderExcluiri am trying to do this application with esp8266 but i getting error in code can you help in coding
ResponderExcluirEstou tentando fazer este aplicativo com esp8266, mas estou recebendo erro no código, você pode ajudar na codificação
ResponderExcluirOlá Fernando.
ResponderExcluirEstou aprendendo muito com você.
Mas tem uma coisa que não consegui entender nesse projeto.
De onde vem o valor do BUFFER_SIZE?
Pelo que sei para criar um array precisa ter um valor tamanho definido, mas não vi em lugar nenhum onde o BUFFER_SIZE recebe o valor.
Essa duvida esta me matando. heheh
Como sempre muito bom tutorial, porém não sei se algum ESP32 está com problema, mas para de funcionar direto aqui na minha montagem
ResponderExcluir