18 novembro 2018

Como programar o ESP32 por Wifi usando OTA

Não seria ótimo se livrar dos cabos na hora de programar o seu módulo ESP32? Isso é possível com o OTA (Over-The-Air), um modo de programação onde você utiliza a rede wifi para transferir remotamente o sketch (programa) para a sua placa.

Programar ESP32 wifi com OTA

O uso do OTA leva os seu projeto de Internet das Coisas (IoT) para um outro patamar, minimizando erros causados por remontagem de circuitos e permitindo a atualização de um programa em poucos minutos.


O que é e por que você precisa do OTA


O OTA está disponível em várias placas do mercado, como a linha ESP8266 e a ESP32, e permite que você (re)programe o módulo remotamente via wifi, sem a necessidade de conectar o módulo em um computador.


Isso é muito útil quando o módulo está em um local de difícil acesso e você precisa alterar alguma coisa na programação. Em condições "normais", você teria que retirar por exemplo o ESP32 do circuito, conectá-lo em um computador, reprogramá-lo e depois devolver o módulo para o circuito.

wifi plantação
 
Um grande transtorno se o seu módulo estiver dentro de algum equipamento, no meio de uma plantação coletando dados ou em algum outro local onde montar e desmontar um circuito não seja uma tarefa fácil.

Com o OTA, basta que o módulo esteja na mesma rede do computador, e toda a programação será feita via rede wireless.

Preparação do módulo ESP32 na IDE Arduino


Antes de mais nada, precisamos preparar a IDE do Arduino para utilização com o ESP32. Entre na IDE e no menu Arquivo -> Preferências, adicione a URL abaixo no campo URLs Adicionais para Gerenciadores de Placas:

https://dl.espressif.com/dl/package_esp32_index.json

Sua tela ficará assim:

IDE Arduino - Preferências

Clique em OK e em seguida vá até o menu Ferramentas -> Placa -> Gerenciador de Placas e procure por ESP32, selecionando ESP32 by Espressif Systems e clique em Instalar:

ESP32 by Espressif Systems

Aguarde alguns instantes e as placas da linha ESP32 serão instaladas na IDE do Arduino. Novamente no menu Ferramentas -> Placa, selecione agora ESP32 Dev Module, conforme a imagem abaixo:

IDE Arduino ESP32 Dev Module

Com a seleção desta placa, serão adicionados novos exemplos na IDE do Arduino específicos para utilização com o ESP32.

Carregando o BasicOTA no módulo ESP32


Um desses exemplos é o que vamos utilizar para configurar o módulo ESP32 para que ele fique "esperando" uma conexão via rede wifi para atualização do programa. Esse exemplo é o BasicOTA, e você pode carregá-lo no menu Arquivo -> Exemplos -> ArduinoOTA -> BasicOTA:

ESP32 BasicOTA

No programa BasicOTA, que eu reproduzo abaixo, configure nas linhas 6 e 7 o nome e senha, respectivamente, da sua rede wifi. É a única alteração no programa:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char* ssid = "SUA-REDE-WIFI";
const char* password = "SUA-SENHA-WIFI-AQUI";

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  // ArduinoOTA.setHostname("myesp32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.begin();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
}

Observe que nessa parte ainda estamos com o módulo fisicamente conectado no computador, acessando o ESP32 via porta serial (COM). Transfira então o BasicOTA normalmente para o módulo. Não esqueça que em alguns módulos é necessário manter pressionado o botão BOOT para que o programa seja transferido corretamente.

Reinicie o ESP32 (no meu módulo, é o botão EN) e aguarde o processo de configuração, que pode ser acompanhado pelo serial monitor:

Serial Monitor OTA


Na última linha mostrada na imagem acima, temos o endereço IP que foi obtido pelo ESP32: 192.168.0.124.

Programando o ESP32 por Wifi usando OTA


Agora vamos desconectar o módulo ESP32 do computador e transferir um programa remotamente. Alimente o módulo com uma fonte externa (uma fonte de telefone celular, por exemplo).

Abra a IDE do Arduino e no menu Ferramentas -> Porta, observe que foi adicionada uma porta de rede com o endereço IP obtido anteriormente:

Network port - Porta de Rede IDE Arduino

Selecione essa porta e carregue o programa abaixo na IDE. O grande "segredo" deste programa é a manutenção da estrutura usada anteriormente no BasicOTA, onde vamos manter as chamadas das bibliotecas, as configurações de acesso a rede wifi (para que o módulo permaneça conectado) e também as chamadas para o ArduinoOTA, que fará com que o ESP32 continue aguardando o carregamento de novos programas quando for necessário.

Temos então o mesmo programa usado anteriormente, mas agora com as configurações para que o led onboard do ESP32 pisque em intervalos regulares. Acrescentamos:

  • Na linha 10 a definição da porta 2 como saída
  • Dentro do loop, entre as linhas 69 e 72, a rotina para que o led acenda e apague em intervalos de 1 segundo

Nosso programa então fica assim. Não esqueça de novamente colocar o nome e senha da sua rede wifi nas linhas 6 e 7:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

const char* ssid = "SUA-REDE-WIFI";
const char* password = "SUA-SENHA-WIFI-AQUI";

void setup() {
  pinMode(2, OUTPUT); //Linha incluida
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  // ArduinoOTA.setHostname("myesp32");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";

    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    Serial.println("Start updating " + type);
  })
  .onEnd([]() {
    Serial.println("\nEnd");
  })
  .onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  })
  .onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });

  ArduinoOTA.begin();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
  digitalWrite(2, HIGH); //Linha incluida
  delay(1000); //Linha incluida
  digitalWrite(2, LOW); //Linha incluida
  delay(1000); //Linha incluida
}

Se você estiver usando Windows, na primeira vez que você tentar transferir o programa ele vai mostrar um aviso do firewall, indicando que o espota.exe está tentando acessar a rede. No nosso caso habilitamos as opções de acesso a rede pública e privada e selecionamos Allow Access (Permitir Acesso):

Espota.exe Firewall Windows

Por causa desse aviso, a IDE do Arduino pode mostrar uma mensagem de erro. Observe que no lado inferior direito da IDE estamos usando como porta para transferência o IP 192.168.0.124:

OTA Erro transferência

Refaça o procedimento de upload do programa, e se tudo estiver ok, o programa será carregado corretamente e o led onboard do módulo ESP32 começara a piscar:

OTA Transferência OK


2 comentários:

  1. Qual seu email para contratar sua consultoria? Trata-se de algo simples e que não estou conseguindo fazer com motor de passo.

    ResponderExcluir
    Respostas
    1. Oi Gustavo,

      Utilize o formulário de contato no lado direito da página, por favor. Daí conversamos.

      Abraço e obrigado!

      Adilson

      Excluir