ESP32 OTA-Updates: Firmware kabellos über WLAN aufspielen (ArduinoOTA & Web-Updater)
Dein ESP32 hängt fertig verbaut im Gehäuse unter der Decke, im Garten oder hinter dem Aquarium – und genau jetzt fällt dir ein Tippfehler im Code auf. Leiter holen, Gehäuse öffnen, USB-Kabel anstöpseln? Muss nicht sein. Mit OTA-Updates (Over-the-Air) flashst du neue Firmware bequem übers WLAN – direkt aus der Arduino IDE oder sogar per Browser-Upload. In diesem Tutorial richtest du ArduinoOTA Schritt für Schritt ein, integrierst es sauber in deine bestehenden Sketche, baust einen Web-Updater für Firmware-Uploads per Browser und sicherst alles mit einem Passwort ab.
Wie funktioniert ein OTA-Update?
Der Flash-Speicher des ESP32 ist in Partitionen aufgeteilt – ähnlich wie eine Festplatte. Beim Standard-Schema gibt es zwei gleich große App-Partitionen: In der einen läuft dein aktuelles Programm, die andere ist frei. Ein OTA-Update schreibt die neue Firmware in die freie Partition, prüft sie und markiert sie als Boot-Partition. Beim nächsten Neustart startet der ESP32 aus der neuen Partition – schlägt irgendetwas fehl, bleibt die alte Firmware unangetastet.
Das Schöne daran: Dieses Sicherheitsnetz ist eingebaut. Ein abgebrochener Upload (WLAN weg, Strom weg) macht dein Board nicht kaputt – es läuft einfach mit der alten Version weiter. Voraussetzung ist nur, dass die laufende Firmware den OTA-Code enthält. Und das führt zur wichtigsten Regel dieses Tutorials:
⚠️ Die eiserne OTA-Regel: Das erste Update kommt immer noch per USB-Kabel – nämlich der Sketch, der OTA überhaupt erst aktiviert. Und: Jeder später per OTA hochgeladene Sketch muss den OTA-Code wieder enthalten. Vergisst du ihn einmal, ist die Funkstrecke tot und du musst doch wieder mit dem Kabel ran.
Das brauchst du
Falls dein ESP32 noch nie am WLAN war: Die Grundlagen von WLAN-Verbindung und Webserver erklärt der Artikel ESP32 Webserver einrichten.
1ArduinoOTA aktivieren: der Basis-Sketch
Die Bibliothek ArduinoOTA ist im ESP32-Boardpaket schon enthalten – nichts zu installieren. Dieser Sketch verbindet sich mit dem WLAN und lauscht auf Update-Anfragen aus der IDE. Lade ihn einmal klassisch per USB hoch:
#include <WiFi.h>
#include <ArduinoOTA.h>
const char* WLAN_NAME = "DeinWLAN";
const char* WLAN_PASSWORT = "DeinPasswort";
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WLAN_NAME, WLAN_PASSWORT);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.printf("\nVerbunden! IP: %s\n", WiFi.localIP().toString().c_str());
ArduinoOTA.setHostname("esp32-wohnzimmer"); // Name im Netzwerk-Menue
ArduinoOTA
.onStart([]() { Serial.println("OTA-Update startet ..."); })
.onProgress([](unsigned int done, unsigned int total) {
Serial.printf("Fortschritt: %u %%\r", (done * 100) / total);
})
.onEnd([]() { Serial.println("\nFertig! Neustart ..."); })
.onError([](ota_error_t fehler) {
Serial.printf("Fehler [%u]\n", fehler);
});
ArduinoOTA.begin();
Serial.println("Bereit fuer OTA-Updates.");
}
void loop() {
ArduinoOTA.handle(); // MUSS regelmaessig aufgerufen werden
}
Nach dem Upload und Neustart erscheint das Board in der Arduino IDE als Netzwerkgerät. So flashst du ab jetzt kabellos:
- Arduino IDE (neu) öffnen: Werkzeuge → Port – unter \"Netzwerk-Ports\" taucht
esp32-wohnzimmer at 192.168.x.xauf - Diesen Netzwerk-Port auswählen (statt des seriellen COM-Ports)
- Ganz normal auf Hochladen klicken – der Sketch wandert übers WLAN aufs Board
- Der ESP32 startet automatisch mit der neuen Firmware neu
ℹ️ PC und ESP32 müssen im selben Netz sein: Die IDE findet das Board per mDNS-Broadcast. Gäste-WLANs, VPNs oder strenge Firewalls blockieren das oft – der Troubleshooting-Abschnitt unten hilft dann weiter.
2OTA in dein echtes Projekt integrieren
Der Basis-Sketch tut nichts außer warten. In der Praxis soll OTA neben deiner eigentlichen Anwendung laufen. Dafür gibt es nur zwei Anforderungen: ArduinoOTA.handle() muss regelmäßig drankommen, und dein Code darf den loop() nicht mit langen delay()-Aufrufen blockieren. Hier das Muster mit einer nicht-blockierenden Blink-LED als Platzhalter für deine Anwendung:
#include <WiFi.h>
#include <ArduinoOTA.h>
const char* WLAN_NAME = "DeinWLAN";
const char* WLAN_PASSWORT = "DeinPasswort";
const int LED = 2; // Onboard-LED
unsigned long letzterWechsel = 0;
bool ledAn = false;
void otaEinrichten() {
ArduinoOTA.setHostname("esp32-projekt");
ArduinoOTA.begin();
}
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.begin(WLAN_NAME, WLAN_PASSWORT);
while (WiFi.status() != WL_CONNECTED) delay(500);
otaEinrichten();
Serial.printf("Laeuft! IP: %s\n", WiFi.localIP().toString().c_str());
}
void loop() {
ArduinoOTA.handle(); // 1. immer zuerst
// 2. deine Anwendung - nicht-blockierend mit millis()
if (millis() - letzterWechsel >= 1000) {
letzterWechsel = millis();
ledAn = !ledAn;
digitalWrite(LED, ledAn);
}
}
💡 Versionsnummer mitgeben: Gib beim Start eine Versionsnummer aus (Serial.println("Firmware v1.4");) oder zeige sie auf einem Display an. Bei kabellosen Updates verliert man sonst schnell den Überblick, welche Version gerade auf welchem Board läuft – spätestens beim dritten ESP32 im Haus.
⚠️ OTA und Deep Sleep vertragen sich schlecht: Ein schlafender ESP32 kann keine Updates empfangen. Üblicher Kompromiss: Das Board bleibt nach dem Aufwachen ein kurzes Zeitfenster (z. B. 30 Sekunden) wach und lauscht auf OTA, bevor es wieder schlafen geht – oder du aktivierst den Wartungsmodus über einen Taster.
3Web-Updater: Firmware per Browser hochladen
ArduinoOTA setzt voraus, dass auf dem Rechner die Arduino IDE läuft. Es geht auch ohne: Der ESP32 kann selbst eine Update-Webseite ausliefern, auf der du eine kompilierte .bin-Datei hochlädst – praktisch, wenn du Firmware an Freunde weitergibst, die keine IDE installiert haben. Dafür exportierst du in der IDE mit Sketch → Kompilierte Binärdatei exportieren die .bin-Datei.
#include <WiFi.h>
#include <WebServer.h>
#include <Update.h>
const char* WLAN_NAME = "DeinWLAN";
const char* WLAN_PASSWORT = "DeinPasswort";
WebServer server(80);
const char* SEITE =
"<h1>ESP32 Web-Updater</h1>"
"<form method='POST' action='/update' enctype='multipart/form-data'>"
"<input type='file' name='firmware'>"
"<input type='submit' value='Update starten'></form>";
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WLAN_NAME, WLAN_PASSWORT);
while (WiFi.status() != WL_CONNECTED) delay(500);
Serial.printf("Web-Updater: http://%s\n", WiFi.localIP().toString().c_str());
server.on("/", HTTP_GET, []() { server.send(200, "text/html", SEITE); });
server.on("/update", HTTP_POST,
[]() { // Antwort nach dem Upload
server.send(200, "text/plain", Update.hasError() ? "FEHLER" : "OK - Neustart");
delay(500);
ESP.restart();
},
[]() { // Upload-Datenstrom verarbeiten
HTTPUpload& up = server.upload();
if (up.status == UPLOAD_FILE_START) {
Update.begin(); // freie Partition oeffnen
} else if (up.status == UPLOAD_FILE_WRITE) {
Update.write(up.buf, up.currentSize); // Firmware-Haeppchen schreiben
} else if (up.status == UPLOAD_FILE_END) {
Update.end(true); // pruefen und aktivieren
}
});
server.begin();
}
void loop() {
server.handleClient();
}
Rufe die IP des Boards im Browser auf, wähle die .bin-Datei und klicke auf \"Update starten\" – nach wenigen Sekunden bootet der ESP32 mit der neuen Firmware. Die Weboberfläche kannst du beliebig ausbauen, zum Beispiel mit Statusanzeigen deiner Sensoren auf derselben Seite.
4Absichern: Passwortschutz für OTA
Ohne Schutz kann jeder im selben WLAN deinem ESP32 neue Firmware unterschieben. Für ArduinoOTA genügt eine Zeile vor ArduinoOTA.begin():
ArduinoOTA.setPassword("geheim123");
// besser: nur den MD5-Hash im Code speichern
// (Hash von "geheim123" vorher z. B. per Online-Tool erzeugen)
// ArduinoOTA.setPasswordHash("5715790a892990382d98858c4aa38d0e");
Die IDE fragt das Passwort dann beim ersten kabellosen Upload ab. Beim Web-Updater schützt du die Seite mit HTTP-Basic-Auth:
server.on("/", HTTP_GET, []() {
if (!server.authenticate("admin", "geheim123")) {
return server.requestAuthentication();
}
server.send(200, "text/html", SEITE);
});
ℹ️ Realistische Einordnung: Passwortschutz hält neugierige Mitbewohner und versehentliche Uploads aufs falsche Board ab – für kritische Anwendungen gehört das Board zusätzlich in ein eigenes IoT-WLAN. Fürs Heimnetz ist die Kombination aus Passwort und eigenem Netz ein solider Standard.
Wofür sich OTA besonders lohnt
📡 Typische OTA-Kandidaten
- Fest verbaute Projekte: Wetterstation im Gehäuse, Sensorknoten im Garten, LED-Steuerung hinterm Schrank
- Smart-Home-Knoten: MQTT-Sensoren bekommen neue Features, ohne dass du sie abmontierst – siehe MQTT mit ESP32 & Home Assistant
-
Mehrere Boards gleichzeitig pflegen: Jedes Board bekommt per
setHostname()einen sprechenden Namen und ist in der IDE sofort zuzuordnen -
ESP8266-Projekte: Der Code funktioniert fast identisch auf dem Wemos D1 Mini – nur
WiFi.hdurchESP8266WiFi.hersetzen
Perfekt für: alles, was du nach dem Einbau nie wieder anfassen willst
Troubleshooting
⚠️ Netzwerk-Port taucht in der IDE nicht auf: mDNS-Problem. Prüfe, ob PC und ESP32 im selben WLAN hängen (nicht im Gästenetz!), deaktiviere testweise VPN und Firewall und starte die IDE neu. Manchmal hilft es, dem Board 1–2 Minuten Zeit zu geben.
⚠️ Upload bricht mitten drin ab: Meist schwaches WLAN. Näher an den Router oder externe Antenne verwenden. Der Abbruch ist dank Zwei-Partitionen-Prinzip ungefährlich – die alte Firmware läuft weiter.
⚠️ \"Sketch too big\" beim Kompilieren: OTA braucht zwei App-Partitionen, dein Sketch muss in eine davon passen. Wähle unter Werkzeuge → Partition Scheme z. B. \"Minimal SPIFFS (large APPS with OTA)\".
⚠️ Board reagiert nach OTA-Update nicht mehr auf OTA: Der neue Sketch enthält kein ArduinoOTA.handle() mehr – die häufigste OTA-Falle überhaupt. Jetzt hilft nur noch das USB-Kabel; danach den OTA-Block wieder fest in deine Sketch-Vorlage übernehmen.
⚠️ Update läuft, aber alte Version startet: Beim Web-Updater fehlt vermutlich Update.end(true) oder die .bin-Datei ist für ein anderes Board kompiliert. Boardtyp in der IDE prüfen und neu exportieren.
🚀 Boards mit OTA-Superkraft
Alle diese Boards aus dem Shop lassen sich kabellos aktualisieren:
- ESP32 Entwicklungsboard (USB-C) – der Allrounder für jedes OTA-Projekt
- ESP32-C3 Mini – winzig, sparsam und voll OTA-fähig
- ESP32-C6 Dev Kit – mit WiFi 6 fürs moderne Smart Home
- Wemos D1 Mini (ESP8266) – OTA auch auf dem Budget-Board
- ESP32 Acryl-Gehäuse – einbauen, zuschrauben, trotzdem updaten
Fazit
OTA-Updates gehören zu den Features, die man nie wieder hergibt, wenn man sie einmal genutzt hat. Du hast gelernt, wie das Zwei-Partitionen-Prinzip abgebrochene Updates ungefährlich macht, hast ArduinoOTA in der Arduino IDE eingerichtet, den OTA-Code sauber in eine nicht-blockierende Anwendung integriert, einen Web-Updater für Browser-Uploads gebaut und alles mit einem Passwort abgesichert.
Die drei Merksätze zum Schluss: Das erste Flashen läuft immer über USB. Jeder OTA-fähige Sketch muss den OTA-Code wieder enthalten – mach ihn zum festen Bestandteil deiner Vorlage. Und ArduinoOTA.handle() braucht einen flüssigen loop() ohne lange delays. Damit kannst du deine Projekte endlich dort einbauen, wo sie hingehören – und nicht dort, wo das USB-Kabel hinreicht. Viel Spaß beim Bauen!