Over-the-air updates
Upload new firmware over Wi-Fi with ArduinoOTA, so a board in a box on the shelf never needs a USB cable again.
Wiring
Nothing to wire. This one runs on the bare board.
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32 Dev Module
#include <WiFi.h>
#include <ESPmDNS.h>
#include <ArduinoOTA.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* OTA_NAME = "esp32-bench"; // the board appears as esp32-bench.local
const char* OTA_PASS = "change-me"; // asked for on every network upload
unsigned long lastBeat = 0;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
Serial.printf("wifi joining %s\n", WIFI_NAME);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("wifi failed, retrying in 5 s");
delay(5000);
WiFi.begin(WIFI_NAME, WIFI_PASS);
}
ArduinoOTA.setHostname(OTA_NAME);
ArduinoOTA.setPassword(OTA_PASS);
ArduinoOTA
.onStart([]() { Serial.printf("ota start: %s\n", ArduinoOTA.getCommand() == U_FLASH ? "sketch" : "filesystem"); })
.onProgress([](unsigned int done, unsigned int total) { Serial.printf("ota %u percent\r", done * 100 / total); })
.onEnd([]() { Serial.println("\nota done, restarting"); })
.onError([](ota_error_t error) { Serial.printf("ota error %u\n", error); });
ArduinoOTA.begin();
Serial.printf("ota ready: %s.local at %s\n", OTA_NAME, WiFi.localIP().toString().c_str());
}
void loop() {
ArduinoOTA.handle(); // call often: uploads only happen while this runs
if (millis() - lastBeat > 10000) {
lastBeat = millis();
Serial.printf("up %lu s, rssi %d dBm\n", millis() / 1000, WiFi.RSSI());
}
}Wiring
Nothing to wire. This one runs on the bare board.
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32S3 Dev Module
#include <WiFi.h>
#include <ESPmDNS.h>
#include <ArduinoOTA.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* OTA_NAME = "esp32-bench"; // the board appears as esp32-bench.local
const char* OTA_PASS = "change-me"; // asked for on every network upload
unsigned long lastBeat = 0;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
Serial.printf("wifi joining %s\n", WIFI_NAME);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("wifi failed, retrying in 5 s");
delay(5000);
WiFi.begin(WIFI_NAME, WIFI_PASS);
}
ArduinoOTA.setHostname(OTA_NAME);
ArduinoOTA.setPassword(OTA_PASS);
ArduinoOTA
.onStart([]() { Serial.printf("ota start: %s\n", ArduinoOTA.getCommand() == U_FLASH ? "sketch" : "filesystem"); })
.onProgress([](unsigned int done, unsigned int total) { Serial.printf("ota %u percent\r", done * 100 / total); })
.onEnd([]() { Serial.println("\nota done, restarting"); })
.onError([](ota_error_t error) { Serial.printf("ota error %u\n", error); });
ArduinoOTA.begin();
Serial.printf("ota ready: %s.local at %s\n", OTA_NAME, WiFi.localIP().toString().c_str());
}
void loop() {
ArduinoOTA.handle(); // call often: uploads only happen while this runs
if (millis() - lastBeat > 10000) {
lastBeat = millis();
Serial.printf("up %lu s, rssi %d dBm\n", millis() / 1000, WiFi.RSSI());
}
}Wiring
Nothing to wire. This one runs on the bare board.
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32C3 Dev Module
#include <WiFi.h>
#include <ESPmDNS.h>
#include <ArduinoOTA.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* OTA_NAME = "esp32-bench"; // the board appears as esp32-bench.local
const char* OTA_PASS = "change-me"; // asked for on every network upload
unsigned long lastBeat = 0;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
Serial.printf("wifi joining %s\n", WIFI_NAME);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("wifi failed, retrying in 5 s");
delay(5000);
WiFi.begin(WIFI_NAME, WIFI_PASS);
}
ArduinoOTA.setHostname(OTA_NAME);
ArduinoOTA.setPassword(OTA_PASS);
ArduinoOTA
.onStart([]() { Serial.printf("ota start: %s\n", ArduinoOTA.getCommand() == U_FLASH ? "sketch" : "filesystem"); })
.onProgress([](unsigned int done, unsigned int total) { Serial.printf("ota %u percent\r", done * 100 / total); })
.onEnd([]() { Serial.println("\nota done, restarting"); })
.onError([](ota_error_t error) { Serial.printf("ota error %u\n", error); });
ArduinoOTA.begin();
Serial.printf("ota ready: %s.local at %s\n", OTA_NAME, WiFi.localIP().toString().c_str());
}
void loop() {
ArduinoOTA.handle(); // call often: uploads only happen while this runs
if (millis() - lastBeat > 10000) {
lastBeat = millis();
Serial.printf("up %lu s, rssi %d dBm\n", millis() / 1000, WiFi.RSSI());
}
}Parts
| Quantity | Part | Where to buy |
|---|---|---|
| 1× | ESP32 dev board | Buy at Amazon |
| 1× | USB cable for the first upload |
Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.
Libraries
WiFi (built in), ArduinoOTA (built in), ESPmDNS (built in)
Load it
- In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
- Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
- Close the IDE's serial monitor, then open the bench here to watch the output.
Field notes
- The first upload has to go over USB. After that, the board shows up as a network port named esp32-bench in the Arduino IDE's port list, and Upload sends the sketch over Wi-Fi.
- Every sketch you upload over the air must include the OTA code too. Leave it out and the next update needs a USB cable again.
- Network uploads need a partition scheme with two app slots, such as the default. Huge APP and No OTA have only one slot and cannot take an update.
- Your computer and the board must be on the same network, and some guest or mesh networks block the mDNS lookups the IDE uses to find the board.
- In PlatformIO, set upload_protocol = espota, upload_port = esp32-bench.local and upload_flags = --auth=change-me.
- To update from a browser instead, the core's HTTPUpdateServer example serves an upload page for the compiled .bin file.
Not tested yet
- Not tested on hardware yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.
Built it? Send a build report with your board and what the serial port printed. Working reports become the "Tested on this board" entries above.