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.