Introduction
Eventuially you are done with your esp8266 software. Flash it, move it into production.
But then: an error! Remove the esp8266 module from production site, flash it, build it into the device again etc etc.
Life could so much be easier if there where a way to do a Wifi update!
What do you say? It all exists? You are right, the example httpupdate has all the details needed to include a update mechanism into your running esp program. It will look for an update server and flash itself, if it finds an update.
So far, so easy. But there are only three minor annoyances: where is this bin file created by the Arduino IDE, how to copy it to the update server and why must I do it by hand?
This guide will make it automatic. On/Off by a menue switch. Just build on your local maschine with your local device or build and distribute to all devices. One switch does it all.
(Warning: Windows ahead!)
Step One
Create a folder on your developing machine. Somewhere.
C:\data\
Step Two
Locate boards.txt. It should be in a folder looking like this
C:\Users\yourusername\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0-rc2Yes, it is that difficult. No, there is no easy way.
Make the following changes:
menu.UploadSpeed=Upload Speed menu.CpuFrequency=CPU Frequency menu.FlashSize=Flash Size menu.FlashMode=Flash Mode menu.FlashFreq=Flash Frequency menu.ResetMethod=Reset Method menu.ESPModule=Module menu.Debug=Debug port menu.DebugLevel=Debug Level menu.LwIPVariant=lwIP Variant #add this>>> menu.MoveToWebServer=Copy to UploadServer ############################################################## generic.name=Generic ESP8266 Module generic.upload.tool=esptool generic.upload.speed=115200 generic.upload.resetmethod=ck generic.upload.maximum_size=434160 generic.upload.maximum_data_size=81920 generic.upload.wait_for_upload_port=true generic.serial.disableDTR=true generic.serial.disableRTS=true generic.build.mcu=esp8266 generic.build.f_cpu=80000000L generic.build.board=ESP8266_ESP01 generic.build.core=esp8266 generic.build.variant=generic generic.build.flash_mode=qio generic.build.spiffs_pagesize=256 generic.build.debug_port= generic.build.debug_level= #add this>>> generic.menu.MoveToWebServer.no=No generic.menu.MoveToWebServer.no.webserver.move=no generic.menu.MoveToWebServer.yes=Yes generic.menu.MoveToWebServer.yes.webserver.move=yes
Step Three
Locate platform.txt. It is in the same folder like boards.txt.
Append the following changes to the end of the file:
# ---------------------------------- recipe.hooks.objcopy.postobjcopy.01.pattern = cmd.exe /c "c:\data\doit.cmd {webserver.move} {build.path} {build.project_name}.bin c:\data\bin.dat"
Step Four
Now you need a web server. Somewhere in your net. This is beyond the scope of this paper. I took a Raspberry Pi because it was there. Any other would do.
You need network access to the documents folder of the web server. With that you can create a batch file in your data folder that copies the files from your local machine to the web server.
If you want to publish the file somewhere else: this is where you can do a ftp upload or whatever you want.
I named the batch "doit.cmd", look at the file names in step three. And my raspberry goes by PHORKYS.
rem %1 yes/no from IDE menu rem %2 build path rem %3 build file name if "%1"=="yes" ( copy /b %2\%3 \\PHORKYS\Root\var\www\%3 )
Step Five
Prepared like this your Arduino Sketch can query the server and fetch the file, flash itself and reboot. I do it with this small routine.
You need to change the UpdateFileUrl fitting to your server and project folder name.
//=================================================================================== const String UpdateFileUrl = "http://PHORKYS/sketchname.ino.bin"; const String UpdateSPIFFSFileName = "/.update.txt"; void CheckUpdateFile(void) { HTTPClient http; http.begin(UpdateFileUrl); const char * headerkeys[] = {"Last-Modified"} ; // could use etag, too size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*); http.collectHeaders(headerkeys, headerkeyssize); int code = http.GET(); int len = http.getSize(); http.end(); // nur sinnvoll, wenn überhaupt eine Datei gelesen if (code = 200) { // Header zusammensammeln String id = String(len); for (int i = 0; i < http.headers(); i++) { id += http.header(i); } String sid = "x"; // Serial.println(id); // Update-Data lesen File file = SPIFFS.open(UpdateSPIFFSFileName, "r"); if (file) { sid = file.readStringUntil('\n'); } file.close(); if (! sid.startsWith(id)) { Serial.println(F("Beginne Update")); // https://github.com/esp8266/Arduino/issues/1017 // Automatic reboot after wdt reset // The only time software reset doesn't work is immediately following a serial // upload. If you reset the module physically after serial upload and place it // into normal (non-bootloader) mode, software reset will work. t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateFileUrl); switch (ret) { case HTTP_UPDATE_FAILED: Serial.print(F("Update error ")); Serial.print(ESPhttpUpdate.getLastError()); Serial.print(" = "); Serial.print(ESPhttpUpdate.getLastErrorString()); Serial.println(); break; case HTTP_UPDATE_NO_UPDATES: Serial.println(F("HTTP_UPDATE_NO_UPDATES")); break; case HTTP_UPDATE_OK: Serial.println(F("HTTP_UPDATE_OK")); break; } // Update-Data schreiben file = SPIFFS.open(UpdateSPIFFSFileName, "w"); if (!file) { Serial.println(F("Panic: update file write access failed")); } else { file.println(id); } file.close(); } } }
It needs some includes, initialized SPIFFS and WIFI and all.
#include "FS.h" #include <ESP8266HTTPClient.h> #include <ESP8266httpUpdate.h>