ESP8266 do jeito simples: conexão ao Arduino, acesso à rede WiFi e resposta a ping
ESP8266 com Arduino: o be-a-bá da conexão e programação para acessar uma rede WiFi e responder ao ping.
É difícil fazer um artigo introdutório ao ESP8266 com Arduino sem dividi-lo em uma série de 4 ou 5 textos ou usar programas quilométricos, mas aceitei o desafio, e vou expor apenas o que considero o básico para iniciar a lidar com essa versátil família de módulos, deixando os aspectos periféricos e as aplicações práticas para artigos futuros, ou para os inúmeros outros autores que estão tratando do "chip da vez".
O número de artigos, aqui e lá fora, falando do ESP8266 vem se multiplicando, e não é pra menos: na virada de março para abril, a comunidade do ESP8266 fez algo genial com suas plaquinhas, que deixaram de ser meros shields que acrescentavam um eficiente suporte a WiFi aos projetos com Arduinos1, e passaram a ser placas de desenvolvimento diretamente programáveis a partir da IDE do Arduino, sem precisar de um Arduino no meio do caminho.
A atenção que esse novo recurso vem recebendo é mais do que merecida, afinal as plaquinhas com ESP8266 (como a ESP-01 no alto à esquerda da foto acima) são baratas e o potencial delas está longe de ser explorado na íntegra. Mas nada disso muda o fato de que elas continuam sendo também excelentes opções na hora de dar a um Arduino a capacidade de conexão WiFi à Internet ou a uma rede local.
Afinal, o ESP8266 é barato, suporta WiFi 802.11 b/g/n, tem todos os componentes (até a antena) integrados à placa, e consumo baixíssimo de energia, entre muitos outros recursos.
Reduzindo o escopo para não complicar
Muitos dos artigos introdutórios ao uso do ESP8266 para dar conectividade ao Arduino acabam sendo desmedidamente complexos, devido a alguns fatores bem concretos: (1) é difícil deixar de primeiro explicar sobre alguma maneira segura de conectar um Arduino de 5V aos 3,3V do ESP8266 (2) para ter alguma funcionalidade prática comum, o artigo acaba tendo de tratar desde a conexão física até o desenvolvimento de aplicações on-line na web e a interligação entre redes com endereçamento local e a Internet (3) o ESP8266 tem uma pilha TCP/IP completa, e descrever a funcionalidade dela exige trazer muitos conceitos à discussão.
Eu prefiro ir aos poucos, e hoje narro a minha experiência inicial com uma plaquinha ESP-01 (a mais simples da linha ESP8266) conectada a um Arduino.
Usando um Arduino Uno Plus que tem opção de funcionar a 3,3V lógicos, consegui reduzir a complexidade desta experiência.
Como eu escolhi a experiência já pensando em como iria compartilhá-la aqui no BR-Arduino, resolvi escapar das 3 complexidades listadas acima:
- Usei um Arduino Uno Plus, que tem chave seletora de nível lógico e assim pode operar a 3,3V – mesma tensão do ESP8266. (há alternativas simples para Arduinos comuns, veja abaixo)
- Parei antes da camada de aplicação. Meu experimento vai apenas até o ponto em que ocorre a conexão à rede sem fio, e o ESP8266 responde a ping enviado de outros computadores da rede local.
- Usei pouco ou nada de TCP.
Em artigos futuros posso vir a abordar os pontos que deixei de fora ao fazer as opções acima, mas prefiro avançar devagar e fixar bem os pontos escolhidos.
Conectando o ESP8266 ao Arduino
O meu ESP-01 tem 8 pinos físicos, dos quais 6 foram usados neste experimento: GND, 3.3V, TX, RX, CH_PD e RST.
Os 2 primeiros da lista acima (GND e 3.3V) são os de alimentação elétrica, e foram conectados ao GND e 3V3 do Arduino, respectivamente. Os 2 últimos (CH_PD e RST) foram conectados a pinos digitais, sendo que o primeiro é permanentemente mantido em HIGH, e o segundo fica LOW brevemente na inicialização do meu programa (causando um reset do ESP8266) e a partir daí fica permanentemente em HIGH.
Em conexões serias “clássicas”, o TX de um vai no RX do outro, e vice-versa.
Já os pinos RX e TX são os responsáveis pela comunicação de dados entre Arduino e ESP8266. O RX recebe bits (e deve ser conectado ao TX do Arduino – o pino 1, no caso do Uno), e o TX envia bits (e deve ser conectado ao RX do Arduino - o pino 0, no caso do Uno).
Todas as conexões de alimentação, sinal e dados mencionadas precisam considerar a tensão do ESP8266, que é de 3,3V, bem abaixo dos 5V típicos dos pinos de dados do Arduino. Eu optei por usar um Arduino cuja tensão dos pinos de dados é configurável e tem opção de 3,3V, mas teria outras alternativas que talvez explore em artigos posteriores em Arduinos de 5V, como divisores de tensão construídos com resistores, ou mesmo CIs conversores de nível lógico.
Com os 6 fios acima, a conexão física entre o Arduino e o ESP-01 está completa; no interesse de termos uma maneira de monitorar na tela do computador o que acontece nessa conexão, entretanto, usei ainda os pinos digitais 8 e 9, conectados a um FTDI Basic para permitir o uso do Monitor Serial mesmo estando com a porta serial física do Arduino ocupada pelo ESP8266, exatamente da forma que descrevi no artigo anterior Biblioteca softwareSerial: conexão alternativa para debug via Monitor Serial. Se o seu FTDI estiver operando a 5V e o Arduino estiver a 3,3V, verifique as tolerâncias envolvidas e, se necessário, ajuste a tensão que sai do TX do FTDI, para evitar riscos.
Dica importante: desconecte o jumper que estiver conectado ao pino 0 do seu Arduino sempre que for fazer upload de programas, como ilustrei na foto acima – e reconecte-o ao final do upload. Numa montagem como a deste artigo, o pino 0 (RX) é usado tanto para o upload de programas via USB quanto para a comunicação serial entre o Arduino e o ESP8266. Se você mantiver o jumper, o ESP vai tentar responder aos dados de upload enviados pela IDE, e a probabilidade de erro é grande.
WiFi no Arduino: programando para o ESP8266
O ESP8266 tem uma interface muito familiar a quem usou modems antes da metade dos anos 90: ele usa "strings AT", comandos enviados pela porta serial (geralmente iniciando com as letras "AT") para receber instruções, que depois processa internamente e, ao final, responde também pela Serial.
Assim, o Arduino não está propriamente conectado à rede WiFi. Quem está conectado é o ESP8266, que recebe comandos do Arduino sobre o que fazer com essa conexão (incluindo iniciá-la e encerrá-la), mas a gerencia de forma completamente autônoma.
O programa que veremos a seguir funciona nos ESP-01 que tenho na bancada, que vieram configurados para velocidade de conexão serial de 9600 bauds (não há relação entre a velocidade da serial e a velocidade da conexão WiFi). Outros modelos de ESP8266 podem vir com outras velocidades de conexão (ouço falar em 57600 e 115200), portanto é possível que o programa precise ser alterado caso eu vá usá-lo com outros modelos.
Vamos ao código, com cores para facilitar a explicação que vem depois dele:
#include <SoftwareSerial.h>
SoftwareSerial monitorSerial(9, 8); // RX, TX
const byte CH_PD=5;
const byte RST=6;
#define rede "brarduino"
#define senha "suasenha"
void setup() {
monitorSerial.begin(38400);
monitorSerial.println("--------------");
pinMode(CH_PD,OUTPUT);
digitalWrite(CH_PD,HIGH);
pinMode(RST,OUTPUT);
digitalWrite(RST,LOW);
delay(100);
digitalWrite(RST,HIGH);
delay(1000);
Serial.begin(9600);
Serial.setTimeout(5000);
monitorSerial.println("ESP8266 Demo - aguardando 1 segundo");
delay(1000);
monitorSerial.println("Enviando RST");
Serial.println("AT+RST");
recebeResposta();
recebeResposta(); // o reset tem 2 respostas - OK (antes) e ready (depois)
monitorSerial.println("Selecionando modo de operacao misto (AP e estacao)");
Serial.println("AT+CWMODE=3");
recebeResposta();
monitorSerial.println("Listando redes visiveis");
Serial.println("AT+CWLAP");
recebeResposta();
monitorSerial.println("Conectando-se a uma rede");
String comando="AT+CWJAP=\"";
comando+=rede;
comando+="\",\"";
comando+=senha;
comando+="\"";
Serial.println(comando);
recebeResposta();
monitorSerial.println("Listando endereco IP (pode dar ping no segundo deles)");
Serial.println("AT+CIFSR");
recebeResposta();
}
void loop() {
}
void recebeResposta() {
int limite=7000;
unsigned long chegada=millis();
boolean continuar=true;
String S="";
unsigned long ultimochar=0;
while (continuar) {
if (Serial.available()) {
char c = Serial.read();
ultimochar=millis();
S=S+c;
monitorSerial.print(c);
if (c==10) { // LF, fim da linha recebida
byte p=S.indexOf(13);
String S1=S.substring(0,p);
if (S1=="OK") continuar=false;
if (S1=="ready") continuar=false;
if (S1=="no change") continuar=false;
if (S1=="ERROR") continuar=false;
S="";
}
}
if (millis()-chegada > limite) continuar=false;
}
}
As duas primeiras linhas, que estão em laranja, e mais a linha da mesma cor que está no início da função setup()
, são as responsáveis por definir e inicializar a nossa conexão via softwareSerial, para permitir o uso do Monitor Serial do Arduino para mensagens de debug e acompanhamento, sem interferir na conexão entre o Arduino e o ESP8266, que são pela Serial nativa. Os detalhes sobre esse uso da softwareSerial você encontra no artigo anterior: Biblioteca softwareSerial: conexão alternativa para debug via Monitor Serial
As linhas em verde escuro antes da função setup()
e dentro dela fazem funções tradicionais de inicialização, identificando quais pinos do Arduino estarão conectados ao CH_PD e ao RST do ESP8266 (e depois inicializando-os, incluindo um reset físico do ESP8266 alternando o valor do pino conectado ao RST), e qual o nome da rede e a respectiva senha que o programa deverá usar para se conectar.
O Arduino comanda o ESP8266 por comandos curtos, e a resposta vem na forma de texto na serial.
As linhas em vermelho são as primeiras a fazer uma conexão com o ESP8266, e elas são as responsáveis por instrui-lo (por meio do comando AT+RST
) a reinicializar. Como já temos um reset físico antes, provavelmente essas linhas poderiam ser removidas, mas elas trazem um exemplo interessante: note que elas são seguidas por 2 chamadas à função recebeResposta()
(que conheceremos mais adiante). Isso acontece porque o comando de reset é atípico, e tem 2 respostas: uma que termina em "OK", indicando que o comando foi recebido, e outra que termina em "Ready", indicando que o reset foi completado.
As linhas a seguir, em cinza, usam o comando AT+CWMODE=3
para garantir que o ESP8266 esteja em um dos seus modos de operação que suportam os comandos que virão a seguir. O ESP tem 3 modos: estação conectada a uma rede Wifi (CWMODE=1), ponto de acesso ao qual outras estações conectam (CWMODE=2), ou misto (CWMODE=3).
A seguir, em marrom, vem um trecho curto que faz algo bem interessante: por meio do comando AT+CWLAP
, instrui o ESP8266 a responder com uma lista de todas as redes sem fio que estiverem visíveis para ele.
Em roxo temos mais um exemplo interessante: a construção de um comando AT um pouco mais complexo, porque envolve parâmetros. É o AT+CWJAP="rede","senha"
, que instrui o ESP8266 a conectar-se à rede sem fio passada como parâmetro, usando a senha também passada como parâmetro. Atenção: as aspas fazem parte do comando.
Completando a sequência do exercício, em cinza, temos o comando AT+CIFSR
, que retorna endereços IP em uso. O segundo deles pode ser usado, em outras máquinas da sua rede, para enviar um ping ao seu ESP8266 – ele vai responder autonomamente, e o Arduino nem vai ficar sabendo.
Note que tudo o que listamos acima foi feito como parte do setup, e não há nada a fazer no loop()
, que está vazio.
Ao final, em verde claro, temos a minha versão básica da função recebeResposta()
, feita para ser chamada após o envio de cada comando ao ESP8266, e ficando responsável por receber a resposta dele e enviá-la ao monitor serial por meio da conexão alternativa que definimos (em laranja) no início do programa. Ela encerra caso perceba que o limite de tempo de conexão (fixado por mim em 7 segundos) se esgotou, ou ao receber um indicativo de final de resposta ("OK", "ERROR", "ready").
O que aparece no Monitor Serial
Abaixo está o que apareceu no Monitor Serial durante a execução do programa acima. Usei as cores correspondentes aos trechos de programa, quando possível.
--------------
ESP8266 Demo - aguardando 1 segundo
Enviando RST
AT+RST
OK
LJ(r!B(KZb
[Vendor:www.ai-thinker.com Version:0.9.2.4]
ready
Selecionando modo de operacao misto (AP e estacao)
AT+CWMODE=3
OK
Listando redes visiveis
AT+CWLAP
+CWLAP:(4,"NetVirtua 404",-80,"e0:ce:c3:dc:50:68",1)
+CWLAP:(4,"TP-LINK_65FB62",-92,"c0:4a:00:65:fb:62",1)
+CWLAP:(4,"netvirtua304",-93,"28:be:9b:97:3b:b4",1)
+CWLAP:(3,"anafln",-84,"00:1d:d5:e3:94:10",1)
+CWLAP:(3,"Carlsson",-53,"f8:d1:11:55:c7:42",6)
+CWLAP:(4,"Ana-fln",-88,"f8:d1:11:ad:dd:be",9)
+CWLAP:(3,"casablanca",-43,"90:84:0d:dc:f2:31",11)
+CWLAP:(4,"netvirtua22-303",-73,"8c:04:ff:7e:34:a5",11)
OK
Conectando-se a uma rede
AT+CWJAP="brarduino","suasenha"
OK
Listando endereco IP (pode dar ping no segundo deles)
AT+CIFSR
192.168.4.1
192.168.0.143
OK
Na listagem acima, atente para os aspectos mencionados na explicação do programa: as duas respostas ao comando de reset, por exemplo. Ou as respostas terminadas em "OK".
Num programa mais robusto e com aplicação prática, o loop()
seria populado, e a função recebeResposta()
provavelmente seria muito mais rica: teria recursos de tratamento de erro, exceções, e despacharia para outras ações dependendo do que fosse recebido do ESP8266. Mas isso – e a conexão a Arduinos de 5V – fica para os próximos artigos ;-)
- E a outros hardwares além dos Arduinos, claro. ↩
Comentar