In this guide, you’ll learn how to do over-the-air (OTA) updates to your ESP8266 NodeMCU boards using the AsyncElegantOTA library and VS Code with PlatformIO. The AsyncElegant OTA library creates a web server that allows you to update new firmware (a new sketch) to your board without the need to make a serial connection between the ESP8266 and your computer.
Additionally, you can also upload new files to the ESP8266 filesystem (LittleFS). The library is very easy to use, and it’s compatible with the ESPAsyncWebServer library that we often use to build web server projects.
By the end of this tutorial, you’ll be able to easily add OTA capabilities to your web server projects with the ESP8266 to upload new firmware and files to the filesystem wirelessly in the future.
Recommended reading: Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266
We have a similar tutorial for the ESP32 board: ESP32 OTA (Over-the-Air) Updates – AsyncElegantOTA (VS Code + PlatformIO)
Overview
This tutorial covers:
- Add the ElegantOTA feature to your ESP8266 web server
- Upload new firmware via OTA to ESP8266 board
- Upload files to LittleFS via OTA to ESP8266 board
We recommend that you follow all the steps in this tutorial to understand how ElegantOTA works and how you can use it in your projects. To demonstrate how to do this, we’ll upload files to build different web server projects.
OTA (Over-the-Air) Programming
OTA (Over-the-Air) update is the process of loading new firmware to the ESP8266 board using a Wi-Fi connection rather than serial communication. This functionality is extremely useful in case of no physical access to the ESP8266 board.
There are different ways to perform OTA updates. In this tutorial, we’ll cover how to do that using the AsyncElegantOTA library. In our opinion, this is one of the best and easiest ways to perform OTA updates.
The AsyncElegantOTA library creates a web server that you can access on your local network to upload new firmware or files to the filesystem (LittleFS). The files you upload should be in .bin format. We’ll show you later in the tutorial how to get your files to .bin format.
The only disadvantage of OTA programming is that you need to add the code for OTA in every sketch you upload so that you’re able to use OTA in the future. In the case of the AsyncElegantOTA library, it consists of just three lines of code.
AsyncElegantOTA Library
As mentioned previously, there are a bunch of alternatives for OTA programming with the ESP8266 boards. For example, in the Arduino IDE, under the Examples folder, there is the BasicOTA example (that never worked well for us); and many other examples from different libraries.
Most of our web server projects with the ESP8266 use the ESPAsyncWebServer library. So, we wanted a solution that was compatible with that library. The AsyncElegantOTA library is just perfect for what we want:
- It is compatible with the ESPAsyncWebServer library;
- You just need to add three lines of code to add OTA capabilities to your “regular” Async Web Server;
- It allows you to update not only new firmware to the board but also files to the ESP8266 filesystem (LittleFS);
- It provides a beautiful and modern web server interface;
- It works extremely well.
If you like this library and you’ll use it in your projects, consider supporting the developer’s work.
OTA Updates with AsyncElegantOTA Library – Quick Summary
To add OTA capabilities to your projects using the AsyncElegantOTA library, follow these steps:
- Iclude the AsyncElegantOTA, ESPAsyncTCP and ESPAsyncWebServer libraries in the platformio.ini file of your project;
- Include AsyncElegantOTA library at the top of the code: #include <AsyncElegantOTA.h>;
- Add this line AsyncElegantOTA.begin(&server); before server.begin();
- Open your browser and go to http://<IPAddress>/update, where <IPAddress> is your ESP8266 IP address.
Continue reading the tutorial for more detailed steps.
How does OTA Web Updater Work?
- The first sketch should be uploaded via a serial port. This sketch should contain the code to create the OTA Web Updater so that you can upload code later using your browser.
- The OTA Web Updater sketch creates a web server you can access to upload a new sketch via web browser.
- Then, you need to implement OTA routines in every sketch you upload so that you’re able to do the next updates/uploads over-the-air.
- If you upload a code without an OTA routine, you’ll no longer be able to access the web server and upload a new sketch over-the-air.
Install AsyncElegantOTA Library (VS Code + PIO)
In this tutorial, we’ll use VS Code + PIO to program the ESP8266. If you want to use Arduino IDE, follow the next tutorial: ESP8266 NodeMCU OTA (Over-the-Air) Updates – AsyncElegantOTA using Arduino IDE.
To use the AsyncElegantOTA library, include it in your platformio.ini file. You also need to include the ESPAsyncWebServer library. Add these libraries as follows:
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
AsyncElegantOTA ESP8266 Basic Example
Let’s start with the basic example provided by the library. This example creates a simple web server with the ESP8266. The root URL displays some text, and the /update URL displays the interface to update the firmware and the filesystem.
Edit your platformio.ini file so that it looks as follows:
[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
Copy the following code to the main.cpp file.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-vs-code/
This sketch shows a Basic example from the AsyncElegantOTA library: ESP8266_Async_Demo
https://github.com/ayushsharma82/AsyncElegantOTA
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
AsyncWebServer server(80);
void setup(void) {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Hi! I am ESP8266.");
});
AsyncElegantOTA.begin(&server); // Start ElegantOTA
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
}
Insert your network credentials and the code should work straight away:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
How the Code Works
First, include the necessary libraries:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
Insert your network credentials in the following variables so that the ESP8266 can connect to your local network.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Create an AsyncWebServer object on port 80:
AsyncWebServer server(80);
In the setup(), initialize the Serial Monitor:
Serial.begin(115200);
Initialize Wi-Fi:
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Then, handle the client requests. The following lines, send some text Hi! I am ESP8266. when you access the root (/) URL:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Hi! I am ESP8266.");
});
If your web server needs to handle more requests you can add them (we’ll show you in the next example).
Then, add the next line to start ElegantOTA:
AsyncElegantOTA.begin(&server); // Start ElegantOTA
Finally, initialize the server:
server.begin();
Access the Web Server
After uploading code to the board, open the Serial Monitor at a baud rate of 115200. Press the ESP8266 on-board RST button. It should display the ESP IP address as follows (yours may be different):
In your local network, open your browser and type the ESP8266 IP address. You should get access the root (/) web page with some text displayed.
Now, imagine that you want to modify your web server code. To do that via OTA, go to the ESP IP address followed by /update. The following web page should load.
Follow the next sections to learn how to upload new firmware using the AsyncElegantOTA.
Upload New Firmware OTA (Over-the-Air) Updates – ESP8266
Every file that you upload via OTA should be in .bin format. VS Code automatically generates the .bin file for your project when you compile the code. The file is called firmware.bin, and it is saved on your project folder on the following path (or similar depending on the board you’re using):
.pio/build/esp12e/firmware.bin
That’s that .bin file you should upload using the AsyncElegantOTA web page if you want to upload new firmware.
Upload a New Web Server Sketch
Let’s see a practical example. Imagine that after uploading the previous sketch, you want to upload a new one that allows you to control an LED via a web interface like this project. Here are the steps you need to follow:
1. Copy the following code to your main.cpp file. Don’t forget to insert your network credentials.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-vs-code/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
bool ledState = 0;
const int ledPin = 2;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
h2{
font-size: 1.5rem;
font-weight: bold;
color: #143642;
}
.topnav {
overflow: hidden;
background-color: #143642;
}
body {
margin: 0;
}
.content {
padding: 30px;
max-width: 600px;
margin: 0 auto;
}
.card {
background-color: #F8F7F9;;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
padding-top:10px;
padding-bottom:20px;
}
.button {
padding: 15px 50px;
font-size: 24px;
text-align: center;
outline: none;
color: #fff;
background-color: #0f8b8d;
border: none;
border-radius: 5px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
/*.button:hover {background-color: #0f8b8d}*/
.button:active {
background-color: #0f8b8d;
box-shadow: 2 2px #CDCDCD;
transform: translateY(2px);
}
.state {
font-size: 1.5rem;
color:#8c8c8c;
font-weight: bold;
}
</style>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
<div class="topnav">
<h1>ESP WebSocket Server</h1>
</div>
<div class="content">
<div class="card">
<h2>Output - GPIO 2</h2>
<p class="state">state: <span id="state">%STATE%</span></p>
<p><button id="button" class="button">Toggle</button></p>
</div>
</div>
<script>
var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onLoad);
function initWebSocket() {
console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function onOpen(event) {
console.log('Connection opened');
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
function onMessage(event) {
var state;
if (event.data == "1"){
state = "ON";
}
else{
state = "OFF";
}
document.getElementById('state').innerHTML = state;
}
function onLoad(event) {
initWebSocket();
initButton();
}
function initButton() {
document.getElementById('button').addEventListener('click', toggle);
}
function toggle(){
websocket.send('toggle');
}
</script>
</body>
</html>)rawliteral";
void notifyClients() {
ws.textAll(String(ledState));
}
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
if (strcmp((char*)data, "toggle") == 0) {
ledState = !ledState;
notifyClients();
}
}
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
handleWebSocketMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void initWebSocket() {
ws.onEvent(onEvent);
server.addHandler(&ws);
}
String processor(const String& var){
Serial.println(var);
if(var == "STATE"){
if (ledState){
return "ON";
}
else{
return "OFF";
}
}
return String();
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
initWebSocket();
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Start ElegantOTA
AsyncElegantOTA.begin(&server);
// Start server
server.begin();
}
void loop() {
ws.cleanupClients();
digitalWrite(ledPin, ledState);
}
This is the same code used in this project, but it contains the required lines of code to handle ElegantOTA:
#include <AsyncElegantOTA.h>
AsyncElegantOTA.begin(&server);
2. Edit your platformio.ini file as follows:
[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
ayushsharma82/AsyncElegantOTA @ ^2.2.5
2. Save and compile your code – click on the Build icon.
3. Now, in the Explorer tab of VS Code, you can check that you have a firmware.bin file under the project folder on the following path (or similar):
.pio/build/esp12e/firmware.bin
4. Now you just need to upload that file using the ElegantOTA page. Go to your ESP IP address followed by /update. Make sure you have the firmware option selected.
5. Click on Choose File, navigate through the folder in your computer and select the file of your project.
6. Wait until the progress bar reaches 100%.
7. When it’s finished, click on the Back button.
8. Then, you can go to the root (/) URL to access the new web server. This is the page that you should see when you access the ESP IP address on the root (/) URL.
You can click on the button to turn the ESP8266 on-board LED on and off.
Because we’ve also added OTA capabilities to this new web server, we can upload a new sketch in the future if needed. You just need to go to the ESP8266 IP address followed by /update.
Congratulations, you’ve uploaded new code to your ESP8266 via Wi-Fi using ElegantOTA.
Continue reading if you want to learn how to upload files to the ESP8266 filesystem (LittleFS) using AsyncElegantOTA.
Upload Files to Filesystem OTA (Over-the-Air) Updates – ESP8266
In this section you’ll learn to upload files to the ESP8266 filesystem (LittleFS) using AsyncElegantOTA.
Web Server with Files from Filesystem (LittleFS)
Imagine the scenario that you need to upload files to the ESP8266 filesystem, for example, configuration files, HTML, CSS, and JavaScript files to update the web server page or any other file that you may want to save in LittleFS via OTA.
To show you how to do this, we’ll create a new web server that serves files from LittleFS: HTML, CSS, and JavaScript files to build a web page that controls the ESP8266 GPIOs remotely.
Copy the following code to your main.cpp file.
/*
Rui Santos
Complete project details
- Arduino IDE: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-arduino/
- VS Code: https://RandomNerdTutorials.com/esp8266-nodemcu-ota-over-the-air-vs-code/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "LittleFS.h"
#include <Arduino_JSON.h>
#include <AsyncElegantOTA.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// Create a WebSocket object
AsyncWebSocket ws("/ws");
// Set number of outputs
#define NUM_OUTPUTS 4
// Assign each GPIO to an output
int outputGPIOs[NUM_OUTPUTS] = {2, 4, 12, 14};
// Initialize LittleFS
void initLittleFS() {
if (!LittleFS.begin()) {
Serial.println("An error has occurred while mounting LittleFS");
}
Serial.println("LittleFS mounted successfully");
}
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
String getOutputStates(){
JSONVar myArray;
for (int i =0; i<NUM_OUTPUTS; i++){
myArray["gpios"][i]["output"] = String(outputGPIOs[i]);
myArray["gpios"][i]["state"] = String(digitalRead(outputGPIOs[i]));
}
String jsonString = JSON.stringify(myArray);
return jsonString;
}
void notifyClients(String state) {
ws.textAll(state);
}
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
if (strcmp((char*)data, "states") == 0) {
notifyClients(getOutputStates());
}
else{
int gpio = atoi((char*)data);
digitalWrite(gpio, !digitalRead(gpio));
notifyClients(getOutputStates());
}
}
}
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,AwsEventType type,
void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
handleWebSocketMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void initWebSocket() {
ws.onEvent(onEvent);
server.addHandler(&ws);
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
// Set GPIOs as outputs
for (int i =0; i<NUM_OUTPUTS; i++){
pinMode(outputGPIOs[i], OUTPUT);
}
initLittleFS();
initWiFi();
initWebSocket();
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html", "text/html",false);
});
server.serveStatic("/", LittleFS, "/");
// Start ElegantOTA
AsyncElegantOTA.begin(&server);
// Start server
server.begin();
}
void loop() {
ws.cleanupClients();
}
Insert your network credentials in the following variables and save the code.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Edit your platformio.ini file so that it looks as follows:
[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
arduino-libraries/Arduino_JSON @ 0.1.0
ayushsharma82/AsyncElegantOTA @ ^2.2.5
board_build.filesystem = littlefs
Update Firmware
After inserting your network credentials, save and compile the code.
Go to the ESP IP address followed by /update and upload the new firmware as shown previously.
Next, we’ll see how to upload the files to the filesystem.
Update Filesystem
Under the project folder create a folder called data and paste the following HTML, CSS and JavaScript files (click on the links to download the files):
In VS Code, click on the PIO icon and go to Project Tasks > env:esp12e (or similar) >Platform > Build Filesystem Image. This will create a .bin file from the files saved in the data folder.
After building the filesystem image, you should have a littlefs.bin file in the following path (or similar):
.pio/build/esp12e/littlefs.bin
That’s that file that you should upload to update the filesystem.
Go to your ESP IP address followed by /update. Make sure you have the Filesystem option selected and select the littlefs.bin file.
After successfully uploading, click the Back button. And go to the root (/) URL again.
You should get access to the following web page that controls the ESP8266 outputs using Web Socket protocol.
To see the web server working, you can connect 4 LEDs to your ESP8266 on GPIOS: 2, 4, 12, and 14. You should be able to control those outputs from the web server.
If you need to update something on your project, you just need to go to your ESP8266 IP address followed by /update.
Congratulations! You’ve successfully uploaded files to the ESP8266 filesystem using ElegantOTA.
Watch the Video Demonstration
Wrapping Up
In this tutorial you’ve learned how to add OTA capabilities to your Async Web Servers using the AsyncElegantOTA library. This library is super simple to use and allows you to upload new firmware or files to LittleFS effortlessly using a web page. In our opinion, the AsyncElegantOTA library is one of the best options to handle OTA web updates.
We hope you’ve found this tutorial useful.
Learn everything you need to know about building web servers with the ESP8266:
Learn more about the ESP8266 with our resources:
Thanks for reading.
I have a strange problem with this.
The OTA code for the ESP32 using PlatformIO worked fine. (On ESP32 of course)
This OTA code for the EPS8266 using Arduino IDE works fine
But this OTA code for ESP8266 does not for some reason.
It compiles and uploads fine, but when I try to upload through the web server I get “[HTTP ERROR] Bad Request”.
Any ideas please?
Ooops,
Maybe if I selected D1-Mini instead of D1-Mini-Pro as my board…
Silly mistake
That’s my afternoon gone.
Excellent tutorial though.
Thank you for your hard work.
This is fantastic but give us an inch and we will want a mile. That mile being update over the air off the local network. Like at my rental home(s) where most of my 8266 sensors are sensoring away. Happy to use one of my domains to make it all work.
Hi Rui, Great tutorial as always. This will be so useful to me. Only one point I’d like to make….If you right click and ‘save link as’, on each of the 3 files for the filesystem example from here, index.html and script.js save perfectly. style.css saves as style.txt and if you are not aware of that, the page layout doesn’t have any formatting.
Brilliant tutorial though…
Hi Paul.
Thanks for the warning.
The best way to download the files is by clicking the Download all files link.
Regards,
Sara
hai sir I do really understand all your explanation,thank you very well kindly please help me with the same issues, I try to connect esp8266 to node.js but I still don’t know how to figure out
Hi.
At the moment, we don’t have any tutorials about that subject.
Regards,
Sara
HI I’m Varun
I have a doubt please share your solution,
I have upload the and works fine and I’m using in home with 5 NodeMCU’s, Now my problem is i forgot the IP address of each NodeMCU can anyone tell me how to find the IP address without removing the module.
Hi Varun,
perhaps you can check the open connections with the User Interface of your WLAN router.
Regards
Jürgen
Hi Rui!
Great tutorial as always, it helped me a lot!
Help please! During compilation I got an error:
Arduino: 1.8.13 Hourly Build 2020/03/16 09:12 (Mac OS X), Board: “LOLIN(WEMOS) D1 mini Pro, 80 MHz, Flash, Disabled, 16M (14M SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 921600”
In file included from /Users/franz/Documents/Arduino/ESP8266_elegant_OTA/ESP8266_elegant_OTA.ino:19:0:
/Users/franz/Documents/Arduino/libraries/AsyncElegantOTA-master/src/AsyncElegantOTA.h: In lambda function:
/Users/franz/Documents/Arduino/libraries/AsyncElegantOTA-master/src/AsyncElegantOTA.h:103:64: error: ‘U_FS’ was not declared in this scope
int cmd = (filename == “filesystem”) ? U_FS : U_FLASH;
^
Mehrere Bibliotheken wurden für “Hash.h” gefunden
Benutzt: /Users/franz/Library/Arduino15/packages/esp8266/hardware/esp8266/2.5.0/libraries/Hash
Nicht benutzt: /Users/franz/Documents/Arduino/libraries/AsyncElegantOTA-master
exit status 1
Fehler beim Kompilieren für das Board LOLIN(WEMOS) D1 mini Pro.
Dieser Bericht wäre detaillierter, wenn die Option
“Ausführliche Ausgabe während der Kompilierung”
in Datei -> Voreinstellungen aktiviert wäre.
I’ve got a problem. OTA script runs perfect but i need to wait sometimes, even 1 minute to webpage load. How would I increase page loading time?
Hi.
It is better to ask that question on the library GitHub page: https://github.com/ayushsharma82/AsyncElegantOTA/issues
Regards,
Sara
Hi,
I would like to combine this (OTA) with WiFiManager from your book “BuildWeb Servers with ESP32 and ESP8266”.
Works fine, but when I update the project’s filesystem, my configurations are gone, so I have to configure the WiFi again.
Any suggestions how to avoid losing configurations (besides storing everything in EEPROM) ?
TIA
Hi.
You have to save the configurations in EEPROM or in the flash memory using Preferences: https://randomnerdtutorials.com/esp32-save-data-permanently-preferences/
And then, load the settings saved (if there are any) at the beginning of the sketch.
Regards,
Sara
Thanks,
So there is only EEPROM for ESP8266 ? Because preferences.h seems only for ESP32.
Hi.
I’m sorry, I thought you were talking about an ESP32.
Yes, the preferences library is just for the ESP32. You have to use EEPROM.
Regards,
Sara
Greetings Rui and Sara
I did the entire procedure as described and it worked perfectly with the shared code, including the .bin file, but when I did it with other existing code of mine, it didn’t work; certainly for some mistake I made (not sure), so it would be possible to explain what should be added in this code below:
(…)
My thanks
Hi.
What exactly didn’t work?
You didn’t include the lines of code for OTA in your sketch.
REgards,
Sara
Hi Sara, thanks for your reply, so:
Q1) What exactly didn’t work?
Q2) You didn’t include the lines of code for OTA in your sketch.
A1) After I added the necessary lines (the second time), I exported to .bin and entered the ESP IP address, chose the .bin file and loaded the ElegantOTA screen at 100% but it doesn’t show OTA Success and not the word Back.
A2) The first time I didn’t include it because I would like your help to know exactly what I should include in the original code, so I leave here again the code with the lines I think should be included for you to take a look , please:
//*************** Declare included libraries *****************
#include <NTPClient.h>
#include <Time.h>
#include <TimeLib.h>
#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#include <WiFiUdp.h>
//************* Declarar estruturas *****************
//Cria uma estrutura para informações de LED RGB
struct RGB {
byte r, g, b;
};
//Cria uma estrutura para informações de tempo
struct TIME {
byte Hour, Minute;
};
//************* Opções editáveis ***************************
//A cor do ponteiro “12H” para dar referência visual ao topo
const RGB Twelve = { 1, 3, 10 }; //azul fraco
//A cor dos ponteiros 3H, 6H e 9H para dar referência visual
const RGB Quarters = { 1, 3, 10 }; //azul fraco
//A cor das “divisões” 1min,2min,4min,5min,7min,8min,10min e 11min para dar referência visual
const RGB Divisions = { 1, 3, 10 }; //azul fraco
//Todos os outros pixels sem informação
const RGB Background = { 1, 3, 10 }; //azul fraco
//O ponteiro das horas
const RGB Hour = { 255, 0, 0 }; //vermelho
//O ponteiro dos minutos
const RGB Minute = { 0, 128, 0 }; //verde
//O ponteiro dos segundos
const RGB Second = { 0, 0, 255 }; //azul intenso
// Faz o relógio avançar ou retroceder (dependendo do tipo de tira de Led)
const char ClockGoBackwards = 0;
//Define o brilho por tempo para o modo noturno e diurno
const TIME WeekNight = {21, 30}; //escurecimento na semana à noite
const TIME WeekMorning = {6, 15}; //clarear pela manhã na semana
const TIME WeekendNight = {21, 30}; //escurecimento à noite nos fins de semana
const TIME WeekendMorning = {9, 30}; //clarear pela manhã nos fins de semana
const int day_brightness = 255;
const int night_brightness = 16;
//Define o seu fuso horário em horas de diferença do GMT
const int hours_Offset_From_GMT = -3;
//Define os detalhes do seu Wi-Fi para que a placa possa se conectar e obter o tempo da internet
const char *ssid = “Dancopy”; // seu SSID de rede (nome)
const char *password = “dsjjg015085”; // sua senha de rede
AsyncWebServer server(80);
byte SetClock;
// Por padrão ‘time.nist.gov’ é usado.
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Pino do ESP8266 que está conectado aos NeoPixels
// #define PIN 14 // Este é o pino D5
//************* Declara funções do usuário ******************************
void Draw_Clock(time_t t, byte Phase);
int ClockCorrect(int Pixel);
void SetBrightness(time_t t);
void SetClockFromNTP ();
bool IsDst();
//************************** Declara NeoPixel ***************************
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(60, 14, NEO_GRB + NEO_KHZ800);
//************* Função Setup para Wol_Clock ******************************
void setup() {
pixels.begin(); // Isso inicializa a biblioteca NeoPixel
Draw_Clock(0, 1); // Simplesmente desenha um relógio em branco
WiFi.begin(ssid, password); // Tenta conectar-se ao Wi-Fi
Draw_Clock(0, 2); // Desenha o fundo do relógio
while (WiFi.status() != WL_CONNECTED)
delay (500); // continua esperando até que possamos conectar com sucesso ao WiFi
Draw_Clock(0, 3); // Adiciona os indicadores de um quarto de hora
SetClockFromNTP(); // obtém a hora do servidor NTP com correção de fuso horário
AsyncElegantOTA.begin(&server);
server.begin();
}
void SetClockFromNTP ()
{
timeClient.update(); // obtém a hora do servidor NTP
setTime(timeClient.getEpochTime()); // Define a hora do sistema a partir do relógio
if (IsDst())
adjustTime((hours_Offset_From_GMT + 1) * 3600); // desloca a hora do sistema com o fuso horário definido pelo usuário (3600 segundos em uma hora)
else
adjustTime(hours_Offset_From_GMT * 3600); // desloca a hora do sistema com o fuso horário definido pelo usuário (3600 segundos em uma hora)
}
bool IsDst()
{
if (month() < 3 || month() > 10) return false;
if (month() > 3 && month() < 10) return true;
int previousSunday = day() – weekday();
if (month() == 3) return previousSunday >= 24;
if (month() == 10) return previousSunday < 24;
return false; // esta linha nunca vai acontecer
}
//************* Loop de programa principal para Wol_Clock ******************************
void loop() {
AsyncElegantOTA.loop();
time_t t = now(); // Obtém a hora atual
Draw_Clock(t, 4); // Desenha todo o mostrador do relógio com horas, minutos e segundos
if (minute(t) == 0) // no início de cada hora, atualiza a hora no servidor de tempo
{
if (SetClock == 1)
{
SetClockFromNTP(); // obtém a hora do servidor NTP com correção de fuso horário
SetClock = 0;
}
}
else
{
delay(200); // Espera somente 0,1 segundos
SetClock = 1;
}
}
//************* Funções para desenhar o relógio ******************************
void Draw_Clock(time_t t, byte Phase)
{
if (Phase <= 0)
for (int i = 0; i < 60; i++)
pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // para Phase = 0 ou menos, todos os pixels são pretos
if (Phase >= 1)
for (int i = 0; i < 60; i++)
pixels.setPixelColor(i, pixels.Color(Background.r, Background.g, Background.b)); // para Phase = 1 ou mais, desenhe os minutos com a cor de fundo
if (Phase >= 2)
for (int i = 0; i < 60; i = i + 5)
pixels.setPixelColor(i, pixels.Color(Divisions.r, Divisions.g, Divisions.b)); // para Phase = 2 ou mais, desenhe divisões de 5 minutos
if (Phase >= 3) {
for (int i = 0; i < 60; i = i + 15)
pixels.setPixelColor(ClockCorrect(i), pixels.Color(Quarters.r, Quarters.g, Quarters.b)); // para Phase = 3 ou mais, desenhe divisões de 15 minutos
pixels.setPixelColor(ClockCorrect(0), pixels.Color(Twelve.r, Twelve.g, Twelve.b)); // para Phase = 3 e acima, desenhe o indicador de 12 horas
}
if (Phase >= 4) {
pixels.setPixelColor(ClockCorrect(second(t)), pixels.Color(Second.r, Second.g, Second.b)); // desenhe o ponteiro dos segundos primeiro
if (second() % 2)
pixels.setPixelColor(ClockCorrect(minute(t)), pixels.Color(Minute.r, Minute.g, Minute.b)); // para ajudar na identificação, o ponteiro dos minutos pisca entre a intensidade normal e meia intensidade
else
pixels.setPixelColor(ClockCorrect(minute(t)), pixels.Color(Minute.r, Minute.g, Minute.b)); // ponteiro dos minutos de menor intensidade
pixels.setPixelColor(ClockCorrect(((hour(t) % 12) * 5)),pixels.Color(Hour.r, Hour.g, Hour.b)); // desenhe o ponteiro das horas por último
}
SetBrightness(t); // Define o brilho do relógio de acordo com a hora
pixels.show(); // mostra todos os pixels
}
//************* Função para definir o brilho do relógio ******************************
void SetBrightness(time_t t)
{
int NowHour = hour(t);
int NowMinute = minute(t);
if ((weekday() >= 2) && (weekday() <= 6))
if ((NowHour > WeekNight.Hour) || ((NowHour == WeekNight.Hour) && (NowMinute >= WeekNight.Minute)) || ((NowHour == WeekMorning.Hour) && (NowMinute <= WeekMorning.Minute)) || (NowHour < WeekMorning.Hour))
pixels.setBrightness(night_brightness);
else
pixels.setBrightness(day_brightness);
else if ((NowHour > WeekendNight.Hour) || ((NowHour == WeekendNight.Hour) && (NowMinute >= WeekendNight.Minute)) || ((NowHour == WeekendMorning.Hour) && (NowMinute <= WeekendMorning.Minute)) || (NowHour < WeekendMorning.Hour))
pixels.setBrightness(night_brightness);
else
pixels.setBrightness(day_brightness);
}
//************* Testa a função de inverção da ordem dos pixels ***************
int ClockCorrect(int Pixel)
{
if (ClockGoBackwards == 1)
return ((60 – Pixel + 30) % 60);
else
return (Pixel);
}
// Thank you very much
Olá Rui e Sara
Depois de fazer todo o procedimento, quando chega na tela ElegantOTA, avança até 100% mas, não mostra OTA Success e nem Back. Alguma dica? Obrigado
Hi.
I’m not sure what might be wrong.
I think it is better to post an issue on the Library’s Github page: https://github.com/ayushsharma82/AsyncElegantOTA/issues
Regards,
Sara
Hi Sara, hi Rui,
thank you for that tutorial! It worked fine for me exactly as described. However compiling the following message shows up:
In file included from src\main.cpp:10:
.pio\libdeps\d1\AsyncElegantOTA\src/AsyncElegantOTA.h:4:2: warning: #warning AsyncElegantOTA.loop(); is deprecated, please remove it from loop() if defined. This function will be removed in a future release. [-Wcpp]
Ignoring the warnig I’m able to upload new code successfull using OTA. Do you know of a replacement for future use if AsyncElegantOTA will be no longer suported?
Thanks so much
Hi.
You just need to remove the following line from the loop() and everything will be fine:
AsyncElegantOTA.loop();
We’ll update the tutorial soon.
Regards,
Sara
Hi Sara,
thank you for the fast reply. Following your suggestion I’ved removed the lines:
void loop(void) {
//AsyncElegantOTA.loop();
}
but still got the warnings:
ed, please remove it from loop() if defined. This function will be removed in a future release. [-Wcpp]
4 | #warning AsyncElegantOTA.loop(); is deprecated, please remove it from loop() if defined. This function will be removed in a future release.
#warning AsyncElegantOTA.loop(); is deprecated, please remove it from loop() if defined. This function will be removed in a future release. [-Wcpp]
How to proceed now?
Thank you
Hi.
You don’t need to worry about that message. It is just a warning note.
The code should compile and upload just fine.
Regards,
Sara
I combined two working examples, WiFiManager and AsyncElegantOTA, producing one app that panic’s the core. Is there a combability issue or my coding. Two great features should play well together.
(…)
Hi.
I also couldn’t make them work together…
Regards,
Sara
same happens to me!
Any change to fix it? Let the community know how please.
regards
Hi.
We’ve built our own WiFi Manager from scratch using the ESPASyncWebServer library, so it should be compatible with ElegantOTA. It’s not very fancy, but it works.
That project will be published next Thursday.
Regards.
Sara
Thanks, I’m looking forward to trying it.
Thanks, I’m looking forward to trying it.
I assume your new WiFi Manager will work with ESPAsyncWebServer and AsyncElegantOTA. This what I need for a base template project for starting new projects.
Hi.
Yes, I think it should work, but I haven’t tested it in that scenario.
Regards,
Sara
Sara/Rui,
I made a bad assumption that the WiFiManager or another library was causing the panic. I created a new PlatformIO project, including AsyncElegantOTA, me-no-dev/ESPAsyncWebServer, me-no-dev/ESPAsyncTCP, and your example in this tutorial and get the same panic when the .bin completes uploading.
Hi again.
Taking that into account, it seems there must be some issue with your base code.
Regards,
Sara
Hi Sara,
I just purchased a new Dell laptop and installed VSCode/PlatformIO, creating a new project, added the three libraries and the provided sample code. I get the same panic.
Regards,
Mark
Maybe You can active only one. In my project when ESP starts I can launch ElegantOTA by switching button. And then I can only update flash. After reboot ESP launch with normal settings, and then Elegant OTA is not activated.
For the littlefs example to work, do I need to create the partition on the ESP32 first before this example can run properly? Is the process missing from the code examples above?
At the moment I get:-
.pio\libdeps\esp32dev\LittleFS_esp32\src\lfs.c:1076:error: Corrupted dir pair at {0x0, 0x1}
E (34) esp_littlefs: mount failed, (-84)
E (34) esp_littlefs: Failed to initialize LittleFS
[E][LittleFS.cpp:90] begin(): Mounting LITTLEFS failed! Error: -1
Hi.
This example is for ESP8266, not for ESP32.
For the ESP32, check this tutorial instead: https://randomnerdtutorials.com/esp32-ota-over-the-air-vs-code/
Regards,
Sara
Sara/Rui,
read
Thank you for this tutorial. I need to read the instructions more carefully and realize that reading and reading again will help me keep from getting frustrated. I had a hard time compiling the program at first but after rereading the instructions it was clear that some of your instructions were a preview of more detailed instructions later on.
Hi Rui/Sara. I have been working for a few days trying to get OTA to work on the arduino IDE with some success. In searching for solutions to my problems (mainly that the port is dropped randomly) it was pointed out that PlatformIO worked much better than the IDE; which brought me here. However, when I followed the instructions here, before trying to upload I ran a check compile and got the error:
UnknownPackageError: Could not find the package with ‘ayushsharma82/AsyncElegantOTA @ ^2.2.5’ requirements for your system ‘windows_amd64’
If I look for the library in PIO, it’s not there, so I don’t know where to get it. Can you steer me in the right direction? Thanks
Guys, I finally found the updated ElegantOTA library. Through much searching I found the one listed in this tutorial is deprecated. The author points to a web page that gives a similar identification of ayushsharma82/ElegantOTA@^3.1.6, but when I put that in the ini file, platformio reports parsing errors, and won’t allow it. I then found that it is in the PIO repository listed under ElegantOTA. Installing from there places the proper ID in the ini file. But the problems don’t end there. There are then several errors generated one refering to a line in the AsyncTCP library they are as follows:
1. cannot convert ‘AsyncWebServer‘ to ‘ESP8266WebServer‘ {aka ‘esp8266webserver::ESP8266WebServerTemplate*’}
2. argument of type “AsyncWebServer *” is incompatible with parameter of type “ESP8266WebServer *” (aka “esp8266webserver::ESP8266WebServerTemplate *”)
4. #error For RASPBERRY_PI_PICO_W board using CYW43439 WiFi only.
I’m not sure where to go with all this, and with my limited experience, I’ve never seen PIO generate errors from libraries before. Any Help greatly appreciated.
Hey Guys, Obviously in that last post there was much going on that I have no idea was occuring. For one thing when I installed the ElegantOTA library (I didn’t notice until I was shutting down) that 3 different Libraries were added for ESPAsyncTCP. So I scrapped it all and started over. It looks much better, however I still have one error in the main.ccp:
argument of type “AsyncWebServer *” is incompatible with parameter of type “ESP8266WebServer *” (aka “esp8266webserver::ESP8266WebServerTemplate *”)
That error has been persistant. Any Clues?