Atualização do firmware do ESP8266 por WiFi

Redes Sociais

Introdução

Também conhecido como OTA, a auto atualização do firmware via WiFi é uma técnica utilizada para subir um novo programa no ESP8266 sem precisar conectar ele novamente na USB do computador. Ou seja, atualizamos o sketch do módulo via rede WiFi.

De forma resumida, nós compilamos o novo código, pegamos o arquivo *.bin e fazemos upload em um formulário como o exemplo abaixo:

Quando clicamos no botão “Enviar” todo o processo de atualização é feito automaticamente pelo ESP8266 sem precisarmos nos preocupar em tirar ele de onde ele estiver instalado e conectá-lo no computador. Tudo é feito via WiFi, de forma transparente!

Requisitos Básicos

O requisito mais importante é que o novo código a ser atualizado no ESP8266 seja menor que a metade do tamanho total da memória Flash. Isso porque o arquivo carregado por upload precisa primeiro ser gravado em algum lugar e depois atualizado.

Caso deseje saber como descobrir o tamanho da memória Flash do seu ESP8266, leia esse outro artigo aqui.

Instruções para implementar a Auto atualização

Primeiro faça o download do código de exemplo na coluna da direita dessa página.

Repare que temos uma função que monta o HTML do formulário de upload chamada updateWifiIni():

// Função que monta o formulário de upload do arquivo de update
void updateWifiIni() 
{
  String html = "<html><head><title>Update Firmware</title>";
  html += "<style>body { background-color: #cccccc; font-family: Arial, ";
  html += " Helvetica, Sans-Serif; Color: #000088; }</style>";
  html += "</head><body>";
  html += "<h1>Update Firmware</h1>";
  html += "<form method=POST action='/update' enctype='multipart/form-data'>";
  html += "<p><input type='file' name='update'></p>";
  html += "<p><input name=button1 type=submit value=Enviar /></p></form>";
  html += "</body></html>";

  server.sendHeader("Connection", "close");
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.send(200, "text/html", html);
}

Esse formulário é simples e contém apenas um campo de upload de arquivo e um botão “Enviar”.

Na sequência temos o código que monta uma página de resposta que apenas apresenta um HTML que informa ao usuário se o processo ocorreu com sucesso ou falhou.

// Função que recebe o post do formulário que carrega o arquivo de upload
void updateWifiFim() 
{
  String html = "<html><head><title>Update Firmware</title>";
  html += "<style>body { background-color: #cccccc; font-family: Arial, ";
  html += " Helvetica, Sans-Serif; Color: #000088; }</style>";
  html += "</head><body>";
  html += "<h1>Update Firmware</h1>";
  
  if (Update.hasError())
    html += "<p>Erro ao carregar firmware!</p>";
  else
    html += "<p>Firmware carregado com sucesso!</p>";
    
  html += "<form method=GET>";
  html += "<p><input name=button2 type=submit value=Voltar /></p></form>";
  html += "</body></html>";

  server.sendHeader("Connection", "close");
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.send(200, "text/html", html);
  ESP.restart();
}

Esta função faz uso do método Update.hasError() para saber se o processo teve algum erro e exibe uma mensagem de acordo com o resultado.

A última instrução reinicia o ESP8266 através do comando ESP.restart().

Já a parte de código abaixo é a responsável por receber o arquivo do novo firmware, verificar se tem espaço para gravar o arquivo e lida com todo o processo de atualização.

// Função que lida com o upload e a atualização do arquivo recebido
void funcUpdate()
{
  HTTPUpload& upload = server.upload();
  // Se o arquivo iniciou o upload verifica se tem espaço e mostra o nome do 
  // arquivo na serial
  if(upload.status == UPLOAD_FILE_START)
  {
    Serial.setDebugOutput(true);
    Serial.printf("Update: %s\n", upload.filename.c_str());
    uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
    // Verifica se deu erro de espaço
    if(!Update.begin(maxSketchSpace))
    {
      Update.printError(Serial);
    }
  } 
  // Se o download estiver em andamento, grava os trecho do arquivo 
  else if(upload.status == UPLOAD_FILE_WRITE)
  {
    if(Update.write(upload.buf, upload.currentSize) != upload.currentSize)
    {
      Update.printError(Serial);
    }
  } 
  // Caso o upload terminou, atualiza e reinicia o ESP
  else if(upload.status == UPLOAD_FILE_END)
  {
    if(Update.end(true))
    { //true to set the size to the current progress
      Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
    }
    else 
    {
      Update.printError(Serial);
    }
    Serial.setDebugOutput(false);
  }
  yield();
}

Veja que esse código é separado por 3 partes de um if, sendo o primeiro que verifica que o processo de upload começou, validando o status do processo tem o valor de UPLOAD_FILE_START. Nessa parte o ESP verifica se existe espaço para acomodar o novo sketch, e também imprime na Serial o nome do arquivo sendo feito upload.

O segundo if verifica se o o status é UPLOAD_FILE_WRITE, ou seja, se os trechos do arquivo estão em processo de gravação.

Por fim, o último if verifica se o processo de upload terminou comparando o status do processo com UPLOAD_FILE_END.

Nessa etapa chamamos a função Update.end(true) para fazer o processo de atualização do arquivo que acabou de ser enviado.

Se tudo der certo o ESP8266 reinicia, senão apresenta um erro na Serial.

O mecanismo que configura a todo esse processo é feito no setup() do código, quando definimos o handle(), assim:

server.on("/update", HTTP_POST, updateWifiFim, funcUpdate);

Sendo que o caminho onde será feito o upload é o “/update” e o método é HTTP_POST, a função que vai lidar com o request é a updateWifiFim e a função que vai lidar com o upload é a funcUpdate.

Pronto, só isso é suficiente para atualizarmos o nosso programa via WiFi!

Como usar

Antes de mais nada configure o SSID e a senha da sua rede nas linhas abaixo do código:

const char* ssid = "XXXX";
const char* password = "YYYY";

Primeiro conecte o ESP8266 no computador e suba o programa pela primeira vez. Dessa vez tem que ser pelo computador. As vezes seguintes que serão pelo WiFi.

Se tiver dúvidas siga os vídeos indicados ao lado, na barra a direita.

Depois que subiu o programa, abra o monitor da serial e descubra o IP do ESP8266.

(clique na imagem para ampliar)

Acesse o IP adicionando o caminho “/update” no final, assim:

http://192.168.15.17/update

Então a página com o formulário de upload vai aparecer:

Nesse momento vamos voltar para a IDE do Arduino e alterar o programa para subir uma versão diferente via WiFi.

Mude a linha abaixo de:

server.send(200, "text/plain", "hello from esp8266!");

para:

server.send(200, "text/html", "<a href=update>OTA update</a>");

Agora vamos configurar uma opção para ligar as mensagens de saída durante a compilação. Acesse o menu Arquivo > Preferências e marque a opção indicada na imagem abaixo:

(clique na imagem para ampliar)

Pode compilar o programa (clicando no menu Sketch > Verificar/Compilar) e vamos verificar nas mensagens de saída para achar o diretório onde o arquivo *.bin é gravado. Veja a imagem abaixo:

(clique na imagem para ampliar)

Agora que você descobriu onde o arquivo foi gravado, volte no formulário de upload, escolha o arquivo *.bin e clique em “Enviar”.

Pronto! Todo o resto do processo o próprio ESP8266 faz sozinho.

Acesse a página inicial para ver a mudança do sketch:

(clique na imagem para ampliar)

Mais Informações

Veja o documento original (em inglês) que inspirou este meu post, clicando aqui.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *