OTA (Over-The-Air) update allows deploying new firmware to a microcontroller without physical connection, via WiFi, Bluetooth or a remote server. On ESP32, OTA is natively supported by ESP-IDF and ArduinoESP32, making it an essential tool for modern IoT projects. This article presents motivations, OTA types, partition architecture, implementation examples, application domains and professional best practices.
1. Why use OTA
1.1 Main Advantages
- Remote maintenance: no need for physical access.
- Mass deployment: update hundreds of devices simultaneously.
- Security: quick fixes in case of vulnerabilities.
- Cost and time saving: no disassembly, no cables.
- Improved user experience: device remains operational.
1.2 OTA Security
Security is paramount when implementing remote updates to prevent unauthorized modifications:
- Firmware signature: Verifying the authenticity of the author.
- Integrity verification (SHA256): Ensuring the file hasn't been corrupted.
- HTTPS connection: Encrypting the transmission channel.
- Authentication: Using tokens or API keys to authorize updates.
2. OTA Architecture on ESP32
ESP32 uses dedicated partitions in its flash memory to manage the update process safely. A typical partition table includes:
The Update Principle:
- Current firmware runs on ota_0.
- New firmware is downloaded into ota_1 (the inactive partition).
- The Bootloader validates the new firmware.
- System restarts and switches to the new partition.
- Automatic rollback: If the new firmware fails to boot, the system reverts to the previous working partition.
3. Types of OTA on ESP32
| OTA Type | Description | Use Case |
|---|---|---|
| Local OTA (Web Server) | ESP32 hosts a web page to upload firmware manually. | Prototyping, local maintenance |
| OTA via WiFi + HTTP(S) | ESP32 downloads firmware from a remote server (URL). | Large-scale deployment |
| OTA via MQTT | Firmware download triggered by an MQTT specific message. | Industrial IoT networks |
| OTA via Bluetooth | Update performed via a smartphone app. | Mobile devices, wearables |
4. Implementation Examples (ESP32)
4.1 OTA via WiFi with ESP32
This method is ideal for local updates within the same network.
#include <WiFi.h>
#include <ArduinoOTA.h>
const char *ssid = "Your_SSID";
const char *password = "Your_PWD";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
ArduinoOTA.setHostname("ESP32-OTA");
ArduinoOTA.setPassword("OTApassword");
ArduinoOTA.onStart([]() {
Serial.println("OTA Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nOTA End");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u %%\r", (progress * 100) / total);
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("OTA Error: %u\n", error);
});
ArduinoOTA.begin();
}
void loop() {
ArduinoOTA.handle();
}
4.2 OTA via HTTP Server (Update from URL)
The device fetches the update from a centralized server.
#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>
const char *ssid = "Your_SSID";
const char *password = "Your_PWD";
const char *firmware_url = "http://your-server.com/firmware.bin";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi OK");
HTTPClient http;
http.begin(firmware_url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
int contentLength = http.getSize();
WiFiClient *stream = http.getStreamPtr();
if (Update.begin(contentLength)) {
size_t written = Update.writeStream(*stream);
if (written == contentLength) {
Serial.println("Firmware downloaded");
}
if (Update.end()) {
if (Update.isFinished()) {
Serial.println("Update OK, reboot...");
ESP.restart();
}
}
}
}
http.end();
}
void loop() {}
4.3 OTA via Integrated Web Server (Manual Upload)
Hosts a simple form to upload the .bin file from a browser.
#include <WiFi.h>
#include <WebServer.h>
#include <Update.h>
WebServer server(80);
void handleRoot() {
server.sendHeader("Connection", "close");
server.send(200, "text/html",
"");
}
void handleUpdate() {
HTTPUpload &upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Update.begin();
} else if (upload.status == UPLOAD_FILE_WRITE) {
Update.write(upload.buf, upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
Update.end(true);
}
}
void setup() {
WiFi.begin("SSID", "PWD");
while (WiFi.status() != WL_CONNECTED) delay(500);
server.on("/", HTTP_GET, handleRoot);
server.on("/update", HTTP_POST, []() {
server.send(200, "text/plain", Update.hasError() ? "Error" : "OK");
}, handleUpdate);
server.begin();
}
void loop() {
server.handleClient();
}
5. Application Domains
Industry & IoT
Home Automation
Automotive
R&D
6. Best Practices for OTA
Security
- Always use HTTPS.
- Verify firmware signature and SHA256.
- Employ strong OTA passwords.
Architecture
- Plan for two OTA partitions.
- Enable automatic rollback.
- Store the current version in NVS.
Monitoring
- Log all updates.
- Notify in case of failure.
- Maintain a versioned firmware server.
7. Conclusion
OTA is an indispensable feature for any serious ESP32 project. It enables maintenance, bug fixing, and feature enhancement without physical intervention, while ensuring security, flexibility, and scalability.