Home › Tag Archives › ESP8266

ESP8266: error: call of overloaded ‘println(time_t (&)())’ is ambiguous

Esse erro pode acontecer por diversas razões, mas no meu caso foi porque eu estava trabalhando em um exemplo feito por outra pessoa onde o desenvolvedor criou uma variável local chamada “now”. Eu fiz uma modificação acidental que escondeu a declaração da variável e então em vez do compilador me avisar disso ele assumiu que todas as referências a “now” no código fossem as declaradas em bibliotecas como a Time.h, que tem variáveis com o mesmo nome. E ele não sabia qual usar.

O compilador não tem como adivinhar sua intenção nesse caso.

A solução foi consertar a declaração que eu havia apagado, mas melhor ainda foi substituir todas as ocorrências de “now” no código por “agora” para evitar acidentes como esse no futuro. Eu acho que nós brasileiros levamos uma pequena vantagem nesse caso por usarmos naturalmente nomes de variáveis em português, o que evita a colisão com os nomes usados em bibliotecas, que geralmente estão em inglês. Se o nome da variável não fosse “now” minha ocultação acidental da declaração teria apenas causado um erro facílimo de entender do tipo “não foi declarada”. Tenha em mente que se o compilador tivesse encontrado apenas uma alternativa e assim não tivesse ficado confuso compilaria o código e eu estaria usando no meu programa o conteúdo da variável errada (a de uma biblioteca em vez da local) o que levaria a defeitos difíceis de debugar.

ESP8266: Usar ESP Touch / SmartConfig é seguro?

Aparentemente, não.

Para quem não conhece, ESP Touch é o nome dado pela ESPRESSIF a um engenhoso método de comunicação de credenciais aparentemente copiado da Texas Instruments, que esta chama de SmartConfig (marca registrada Texas). Nesse método, um ESP8266 ainda não configurado, que não faz idéia de a qual rede se conectar e muito menos a senha, é colocado em “modo de monitoramento” e fica continuamente escutando o tráfego de todas as redes Wi-Fi a seu alcance (uma por vez, rapidamente).  Uma app rodando em um computador ou smartphone conectado a um roteador Wi-Fi o mais próximo do ESP8266 quanto possível transmite continuamente via pacotes UDP o SSID e a senha que você quer que o ESP8266 conheça.  Quando o ESP8266 finalmente esbarrar nessa informação ele se auto configura com o SSID e a senha coletados.

Nota: embora o protocolo permita que você transmita o SSID e a senha de um roteador diferente do qual está conectado, é recomendável que você se conecte ao mesmo roteador cuja senha quer dar ao dispositivo porque isso permite que a app detecte que o dispositivo se conectou (estarão no mesmo domínio de broadcast). Se o dispositivo se conectar a outro roteador provavelmente não será detectável. Por causa disso algumas apps nem te dão a opção de escolher o SSID.

Isso é possível mesmo numa rede criptografada porque a app codifica essa informação em um campo da transmissão Wi-Fi que qualquer um pode ver: o tamanho do pacote. É como usar código morse. O pacote continua criptografado, mas você pode ver o seu tamanho e esse tamanho corresponde a “uma letra” específica (não é exatamente assim, mas o princípio é esse).

Engenhoso e prático mas com um grande problema: qualquer outro dispositivo ou software compatível com SmartConfig ao alcance pode ver o mesmo tráfego e recuperar as credenciais de acesso. Aqui é explicado como se faz isso.

Aparentemente a Texas Instruments incluiu em versões mais recentes do Smart Config a capacidade de criptografar essa transmissão com AES. No caso a app e o dispositivo precisam ter combinado antes uma chave que vai ser usada para poder decodificar a transmissão (a app da Texas tem um campo para a chave, que vem em um QRCode no dispositivo). Essa é uma mudança trivial do ponto de vista do usuário, mas aparentemente não foi implementado no ESP8266. Segundo a documentação da biblioteca ESP8266 Arduino Core a sintaxe para iniciar o monitoramento é:

E apenas isso. Eu ficaria mais à vontade para usar o recurso se a sintaxe fosse algo como

E você precisasse colocar a mesma chave na app, junto com a senha do roteador.

A propósito, outro problema do SmartConfig é que raramente funciona e um dos problemas (mas não o único) é que o ESP8266 suporta apenas redes de 2.4GHz e a app não consegue diferenciar uma rede de 2.4GHz de uma de 5GHz. Pior ainda: se existirem duas redes com o mesmo SSID o Android dá preferência a se conectar à rede de 5GHz. Você ou o cliente do seu produto podem não se dar conta disso e o SmartConfig não vai funcionar. Usando o método “tradicional” de configuração se conectando ao SoftAP, pelo menos você tem menos chances de errar porque a varredura do ESP8266 só mostra as redes de 2.4GHz. Eu recomendo que você esqueça o SmarConfig e use SoftAP com CaptivePortal para a configuração.

ESP8266: Como obter o endereço IP do cliente HTTP

