OTA con LED parpadeando en el pin 13
#include <WiFi.h> #include <WebServer.h> #include <Update.h> // Config WiFi const char* ssid = "XXXXXXXX"; const char* password = "XXXXXXXX"; #define RELAY_PIN 13 // usa cualquier pin digital disponible // IP fija (opcional) IPAddress ip(192, 168, 1, 112); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); IPAddress dns(8, 8, 8, 8); WebServer server(80); // HTML para la página OTA const char* otaForm = R"rawliteral( <!DOCTYPE html> <html> <head> <title>ESP32 OTA Update</title> <meta charset="utf-8"> <style> body { font-family: sans-serif; background-color: #f4f4f4; padding: 30px; } form { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px #ccc; } input[type="submit"] { padding: 10px 20px; } </style> </head> <body> <h2>ESP32 OTA Firmware Update</h2> <form method="POST" action="/update" enctype="multipart/form-data"> <input type="file" name="update"> <input type="submit" value="Subir firmware"> </form> </body> </html> )rawliteral"; void handleRoot() { server.send(200, "text/html", "<h1>ESP32 OTA disponible en <a href='/update'>/update</a></h1>"); } void handleUpdateForm() { server.sendHeader("Connection", "close"); server.send(200, "text/html", otaForm); } void handleUpdateUpload() { HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("\nIniciando actualización: %s\n", upload.filename.c_str()); if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { Update.printError(Serial); } } else if (upload.status == UPLOAD_FILE_WRITE) { if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { Update.printError(Serial); } Serial.print("."); } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) { Serial.printf("\nActualización completa: %u bytes\n", upload.totalSize); } else { Update.printError(Serial); } } yield(); } void handleUpdateFinished() { if (Update.hasError()) { server.send(200, "text/html", "<h1>❌ Fallo en la actualización</h1><p>Revisa la consola serie para más detalles.</p>"); } else { server.send(200, "text/html", "<h1>✅ Actualización exitosa</h1><p>Reiniciando en 5 segundos...</p>"); server.client().stop(); // cerrar conexión limpiamente delay(5000); ESP.restart(); } } void setup() { pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, LOW); // asegúrate de que esté apagado al inicio Serial.begin(115200); delay(1000); // WiFi WiFi.config(ip, gateway, subnet, dns); WiFi.begin(ssid, password); Serial.print("Conectando a WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi conectado. IP: "); Serial.println(WiFi.localIP()); // Rutas web server.on("/", handleRoot); server.on("/update", HTTP_GET, handleUpdateForm); server.on("/update", HTTP_POST, handleUpdateFinished, handleUpdateUpload); server.begin(); Serial.println("Servidor web OTA iniciado"); } void loop() { server.handleClient(); Serial.println("Encendiendo Led"); digitalWrite(RELAY_PIN, HIGH); // activa el relé delay(5000); // bomba encendida 5 segundos Serial.println("Apagando Led"); digitalWrite(RELAY_PIN, LOW); // desactiva el relé delay(5000); // bomba apagada 5 segundos }
#include <WiFi.h> #include <WebServer.h> #include <Update.h> // =================== HTMLS =================== const char* mainPage = R"rawliteral( <!DOCTYPE html> <html> <head> <title>Control ESP32</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { font-family: sans-serif; background-color: #f4f4f4; padding: 30px; max-width: 600px; margin: 0 auto; } .card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px #ccc; margin-bottom: 20px; } .btn { padding: 10px 20px; border: none; border-radius: 4px; color: white; font-size: 16px; cursor: pointer; transition: background-color 0.3s; } .btn-on { background-color: #4CAF50; } .btn-on:hover { background-color: #45a049; } .btn-off { background-color: #f44336; } .btn-off:hover { background-color: #d32f2f; } .btn-auto { background-color: #2196F3; } .btn-auto:hover { background-color: #0b7dda; } .status { padding: 10px; margin: 10px 0; border-radius: 4px; text-align: center; } .on { background-color: #dff0d8; color: #3c763d; } .off { background-color: #f2dede; color: #a94442; } </style> <script> function toggleLED() { fetch("/toggle").then(() => location.reload()); } function toggleAuto() { fetch("/auto").then(() => location.reload()); } </script> </head> <body> <h1>Control ESP32</h1> <div class="card"> <h2>Control del LED</h2> <div class="status %LED_STATUS%">Estado actual: %LED_STATE%</div> <button class="btn %BTN_ON_CLASS%" onclick="toggleLED()">%BTN_TEXT%</button> <button class="btn btn-auto" onclick="toggleAuto()">%AUTO_TEXT%</button> </div> <div class="card"> <h2>Actualización OTA</h2> <form method="POST" action="/update" enctype="multipart/form-data"> <input type="file" name="update"> <input type="submit" value="Actualizar firmware"> </form> </div> </body> </html> )rawliteral"; const char* successPage = R"rawliteral( <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Actualización exitosa</title> <meta http-equiv="refresh" content="5;url=/" /> </head> <body style="font-family: sans-serif; background-color: #f4f4f4; padding: 30px;"> <div style="background: white; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px #ccc;"> <h1>✅ Actualización exitosa</h1> <p>El ESP32 se reiniciará automáticamente en unos segundos...</p> </div> </body> </html> )rawliteral"; // Configuración WiFi const char* ssid = "XXXXXX"; const char* password = "XXXXXXXX"; // IP estática (opcional) IPAddress ip(192, 168, 1, 112); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); IPAddress dns(8, 8, 8, 8); #define RELAY_PIN 13 WebServer server(80); bool ledState = false; bool autoBlink = true; unsigned long previousMillis = 0; const unsigned long interval = 500; void setup() { Serial.begin(115200); pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, LOW); WiFi.config(ip, gateway, subnet, dns); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) delay(100); Serial.print("Conectado: "); Serial.println(WiFi.localIP()); server.on("/", []() { String html = mainPage; html.replace("%LED_STATE%", ledState ? "ENCENDIDO" : "APAGADO"); html.replace("%LED_STATUS%", ledState ? "on" : "off"); html.replace("%BTN_TEXT%", ledState ? "Apagar" : "Encender"); html.replace("%BTN_ON_CLASS%", ledState ? "btn-off" : "btn-on"); html.replace("%AUTO_TEXT%", autoBlink ? "Auto: ON" : "Auto: OFF"); server.send(200, "text/html; charset=utf-8", html); }); server.on("/toggle", []() { ledState = !ledState; autoBlink = false; digitalWrite(RELAY_PIN, ledState); server.send(200, "text/plain", "OK"); }); server.on("/auto", []() { autoBlink = !autoBlink; server.send(200, "text/plain", "OK"); }); server.on("/update", HTTP_POST, []() { server.sendHeader("Connection", "close"); server.send(200, "text/html; charset=utf-8", successPage); delay(2000); ESP.restart(); }, []() { HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("OTA iniciada: %s\n", upload.filename.c_str()); if (!Update.begin(UPDATE_SIZE_UNKNOWN)) Update.printError(Serial); } else if (upload.status == UPLOAD_FILE_WRITE) { if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) Update.printError(Serial); } else if (upload.status == UPLOAD_FILE_END) { if (Update.end(true)) Serial.println("OTA finalizada correctamente"); else Update.printError(Serial); } }); server.begin(); } void loop() { server.handleClient(); if (autoBlink) { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; ledState = !ledState; digitalWrite(RELAY_PIN, ledState); } } }