Essa informação é útil quando, por exemplo, você precisa determinar se o cliente está conectado pelo SoftAP, porque o endereço IP do cliente normalmente estará na faixa 192.168.4.x.

Só vai funcionar corretamente em uma função que manipule uma requisição do servidor, como as definidas por “WebServer.on()”. Em outras o resultado pode ser “0.0.0.0” ou o endereço IP de outro cliente.

Testado com ESP8266 Arduino Core 2.3.0.

 

ESP8266: O tamanho do stack é fixo em 4KB

Isso pode pegar você de surpresa. Mesmo com 30KB ou mais de RAM livre seu programa vai dar stack overflow com resultados imprevisíveis se você usar mais de 4KB em alguma rotina ou sucessão de rotinas encadeadas, o que é muito fácil usando, por exemplo, manipulação de strings com ArduinoJSON.

Isso é definido em cores\esp8266\cont.h:

#define CONT_STACKSIZE 4096

ESP8266: Problemas enlouquecedores provocados por alimentação

Se você acha que problemas de alimentação só podem levar a travamentos e resets vai ficar espantado. Estes são os problemas que podem ocorrer na falta de um capacitor eletrolítico de desacoplamento na linha de 3.3V, bem perto do chip:

  • SoftAP com funcionamento irregular, chegando a ser impossível usar. Fica aparecendo e desaparecendo da lista de APs detectados pelo celular;
  • No modo STA ou AP_STA não conecta a certos roteadores. Dá consistentemente erro de senha errada, apesar de consistentemente conectar a outros e funcionar por semanas sem problemas aparentes.

Problema detectado com diversos módulos ESP-01 usando o firmware ESP8266 Arduino Core. O mais louco é que o primeiro problema desaparece se você fizer um downgrade para a versão 2.0.0 do Core. Com as versões mais recentes 2.3.0 e 2.4.0-rc2 sempre se manifesta. Isso faz você achar que se trata de um bug de software quando se dá conta de que módulos programados dois anos atrás não manifestam o problema. Tirando esses problemas o módulo funciona aparentemente sem falhas.

Colocar um capacitor de 220uF x 10V (100uF podem bastar) entre os terminais +3.3V e GND do módulo resolve o problema

ESP8266: O que fazer quando WiFi.hostname() não funciona

Primeiramente é preciso que fique claro que o hostname definido nesta função é o chamado “DHCP hostname” e praticamente só serve para definir o que aparece na listagem de “DHCP leases” do roteador. Você não vai pode usá-lo para dar um “ping” a não ser que seu servidor DHCP seja também um servidor DNS. O ESP8266 já tem um hostname padrão no formato ESP_XXXXXX onde XXXXX são os seis últimos caracteres do endereço MAC e você não precisa usar WiFi.hostname() se esse hostname for suficiente para você.

Requerimentos para que WiFi.hostname() funcione:

  • A função precisa ser executada antes de WiFi.begin();
  • Só funciona se o ESP8266 estiver configurado para obter IP por DHCP;
  • Você precisa reiniciar o roteador e depois obter um IP por DHCP para ver o novo nome aparecer na lista.

Testado com ESP8266 Arduino Core 2.3.0.

 

ESP8266: Como enviar email pelo GMAIL.

O processo é muito parecido com o usado para enviar email criptografado para outros provedores. Os detalhes a atentar são:

  1. Você precisa configurar a conta gmail para permitir o acesso de “aplicativos menos seguros”, por isso é recomendável que você crie e configure uma conta no gmail só para isso;
  2. O servidor é smtp.gmail.com e a porta é 465;
  3. Nos campos “MAIL from” e “RCPT to” você deve preencher apenas o email, assim: <usuario@servidor.com> . Do contrário dará “syntax error”.

Erros que você pode encontrar:

  1. “MAIL first” – Neste momento o servidor esperava o comando “MAIL from:”
  2. “RCPT first” – Neste momento o servidor esperava o comando “RCPT TO:”
  3. “Syntax error” – Remova o “nome” da caixa postal. Deixe apenas o endereço de email;

Por que “aplicativos menos seguros”? Existe modo de contornar isso?

Aparentemente, não.

O gmail não parece explicar em lugar algum o que faz o aplicativo ser seguro ou não no conceito da Google. A minha suspeita é que tenha algo a ver com data/hora (para validar certificados) por duas razões:

  • As apps “seguras” da google também recusam seu login se, por exemplo, a data/hora do seu celular Android estiver errada;
  • Quando você habilita o debug “Core +SSL” do ESP8266 é exibida uma mensagem: “please start sntp first!” assim que você faz uma conexão criptografada. O autor da biblioteca, Igor, diz que essa mensagem é do SDK da Expressif e não dele e você pode “ignorá-la com segurança“, mas SNTP significa Simple Network Time Protocol e se o SDK quer que você tenha o horário correto antes da conexão, alguma razão existe.

E eu não faço idéia de como fazer o protocolo de comunicação ser configurado com data/hora corretos nem se isso seria suficiente.  A Google possivelmente quer se certificar de que você está validando o certificado dela antes de transmitir, mas isso é só um palpite.

 

ESP8266: Como enviar e-mail por uma conexão criptografada (SSL/TLS).

Em um post anterior eu mostrei como se enviava e-mail e adverti para o fato de que a conexão não era segura e as credenciais podiam ser interceptadas (além do fato óbvio do e-mail poder ser lido). Eu achei que enviar por uma conexão segura fosse muito complicado, mas descobri que não é. O problema é que usa muita RAM. O email sem criptografia te deixa com 46KB livres para o resto do seu programa enquanto este aqui te deixa com “apenas” 18KB. Lembre-se de que isso ainda é 9x a RAM total de um Arduino UNO.

Sobre fingerprints e validação de certificado

Se você usa um servidor de e-mail numa conta compartilhada, como é o caso da hostgator, o certificado não vai validar se você colocar o nome do seu domínio como servidor. Você tem que obter o nome correto do servidor de e-mail que atende a sua conta. Na hostgator isso pode ser visto no cPanel.

Por exemplo, meu servidor de e-mail normal seria: meudominio.com.br ou mail.meudominio.com.br mas para validar o certificado eu preciso colocar gator1234.hostgator.com.

O exemplo abaixo é uma adaptação simples do exemplo que não usa criptografia.

Por alto, as diferenças são 4:

1)Acrescente: #include <WiFiClientSecure.h>

2)Acrescente: const char* fingerprint = “fingerprint_aqui”;

3)Mude: WiFiClient client; para WiFiClientSecure client; 

4)Acrescente a validação de certificado logo após a conexão:

 

ESP8266: Os LEDs do módulo ESP-01

ESP-01_leds

O LED vermelho é ligado diretamente à alimentação e o LED azul é ligado ao TX da serial. Se você não usar a serial no seu projeto pode controlar esse LED usando GPIO1, conforme o código abaixo:

 

ESP8266: GPIO no módulo ESP-01

esp8266_esp01_automalabs

ESP-01_pinout_automalabs

O problema: o ESP-01 tem apenas dois GPIO disponíveis: GPIO0 e GPIO2 e ambos são usados no processo de boot do chip.

Por que é tão limitado ?

O meu melhor palpite é que ele não foi mesmo feito para isso. Quando o ESP-01 surgiu não existia essa facilidade que temos hoje para programá-lo diretamente. O fabricante do módulo, AI Thinker, criou um firmware que respondia a comandos AT e esse módulo foi criado para basicamente dar Wi-Fi a um projeto usando outro microcontrolador, como um Arduino. O módulo não precisava de GPIO para isso e o microcontrolador podia se comunicar por TX e RX e controlar seu status e até resetá-lo através dos pinos RST e CH_PD.

Para usar como saídas

Qualquer que seja o caso é recomendável que você tenha resistores de pull-up em ambos e assim o sinal ativo seja “LOW”.

Você pode usar ambos GPIO0 e GPIO2 como saídas, mas eu só recomendo no momento para LEDs e para i2C. GPIO2 especificamente é o TX da “hardware UART” na inicialização e por isso “pisca”. Acionar um relê com ele pode não ser uma boa ideia. GPIO0 parece ser seguro para relês mas ainda não estou certo disso.

Eu costumo usar assim e até agora não notei nenhum problema. Alguns recomendam colocar um pull-up de 4k7 ou 3k3 em paralelo com cada conjunto, mas ainda não vi real necessidade para isso:

ESP-01_output_leds

 

Para usar como entrada

Se qualquer um dos dois pinos estiver em nível baixo o ESP8266 poderá não inicializar. Você pode contornar o problema usando um dos GPIO como saída para ativar o uso do outro como entrada conforme mostra o último exemplo desta página, que é muito confuso por isso refiz assim:

ESP-01_GPIO

Durante o boot não importa se a chave S1 está aberta ou fechada, os resistores manterão GPIO0 e GPIO2 em nível alto. Quando rodar o programa você coloca GPIO2 como saída e em nível baixo, assim:

pinMode(2, OUTPUT);
digitalWrite(2, LOW);

Agora GPIO0 pode ser HIGH ou LOW dependendo da posição da chave. E assim você ganha uma entrada.

Mas o modo mais simples e “seguro” de ter uma entrada no ESP-01 é usar o pino RX da serial. Ele pode ser “liberado” no sketch com uma linha assim:

Serial.begin(115200,SERIAL_8N1,SERIAL_TX_ONLY);

É claro que você não vai poder transmitir nada para esse sketch, mas vai poder receber normalmente pela serial.

Outro modo, mais complicado, de expandir a capacidade de I/O do ESP-01 é usando i2C. Basta um chip como o PCF8574 para transformar GPIO0 e GPIO2 em até oito entradas/saídas perfeitamente usáveis.

 

ESP-01_PCF8574_I2C