This tutorial shows how to build a web server that serves HTML and CSS files stored on the ESP8266 NodeMCU filesystem (SPIFFS) using Arduino IDE. Instead of having to write the HTML and CSS text into the Arduino sketch, we’ll create separate HTML and CSS files.
The web server we’ll build shows how to control the ESP8266 outputs and how to display sensor readings. As an example, we’ll control an LED and display sensor readings from a BME280 sensor.
You can use the concepts learned in this tutorial to control any output or display sensor readings from other sensors.
Recommended reading: ESP32 Web Server using SPIFFS
Project Overview
Before going straight to the project, it’s important to outline what our web server will do, so that it’s easier to understand.
- The web server controls an LED connected to the ESP8266 GPIO 2. This is the ESP8266 on-board LED. You can control any other GPIO;
- The web server page shows two buttons: ON and OFF – to turn GPIO 2 on and off;
- The web server page also shows the current GPIO state;
- You’ll also use a BME280 sensor to display sensor readings (temperature, humidity, and pressure).
The following figure shows a simplified diagram to demonstrate how everything works.
Prerequisites
Before proceeding with this project, make sure you check all the following prerequisites.
1. Install ESP8266 Board in Arduino IDE
We’ll program the ESP8266 using Arduino IDE, so you must have the ESP8266 add-on installed. Follow the next tutorial to install it:
2. Filesystem Uploader Plugin
To upload files to the ESP8266 SPI Flash Filesystem (SPIFFS), we’ll use the Filesystem Uploader Plugin. Install the plugin in your Arduino IDE:
3. Installing Libraries
One of the easiest ways to build a web server using files from the filesystem is using the ESPAsyncWebServer library.
Installing the ESPAsyncWebServer library
This library is not available to download through the Arduino IDE libraries manager. So, you need to follow the next steps to install the library:
- Click here to download the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder
- Unzip the .zip folder and you should get ESPAsyncWebServer-master folder
- Rename your folder from
ESPAsyncWebServer-masterto ESPAsyncWebServer - Move the ESPAsyncWebServer folder to your Arduino IDE installation libraries folder
Alternatively, you can go to Sketch > Include Library > .zip Library and select the previously downloaded library.
Installing the ESPAsyncTCP
The ESPAsyncWebServer library also needs the ESPAsyncTCP library to operate properly. Follow the next steps to install the ESPAsyncTCP library:
- Click here to download the ESPAsyncTCP library. You should have a .zip folder in your Downloads folder
- Unzip the .zip folder and you should get ESPAsyncTCP-master folder
- Rename your folder from
ESPAsyncTCP-masterto ESPAsyncTCP - Move the ESPAsyncTCP folder to your Arduino IDE installation libraries folder
- Finally, re-open your Arduino IDE
Alternatively, you can go to Sketch > Include Library > .zip Library and select the previously downloaded library.
Installing BME280 libraries
In this tutorial, we’ll display readings from a BME280 sensor (Guide with ESP8266). You need to install the following libraries:
You can install these libraries through the Arduino IDE Libraries Manager. Go to Sketch > Include Libraries > Manage Libraries. Then, search for the libraries’ name to install them.
Parts Required
To proceed with this project, you need the following parts:
- ESP8266 (read Best ESP8266 development boards)
- BME280 sensor module (Guide for BME280)
- 5 mm LED
- 330 Ohm resistor
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic Diagram
Connect all the components by following the next schematic diagram.
BME280 | ESP8266 |
Vin | 3.3V |
GND | GND |
SCL | GPIO 5 |
SDA | GPIO 4 |
Organizing Your Files
To build the web server you need three different files. The Arduino sketch, the HTML file and the CSS file. The HTML and CSS files should be saved inside a folder called data inside the Arduino sketch folder, as shown below:
Creating the HTML File
Create an index.html file with the following content or download all project files here:
<!DOCTYPE html>
<!--
Rui Santos
Complete project details at https://RandomNerdTutorials.com
-->
<html>
<head>
<title>ESP8266 Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>ESP8266 Web Server</h1>
<p>GPIO state<strong> %STATE%</strong></p>
<p>
<a href="/on"><button class="button">ON</button></a>
<a href="/off"><button class="button button2">OFF</button></a>
</p>
<p>
<span class="sensor-labels">Temperature</span>
<span id="temperature">%TEMPERATURE%</span>
<sup class="units">°C</sup>
</p>
<p>
<span class="sensor-labels">Humidity</span>
<span id="humidity">%HUMIDITY%</span>
<sup class="units">%</sup>
</p>
<p>
<span class="sensor-labels">Pressure</span>
<span id="pressure">%PRESSURE%</span>
<sup class="units">hPa</sup>
</p>
</body>
<script>
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 10000 ) ;
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("pressure").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/pressure", true);
xhttp.send();
}, 10000 ) ;
</script>
</html>
Because we’re using CSS and HTML in different files, we need to reference the CSS file on the HTML text.
<link rel="stylesheet" type="text/css" href="style.css">
The <link> tag tells the HTML file that you’re using an external style sheet to format how the page looks. The rel attribute specifies the nature of the external file, in this case that it is a stylesheet—the CSS file—that will be used to alter the appearance of the page.
The type attribute is set to “text/css” to indicate that you’re using a CSS file for the styles. The href attribute indicates the file location; since both the CSS and HTML files will be in the same folder, you just need to reference the filename: style.css.
In the following line, we write the first heading of our web page. In this case we have “ESP8266 Web Server”. You can change the heading to any text:
<h1>ESP8266 Web Server</h1>
Then, add a paragraph with the text “GPIO state: ” followed by the GPIO state. Because the GPIO state changes accordingly to the state of the GPIO, we can add a placeholder that will then be replaced for whatever value we set on the Arduino sketch.
To add placeholder use % signs. To create a placeholder for the state, you can use %STATE%, for example.
<p>GPIO state<strong> %STATE%</strong></p>
You attribute a value to the STATE placeholder in the Arduino sketch.
Then, create an ON and an OFF buttons. When you click the on button, we redirect the web page to to root followed by /on url. When you click the off button you are redirected to the /off url.
<a href="/on"><button class="button">ON</button></a>
<a href="/off"><button class="button button2">OFF</button></a>
Finally, create three paragraphs to display the temperature, humidity and pressure.
<p>
<span class="sensor-labels">Temperature</span>
<span id="temperature">%TEMPERATURE%</span>
<sup class="units">°C</sup>
</p>
<p>
<span class="sensor-labels">Pressure</span>
<span id="pressure">%PRESSURE%</span>
<sup class="units">hPa</sup>
</p>
<p>
<span class="sensor-labels">Humidity</span>
<span id="humidity">%HUMIDITY%</span>
<sup class="units">%</sup>
</p>
We use the %TEMPERATURE%, %HUMIDITY% and %PRESSURE% placeholders. These will then be replaced by the actual temperature readings in the Arduino sketch.
Automatic Updates
We also add a bit of JavaScript in our HTML file that is responsible for updating the temperature readings without the need to refresh the web page.
The following snipet of code is responsible for the temperature.
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;
To update the temperature, we have a setInterval() function that runs every 10 seconds.
Basically, it makes a request in the /temperature URL to get the latest temperature reading.
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;
When it receives that value, it updates the HTML element with temperature id.
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
In summary, this previous section is responsible for updating the temperature asynchronously. The same process is repeated for the humidity and pressure readings.
Creating the CSS File
Create the style.css file with the following content or download all project files here:
/***
Rui Santos
Complete project details at https://RandomNerdTutorials.com
***/
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
h1 {
color: #0F3376;
padding: 2vh;
}
p {
font-size: 1.5rem;
}
.button {
display: inline-block;
background-color: #008CBA;
border: none;
border-radius: 4px;
color: white;
padding: 16px 40px;
text-decoration: none;
font-size: 30px;
margin: 2px;
cursor: pointer;
}
.button2 {
background-color: #f44336;
}
.units {
font-size: 1.2rem;
}
.sensor-labels {
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}
This is just a basic CSS file to set the font size, style and color of the buttons and align the page. We won’t explain how CSS works. A good place to learn about CSS is the W3Schools website.
ESP8266 Asynchronous Web Server Sketch
Copy the following code to the Arduino IDE or download all project files here. Then, you need to type your network credentials (SSID and password) to connect the ESP8266 to your local network.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com
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 <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set LED GPIO
const int ledPin = 2;
// Stores LED state
String ledState;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
String getTemperature() {
float temperature = bme.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float temperature = 1.8 * bme.readTemperature() + 32;
Serial.println(temperature);
return String(temperature);
}
String getHumidity() {
float humidity = bme.readHumidity();
Serial.println(humidity);
return String(humidity);
}
String getPressure() {
float pressure = bme.readPressure()/ 100.0F;
Serial.println(pressure);
return String(pressure);
}
// Replaces placeholder with LED state value
String processor(const String& var){
Serial.println(var);
if(var == "STATE"){
if(digitalRead(ledPin)){
ledState = "ON";
}
else{
ledState = "OFF";
}
Serial.print(ledState);
return ledState;
}
else if (var == "TEMPERATURE"){
return getTemperature();
}
else if (var == "HUMIDITY"){
return getHumidity();
}
else if (var == "PRESSURE"){
return getPressure();
}
return String();
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
// Initialize the sensor
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
// Initialize SPIFFS
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Route to load style.css file
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/style.css", "text/css");
});
// Route to set GPIO to HIGH
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
// Route to set GPIO to LOW
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, LOW);
request->send(SPIFFS, "/index.html", String(), false, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getTemperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getHumidity().c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getPressure().c_str());
});
// Start server
server.begin();
}
void loop(){
}
How the code works
Continue reading to learn how the code works, or skip to the next section.
First, include the necessary libraries:
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
You need to type your network credentials in the following variables:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Create an instance that refers to the BME280 sensor called bme:
Adafruit_BME280 bme; // I2C
Next, create a variable that refers to GPIO 2 called ledPin, and a String variable to hold the led state: ledState.
const int ledPin = 2;
String ledState;
Create an AsynWebServer object called server that is listening on port 80.
AsyncWebServer server(80);
Get Sensor Readings
We create three functions to return the sensor readings as strings: the getTemperature(), getHumidity() and getPressure() functions.
Here’s how the getTemperature() function looks like (the other functions are similar).
String getTemperature() {
float temperature = bme.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float temperature = 1.8 * bme.readTemperature() + 32;
Serial.println(temperature);
return String(temperature);
}
If you want to display temperature in Fahrenheit degrees, you just need to uncomment the corresponding line in the getTemperature() function:
float temperature = 1.8 * bme.readTemperature() + 32;
To learn more about interfacing the BME280 sensor with the ESP8266, you can read the following tutorial:
processor()
The processor() function attributes a value to the placeholders we’ve created on the HTML file. It accepts as argument the placeholder and should return a String that will replace the placeholder. The processor() function should have the following structure:
String processor(const String& var){
Serial.println(var);
if(var == "STATE"){
if(digitalRead(ledPin)){
ledState = "ON";
}
else{
ledState = "OFF";
}
Serial.print(ledState);
return ledState;
}
else if (var == "TEMPERATURE"){
return getTemperature();
}
else if (var == "HUMIDITY"){
return getHumidity();
}
else if (var == "PRESSURE"){
return getPressure();
}
}
This function first checks if the placeholder is the STATE we’ve created on the HTML file.
if(var == "STATE"){
If it is, then, accordingly to the LED state, we set the ledState variable to either ON or OFF.
if(digitalRead(ledPin)){
ledState = "ON";
}
else{
ledState = "OFF";
}
Finally, we return the ledState variable. This replaces the STATE placeholder with the ledState string value.
return ledState;
If it finds the %TEMPERATURE% placeholder, we return the temperature by calling the getTemperature() function created previously.
else if (var == "TEMPERATURE"){
return getTemperature();
}
The same happens for the %HUMIDITY% and %PRESSURE% placeholders by calling the corresponding functions:
else if (var == "TEMPERATURE"){
return getTemperature();
}
else if (var == "HUMIDITY"){
return getHumidity();
}
else if (var == "PRESSURE"){
return getPressure();
}
setup()
In the setup(), start by initializing the Serial Monitor and setting the GPIO as an output.
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
Initialize the BME280 sensor:
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Initialize SPIFFS:
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
Wi-Fi connection
Connect to Wi-Fi and print the ESP8266 address:
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
Async Web Server
The ESPAsyncWebServer library allows us to configure the routes where the server will be listening for incoming HTTP requests and execute functions when a request is received on that route. For that, use the on method on the server object as follows:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", String(), false, processor);
});
When the server receives a request on the root “/” URL, it will send the index.htmlfile to the client. The last argument of the send() function is the processor, so that we can replace the placeholder with the value we want – in this case the ledState.
Because we’ve referenced the CSS file on the HTML file, the client will make a request for the CSS file. When that happens, the CSS file is sent to the client:
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/style.css","text/css");
});
You also need to define what happens on the /on and /off routes. When a request is made on those routes, the LED is either turned on or off, and the ESP32 serves the HTML file.
server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(),false, processor);
});
server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, LOW);
request->send(SPIFFS, "/index.html", String(),false, processor);
});
In the HTML file, we’ve written a JavaScript code that requests the temperature, humidity and pressure on the /temperature, /humidity, /pressure routes, respectively, every 10 seconds. So, we also need to handle what happens when we receive a request on those routes.
We simply need to send the updated sensor readings. The updated sensor readings are returned by the getTemperature(), getHumidity() and getPressure() functions we’ve created previously.
The readings are plain text, and should be sent as a char, so, we use the c_str() method.
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getTemperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getHumidity().c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", getPressure().c_str());
});
In the end, we use the begin() method on the server object, so that the server starts listening for incoming clients.
server.begin();
Because this is an asynchronous web server, you can define all the requests in the setup(). Then, you can add other code to the loop() while the server is listening for incoming clients.
Uploading Code and Files
Save the Arduino sketch as ESP8266_SPIFFS_Web_Server or download all project files here.
- Go to Sketch > Show Sketch folder, and create a folder called data. Save the HTML and CSS files inside that folder;
- In Tools > Board, select the ESP8266 board you’re using;
- Then, go to Tools > Flash size and select 4M (1M SPIFFS).
Finally, upload the files to your board. Go to Tools > ESP8266 Data Sketch Upload and wait for the files to be uploaded.
Then, press the Arduino IDE upload button to upload the code to the ESP8266.
When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the ESP8266 on-board RST button, and it should print the ESP8266 IP address.
Demonstration
Open a browser and type your ESP8266 IP address. The following web page should load.
Press the ON and OFF buttons to control the ESP8266 on-board LED. You can also visualize the latest sensor readings. The sensor readings are updated automatically without the need to refresh the web page.
Wrapping Up
Using the ESP8266 SPI Flash File System (SPIFFS) is specially useful to store HTML and CSS files to serve to a client – instead of having to write all the code in the Arduino sketch.
We have other related projects that you may like:
- ESP32 Web Server using SPIFFS
- ESP8266 DHT Temperature and Humidity Web Server
- Hack a PIR Motion Sensor with an ESP8266
- ESP8266 Wi-Fi Button – DIY Amazon Dash Button Clone
Learn more about the ESP8266:
- Home Automation using ESP8266
- MicroPython Programming with ESP32 and ESP8266
- Free ESP8266 Projects and Tutorials
Thanks for reading.
Hello Sara,
I just finished building a thermostat to replace my old mercury switch thermostat. In this project I used the ESP8266, DHT22, and BLYNK. I can now control my heat/ac remotely. However I want to replace BLYNK with my own server so I went out yesterday and purchased a set of books (HTML, CSS, JAVASCRIPT, and JQUERY). How fortuitous for me that your project was just posted; it will be very helpful. Thank you. I do have a question; what schematic capture software did you use in this project?
Is there any project, which sends sensor data to my own website and from across the world I can see the sensors data.
Hi.
Yes, you can follow the next tutorials:
https://randomnerdtutorials.com/visualize-esp32-esp8266-sensor-readings-from-anywhere/
https://randomnerdtutorials.com/esp32-esp8266-mysql-database-php/
Regards,
Sara
Hey Sara, it is a really very interesting project, thanks for it. Please I have question for you. I am starting to work with SPIFFS and I assume that as it is a Flash memory when I reset or reboot my NodeMCU, it should keep the information in the file that I have created, but when I reset the module and I send it to read what is in the file, it returns empty. I send you my code, thanks a lot !
#include “FS.h”
#include <ArduinoJson.hpp>
#include <ArduinoJson.h>
String json;
void SerializeObject()
{
StaticJsonDocument<300> doc;
doc["SSID"] = "";
doc["PASSWORD"] = "";
doc["CANT_REJILLAS"] = 3;
doc["CANT_SENSORES_TEMP"] = 5;
serializeJson(doc, json);
Serial.println(json);
}
void DeserializeObject(String desjson)
{
StaticJsonDocument<300> doc;
DeserializationError error = deserializeJson(doc, desjson);
if (error) { return; }
const char* ssid = doc["SSID"];
const char* password = doc["PASSWORD"];
int cant_rejillas = doc["CANT_REJILLAS"];
int cant_temp = doc["CANT_SENSORES_TEMP"];
Serial.println(ssid);
Serial.println(password);
Serial.println(cant_rejillas);
Serial.println(cant_temp);
}
/**
* escribe contenido en un archivo
* string state – contenido a escribir en el archivo
* string path – archivo que se va a escribir
*/
void writeFile(String state, String path) {
File rFile = SPIFFS.open(path,”w+”);
if(!rFile){
Serial.println(“Error!”);
} else {
rFile.println(state);
Serial.println(state);
}
rFile.close();
}
/**
* el contenido de un archivo
* param cadena path – archivo que se va a leer
* return string – contenido leído del archivo
*/
String readFile(String path) {
File rFile = SPIFFS.open(path,”r”);
if (!rFile) {
Serial.println(“Error !”);
}
String content = rFile.readStringUntil(‘\r’);
Serial.print(“reading state: “);
Serial.println(content);
rFile.close();
return content;
}
/**
* @desc inicializa el sistema de archivos
*/
void openFS(void){
if(!SPIFFS.begin()){
Serial.println(“\nError”);
} else {
Serial.println(“\nSuccess!”);
}
}
void setup() {
Serial.begin(115200);
SPIFFS.begin();
openFS();
//SerializeObject();
Serial.println(” Reading previously saved”);
String state = readFile(“/config2.txt”);
Serial.println(state);
writeFile(json, “/config2.txt”);
String state2 = readFile(“/config2.txt”);
DeserializeObject(state2);
}
void loop()
{
}
Hi.
Yes, that’s right.
It keeps the files saved in SPIFFS even after resetting.
I can’t find out what might be wrong.
Do you get any errors on the write/read functions?
Regards,
Sara
You just need to create api at your sent to accept the GET or POST request
Great article! I’m curious about the limitations, though. How much space is available for HTML and CSS files? Enough for the web pages to be heavily graphical? Can CSS media queries be used to make the site responsive? Can php be installed so that exec() can leveraged to execute programs on the ESP8266 via a button or link on a webpage?
For the ESP8266, in Arduino IDE, you can select a SPIFFS size up to 3M.
Regards,
Sara
Fritzing!
Hey Leon,
Thanks, that’s what I thought but I have a follow up question; do I include the exclamation mark (!) on the end of Fritzing when I search for it on the WEB. Just kidding have a nice day!
Great posting. It meets all of the requirements for a project I am working on except one. I won’t be where there is internet so I need the 8266 to be configured as an access point. It only needs to serve one client (a smartphone). Could you tell me how to do that? I have tried in the past with other projects, to no avail. It is no problem to set up the access point, but for some reason the asynchronous communication fails. Thanks!
Hi William.
Something stopped working with some libraries updates.
We’ve modified and updated the code and now you should have no problems setting an access point.
You can follow this project for setting the access point: https://randomnerdtutorials.com/esp32-access-point-ap-web-server/
This is for ESP32, but works for ESP8266.
Regards,
Sara
This tutorial is almost perfectly suited to my project.
I need to read a value from my solar water heating system, apply human intelligence from the weather forecast and return a command to initiate a burn cycle on the boiler if the sun is not going to shine much later in the day.
As a real beginner with software, I’d been prepare to achieve my goal by hacking various parts from other tutorials but not looking forward to it. This looks perfect for me to tweak to my requirement.
Hi,
I do not have this. I use IDE 1.8.3. Does this come in a later release or do I have to install this tool?
” Go to Tools > ESP8266 Data Sketch Upload
Open IDE and go to File->preferences to find out where your sketches are saved to. In that directory create the following folders/subfolders that do not exist:
sketch_directory/tools/ESP8266FS/tool
Extract the tar file to some junk directory and copy the esp8266fs.jar into the tool directory.
Close and re-open IDE; look carefully under IDE/tools tab; ESP8266 Sketch Data Upload to be there.
Hi.
You need to install it.
See here: https://randomnerdtutorials.com/install-esp8266-filesystem-uploader-arduino-ide/
Regards,
Sara
I found Adafruit BME280 Library under Sketch -> Include Llibrary -> Manage Libraries… but I could not find the Adafruit Sensor library. I do see that in GitHub. Can you tell me how to load it from there? Thanks.
Hi William.
Search for “adafruit unified sensor” and it should be the last in the list
https://i2.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/04/adafruit_unified_sensor_library.png
Regards,
Sara
Hello Markus,
Look at your file preferences in IDE(FILE->Preferences) to see which directory your sketches are saved to.
Go to that directory and see if it contains a “tools” directory.
If it doesn’t then create a new directory path (sketchbook directory /tools /ESP8266FS /tool) or it does then add the last two folders.
Unpack the tar file in some junk folder and then copy and paste the esp8266fs.jar it into the tool folder you just created.
You should see the new option when you reopen IDE; look carefully.
Regards,
Roger
Markus,
You need to install the ESP files separately from the Arduino IDE. You do so by editing a line in preferences, which adds a selection to Boards Manager in the IDE. You then install the boards from there. Look around a bit and you’ll find the complete instructions on RNT…(a GREAT resource).
Dave
Thanks for the post! using this setup do you know how I could get the contents of an html text input form from the web page to a variable?
Hi Jeff.
We’ve recently created a tutorial about that.
https://randomnerdtutorials.com/esp32-esp8266-input-data-html-form/
I hope this helps.
Regards,
Sara
Hi there,
I installed this on one of my WEMOS D1 mini Pro V1.0.0 ESP8266F.X based board. I set the board type to NodeMCU 1.0 (ESP12E Module), and the Flash Size to 1M SPIFFS.
Everything loaded and ran fine except that the functions of the webpage ‘Buttons’ (the ON button and the OFF button) were ‘Opposite’.
When I clicked the ON, the LED went OFF, and the URL changed to I.P./off
When I clicked the OFF, the LED went ON, and the URL changed to I.P./on
I changed a few things in the IDE Sketch and got it to work as it should – but it doesn’t make sense why it works as it should now – any ideas?
Here are the parts of the Sketch that I changed. You will see my commented out parts with my initials next to the line (//jhh).
First part of change:
if(var == “STATE”){
if(digitalRead(ledPin)){
ledState = “OFF”;
// ledState = “ON”; //jhh
}
else{
ledState = “ON”;
// ledState = “OFF”; //jhh
}
Second part of change:
// Route to set GPIO to HIGH
server.on(“/on”, HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, LOW);
//digitalWrite(ledPin, HIGH); //jhh
request->send(SPIFFS, “/index.html”, String(), false, processor);
});
// Route to set GPIO to LOW
server.on(“/off”, HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);
//digitalWrite(ledPin, LOW); //jhh
request->send(SPIFFS, “/index.html”, String(), false, processor);
});
I’m not sure why, but other comments I’ve posted on your projects have never been answered, they return a message saying they are being reviewed by the moderator. Who knows, maybe this one will get a response as it could affect others. Thanks Johnhh.
Hi John.
We receive lots of comments every day. It’s very difficult to review and answer every comment we receive. I’m sorry for that.
I’ve just tested this code again and it is working properly.
Did you connect an LED to your ESP8266 or are you just controlling the on-board LED?
The on-board LED behaves the other way around. When you send a LOW signal it turns on, when you send a HIGH signal it turns off.
Or are you using another pin?
Regards,
Sara
Thanks for getting back to me.
Yes, I’m using the on-board LED, so if what you say is correct, then that makes sense. Does this only happen with the WEMOS board? My other boards behave normally.
Another question I had was about your ESP32-Camera Motion picture capture, and was about how to improve the ‘White Balance’ on the captured picture. Any suggestions?
Many thanks Johnhh
the onboard LED on the ESP8266-12E as found on the wemos has reversed logic as it is attached between Vcc and GPIO2.
If you would add an external LED to gpio2 (through a series resistor) it should just work fine
apologies, I see Sara already said that
why delay is not working in this part
server.on(“/off”, HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
request->send(SPIFFS, “/index.html”, String(), false, processor);
});
How to blink led using server.on method.
Delay function is not working.
Please help
The web page is not automatically refreshed but the datas are !
Who can this be ?
Hi.
What do you mean?
Please reply my question
I want to blink led using this code but delay function is not working.
How to solve this problem ?
Hi,
Im trying to work my way through this code and have a question
In the processor() there is a variable “var” but i cannot see how/where it gets assigned a value.
Can someone point me in the right direction please
I’m very much a beginner lol.
Bob
Hi.
The var corresponds to any placeholders that you may have in your HTML text.
That is automatically handled by the AyncWebServer library.
Regards,
Sara
Thank You Sara
Much appreciated
Bob
how to blink led using this project.
I am trying but delay function is not working
please help
Hi
I tried to replace your sensor with a DHT22
Unfortunatly I’m not able to read temperature and humidity !
I’m getting ‘nan’
Do you have experience with this sensor and SPIFFS ?
I can’t understand why
Thanks for your answer
JCB
Hi.
You can follow the code in this tutorial, but instead of having the HTML page on the Arduino program, you save it to SPIFFS.
https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/
Also, it may help taking a look at our torubleshooting guide: https://randomnerdtutorials.com/solved-dht11-dht22-failed-to-read-from-dht-sensor/
I hope this helps.
Regards,
Sara
Thank you very much for your help!
It’s a pleasure to read your projects, it’s very interesting! Please continue!
JCB
Kindly also reply me
I ask multiple questions many times but no reply from your side!!
Hi Usman.
I’m sorry about that.
We receive lots of comments every day, it is difficult to read and answer all comments.
So, you want the LED to start blinking when you send an ON command?
The best approach is to create a flag variable that will change accordingly to the command received.
Then, in the loop() you decide what happens when that variable changes from one state to another.
It is recommended to blink the LED without delay (using timers instead).
Let me know if you need further help.
Regards,
Sara
ESP8266 NodeMCU can be used as Web server with html webpage. Many times you may want to add images in web page. This can be achieved with help of SPIFFS (SPI Flash File System) or use of dataURL for small size images. Lets see step by step to upload image in web page.
Hello, we have an in-depth guide that shows “How to Display Images in ESP32 and ESP8266 Web Server”: https://randomnerdtutorials.com/display-images-esp32-esp8266-web-server/
I hope that helps.
Regards,
Rui
Hi Rui, Hi Sara,
as usual another good project and tutorial!!!
What should I do to implement in this project the part referred to WiFiManager with ESP8266 – Autoconnect?
In this way it will be a complete stand alone gadget to be used everywhere.
Hi Attilio.
The code needs to include the following libraries for the WiFiManager:
#include
#include
#include
You also need to create a WiFiManager object:
WiFiManager wifiManager;
And run the autoConnect() method:
wifiManager.autoConnect(“AutoConnectAP”);
That’s it! By adding these new lines of code to your ESP8266 projects, you’re able to configure Wi-Fi credentials using the WiFiManager.
Take a look at the tutorial: https://randomnerdtutorials.com/wifimanager-with-esp8266-autoconnect-custom-parameter-and-manage-your-ssid-and-password/
P.S. I haven’t tried this. I don’t know if this is compatible with this web server project.
If you try it, then let me know.
Regards,
Sara
Hi Sara and thanks for your reply. You wrote three times #include but with no library.
Which library I have to include?
I’m sorry.
The comments plugin deleted the libraries.
These are the libraries:
ESP8266WiFi.h
DNSServer.h
ESP8266WebServer.h
WiFiManager.h
Regards,
Sara
I have tried several times to get this app to install and compile, but no luck. I get dozens of link errors, all referencing missing functions from std:: that are most/all referenced by ESPAsyncWebServer. I am using Arduino IDE 1.8.9. I have no problems with other ESP8266 examples.
Is there some version problem here? Or a build command missing?
Regards,
Ray L.
BTW – The ESPAsyncWebServer and ESPAsyncTCP libraries and the entire ESP8266_SPIFFS installs were all downloaded using the links in the article.
Regards,
Ray L.
Ok.
I don’t know why that happens?
Did you experiment other examples with the AsyncTCP library?
What are the erros that you’re getting?
Regards
Sara
Hi Ray.
Besides the ESPAsyncWebServer library, you also need to install the ESPAsyncTCP: https://github.com/me-no-dev/ESPAsyncTCP
Do you have both libraries installed?
Regards,
Sara
Just got it sorted out. For some reason the 2.5.2 ESP package did not install correctly, so it was trying to build using an old 2.4.2rc2 package. I un-installed that, re-installed 2.5.2 (took THREE tries to get it to install!), and it now builds with no errors.
Thanks!
Regards,
Ray L.
Apparently the Async webserver has some problems with the WiFiManagar if that is used at the same time (so not in this project).
Apparently there is an Async wifimanager as well that should work: https://github.com/alanswx/ESPAsyncWiFiManager
Hi.
Thank you for sharing.
We need to try it out.
Regards,
Sara
Hi, how to convert xhttp server in a websockets server?
How I can add wifimanager for config my own wifi parameters?
Please, Help me!!!
Hi Manuel.
For wifimanager, you can follow: https://randomnerdtutorials.com/wifimanager-with-esp8266-autoconnect-custom-parameter-and-manage-your-ssid-and-password/
We don’t have any tutorial about the other subject.
Regards,
Sara
Hi Rui&Sara, I have to say I love your projects. But this one I’m having some issues with. I received 3 BME 280 sensors today, and wired them up to my ESP8266 as shown. Uploaded the code and files to spiff, but what happened was that the sketch reached the point to initialize the sensor, then printed out “could not find a valid BME 280 sensor, check wiring”. And repeated continuously. Wiring was ok, I then ran a I2C scanner sketch and it reported an address of 0x076. After some searching, I found Adafruit’s BME 280 test sketch. It also could not verify a proper BME 280, but did report a sensor ID of ox58, indicating that is represents a BMP 280. That being said I’ve read on some blogs that the library should work on either the BME OR BMP280 sensors. I would really appreciate some wisdom on this one. Thanks
As an update, and for anyone also having issues like the above, I’ve found a solution to this specific issue here:
http://www.esp8266learning.com/esp8266-and-bme280-temperature-sensor-example.php?unapproved=21462&moderation-hash=577bedee5fd90859612658116e09f5a5#comment-21462
However I now find that 3 out of 3 sensors do not read properly. One reads ~10 deg F high on temperature, 0 humidity, and nan on pressure. The other 2 were worse. I was under the impression that these sensors were more accurate than the DHT types and the 18B20, but in this case it doesn’t appear to be so. Running the chipID sketch in the adafruit examples (in the Arduino IDE) indicates that the chip ID is 0x58 which is why the sketch won’t work. The link above shows how to circumvent that. I’m guessing there are many “copys” of the original Bosch chips out there.
Hi Sara, I’ve messed with this project a few times, but have stumbled a couple times; once with the BME 280, other times with firmware, and put it aside to deal with hight priorites. Still trying to get it going, and my latest issue which I don’t understand, is that when I try to upload the data to spiffs, I get a lengthy error
Arduino: 1.8.10 (Windows 10), Board: “LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Disabled (new can abort), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600”
Executable segment sizes:
IROM : 303132 – code in flash (default or ICACHE_FLASH_ATTR)
IRAM : 28520 / 32768 – code in IRAM (ICACHE_RAM_ATTR, ISRs…)
DATA : 1272 ) – initialized variables (global, static) in RAM/HEAP
RODATA : 2572 ) / 81920 – constants (global, static) in RAM/HEAP
BSS : 25872 ) – zeroed variables (global, static) in RAM/HEAP
Sketch uses 335496 bytes (32%) of program storage space. Maximum is 1044464 bytes.
Global variables use 29716 bytes (36%) of dynamic memory, leaving 52204 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port COM5
Connecting….
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: bc:dd:c2:2a:3a:9a
Uploading stub…
Running stub…
Stub running…
Changing baud rate to 460800
Changed.
Configuring flash size…
Auto-detected Flash size: 4MB
Compressed 339648 bytes to 244089…
Writing at 0x00000000… (6 %)
Writing at 0x00004000… (13 %)
Writing at 0x00008000… (20 %)
Writing at 0x0000c000… (26 %)
Writing at 0x00010000… (33 %)
Writing at 0x00014000… (40 %)
Writing at 0x00018000… (46 %)
Writing at 0x0001c000… (53 %)
Writing at 0x00020000… (60 %)
Writing at 0x00024000… (66 %)
Writing at 0x00028000… (73 %)
Writing at 0x0002c000… (80 %)
Writing at 0x00030000… (86 %)
Writing at 0x00034000… (93 %)
Writing at 0x00038000… (100 %)
Wrote 339648 bytes (244089 compressed) at 0x00000000 in 5.6 seconds (effective 489.0 kbit/s)…
Hash of data verified.
Leaving…
Hard resetting via RTS pin…
[SPIFFS] data : C:\Users\flagt\Documents\Arduino\ESP8266_SPIFFS\data
[SPIFFS] size : 2024
[SPIFFS] page : 256
[SPIFFS] block : 8192
/index.html
/style.css
[SPIFFS] upload : C:\Users\flagt\AppData\Local\Temp\arduino_build_100253/ESP8266_SPIFFS.spiffs.bin
[SPIFFS] address : 0x200000
[SPIFFS] reset : –before default_reset –after hard_reset
[SPIFFS] port : COM5
[SPIFFS] speed : 921600
[SPIFFS] python : python.exe
[SPIFFS] uploader : C:\Users\flagt\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.2\tools\upload.py
Python was not found but can be installed from the Microsoft Store: https://go.microsoft.com/fwlink?linkID=2082640SPIFFS Upload failed!
I’m not getting where python has anything to do with this, can you enlighten me before I go off in a wrong direction, thanks.
As an update to my last post, I’ve reinstalled the Arduino IDE, along with support for the ESP8266. I’ve uploaded several sketches successfully, along with uploading files to spiffs. However when I upload the sketch for this project something goes wrong. I get no output on the serial monitor unless I change the baud rate to the diagnostic speed of 74880, and on reset I get:
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1392, room 16
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld
Hi John.
Can you try uploading a blank sketch, and then a blinking LED sketch and see if it works?
Also, make sure you’re using a good USB cable to upload code and provide power.
Regards,
Sara
Power and cable good, this module is has been in use for many projects. (Mostly yours 😉 )
I’ve uploaded and run:
Blink
Memory test from examples
and your Esp8266 HTML server (adapted and modified for my needs)
All ran well.
Sara, I should also mention that I updated the spiffs uploader library to ver 5.0
which is supposed to allow for python 3.0 usage.
After doing some reserach on the spiffs file system, I found this:
FUNCTION begin
SPIFFS.begin()
This method mounts file system. It must be called before any other FS APIs are used. Returns true if file system was mounted successfully, false otherwise.
By adding a couple strategic println statements I found that the sketch was indeed running but no output to the serial monitor was available, because it wasn’t getting to those functions.
I added a SPIFFS.begin() at the top of the setup function, and it now runs.
hi john can you please tell me where exactly do you add the SPIFFS.begin line because i am getting same text errors. and unable to find it I need it urgently.
Hi saiyad,
Actually spiffs is being deprecated, so I don’t know if you want to use it or not. It is being replaced by “LittleFS”. You can download the library through your Arduino library manager.
It works the same as spiffs, be careful when you upload your files to the ESP8266 that you choose ESP8266 LittleFS data upload. If you want to try Spiffs.begin you can put it in your setup function.
I have uploaded the code successfully. But the IP address is picturing in machine language on pressing the reset button of the board. How to rectify
Hi.
What do you mean?
Double-check that you have the right baud rate selected on the Serial Monitor at the bottom right corner.
Regards,
Sara
Thnx a lot for this example. It is much appreciated.
I’ve been playing with both the ESP8266 and ESP32. It seems that a bunch of Wifi related libraries are shared and then there are specific libraries for each. Just looking at the ESP8266 it seems that there libraries with similar functionality:
ESPAsyncWebServer and ESP8266WebServer. When should we use which library?
Possible scenarios:
1 )Webserver with SPIFFS to serve pages – Accesspoint so you could connect to it directly from a mobile phone
2) Same as above , but it connects to your home network
3) You want to scan for available networks
4) Run both a webserver and push data using MQTT
Keep up the great work!!
Hey Rui & Sara good stuff well organized, thanks.
I’m running into an issue with a similar concept, HTML and CSS on SPIFFS where I have %NAME% “placeholders” in the HTML that I’m filling using:
server.on(“/network.html”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/network.html”, String(), false, urlProcessor);
});
urlProcessor is rather long and complex but I can see it being called with the correct placeholders but also strings like (from my debug log):
54855: urlProcessor(): Requested “;
min-height: 100”
55019: urlProcessor(): Requested “);
background-repeat: repeat-”
It turns out these are from my CSS where I’m using things like “width: 100%;”
Any time I’m using a % sign in my CSS the following text is being evaluated as a placeholder and being sent to urlProcessor().
Why? And how do I stop it?
Hi Martin.
Do you have separated CSS and HTML files? Or is it everything on the same file?
If you have everything on the same file, create an HTML and a separated CSS file.
Regards,
Sara
Yes dashboard.html uses main.css and the problem is occurring with for example width: “100%; height: 100%;” in main.css
The string “; height: 100” is being passed to my processor function.
How are you handling the call for the main.css file?
It should be something like this without the processor on the send() function.
server.on(“/main.css”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/main.css”, “text/css”);
});
Ah, I think you have it. Due to my ordering of handlers I think the requests for main.css were being handled by the wrong handler.
I guess I don’t properly understand esp8266 asyncwebserver at the level of detail I need.
Thanks
But, is it working now?
Regards,
Sara
Yes its working now thanks. I ended up moving the following “default” handler to the bottom of the list of declarations:
server
.serveStatic(“/”, SPIFFS, “/”)
.setDefaultFile(“index.html”)
.setAuthentication(appConfig.adminCredentials.userName, appConfig.adminCredentials.password);
Question related to %PLACEHOLDER%. I have the following in my .html:
and the url processor returns /signal{1-5}.png (depending on the RSSI signal strength. On initial load the page loads the image /signal2.png or whatever.
However, in the javascript to refresh I’m calling a separate URL /signal which returns the same name of the image to load, however because its not being processed by the URL processor the web page displays the text “signal2.png” rather than loading the image signal2.png.
How can I get the javascript to display the image instead of the path to the image?
Missing snippet from my .html:
You cannot insert HTML here.
Are you using the processor to handle the request on the other separate URL /signal?
Not sure if you mean cannot insert HTML into this comment section, or use the URL processor to return complete HTML statements.
I am using a URL processor function to handle the main page and a separate function that just returns a single value on /signal.
So now I have both those functions returning an entire HTML img tag and its working great.
I’m pretty sure I can use the same technique to return javascript to be executed. Which opens lots of exciting doors for dynamic pages.
Thanks for your help
Hi.
I was talking about inserting HTML in the comment section.
You can return whatever you want in the processor, and it will be included in the HTML text (including javascript)
Regards 🙂
Sara
html stripped 🙂
Wictory !!! I solved problem with my ESP8266 module:
Step 1 : i reflashed “bios” with official firmware (AT supporting) by this link instructables.com/id/Intro-Esp-8266-firmware-update/
Step 2 : i installed to the arduino tool EspExceptionDecoder this utility decode
numbers from owerflowing stacks output of this utility give relevant data which help for investigate.
Step 3 : i defined correctly ESP module in arduino IDE. My board is named as WiFi D1.Warning are not correctly compatible with generic ESP8266 module!!! After this setting , all running is OK. FTP server. NTP client, asyncwebserver spiffs uploader …
Thanks!
I got it working as described.
My only trouble was connecting to my local network, the reset button on the NodeMCU-12E did not establish the connection, BUT unplugging/replugging the board from the USB worked instantly.
hi csv can you please help me i am getting below shown error while uploading same code as above.
Exception (28):
-> epc1=0x4020808c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
-> >>>stack>>>
-> ctx: sys
Do you have any examples or could provide one that shows how to set up the SPIFFS (server on) code if you have multiple html pages and more than one style.css? Ie what are the equivalent calls to:
server.on(“/style.css”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/style.css”,”text/css”);
});
AND
if I have many variables across multiple pages, do I combine the variables in a single Process function or do I need to somehow distinguish between the pages?
Another question is how do you determine what is the best approach to the various options you’ve presented for doing web interaction. One mode seems to be driven like a callback (i.e. set interval function) and %BUTTONHOLDER%. Other examples have the web interaction driven by “client….” pushing HTML code. I think I prefer the callback types better – especially with SPIFFS, that keeps most of the UI code out of the sketch. Any comment?
hi,
I added a button to this project to pulse the led for 5 secs when you press it but it doesn’t work can you please help?
This is the Arduino code I added:
// pulse output
server.on(“/pulse”, HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, LOW);
delay(5000);
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, “/index.html”, String(), false, processor);
});
This is the html I added:
pulse
The button works but like the off button, not pulsing.
<!– pulse –>
sorry.
Hi.
You should avoid adding delays inside that function.
Instead, add a flag variable and check its value on the loop.
For example:
bool pulseOn;
server.on(“/pulse”, HTTP_GET, [](AsyncWebServerRequest *request){
pulseOn = true;
Then, in the loop(), check the value of the variable and blink the LED accordingly.
Because there is a long delay, I recommend using timers to blink the LED. Otherwise, you’ll block your code.
I hope this helps.
Regards,
Sara
Hi Rui & Sara,
I modified this project to work with a DHT21 sensor so as to have automatic updates on sensors in place. I also moved the index.html file into flash using LittleFS. Along with the index file there is a graphic that loads via an img tag in the index file, along with a style.css. It all works but there is an 8-9 second delay when first logging on the server for the place holders to be populated with readings. I verified that by reverting back to the index file within the sketch and the readings loaded almost imeadiately. Is there any way to speed it up using LittleFS?
hello
Exception (28):
-> epc1=0x4020808c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
-> >>>stack>>>
-> ctx: sys
I am doing the same thing as it is suggested in this blog it was a great program but somehow I am getting the above-shown error also I have run this code many time ago it was giving me the same error something i can interpret from this error is that It is stack error that is happening when i go to the IP address or web server it can’t show me any data and in the serial monitor, it shows same as above. Please help me I’m really in need.
Hey, when i try to open the local server it is unable to load the homepage.
did everything as mentioned ie. uploading and all , still am unable. it says problem loading page
Hi.
Are you sure you uploaded all the files correctly to your board?
Regards,
Sara
I have the same problem.
I feel like I’ve tried everything.
No errors during compiling or uploading sketch.
I use a nodeMCU 8266
same here. Just replaced bme sensor for ds18b20 and check data files are written in SPIFFS correctly.
ino file: pastebin.com/QwsVuTuX
serial monitor output: pastebin.com/11ELMz2L
Hello Rui and Sarah!
I’m very interested in your lessons. Your work is very useful for people like me. But it’s very difficult to find the answers for some questions. Based on this lesson, I’d like to create a button or slider for a web page in two positions “Auto-Manual”. In “Auto” position, one part of the code will be executed. In the “Manual” position, another part of the code will be executed.
For example: if in the “Auto” position, the following will be executed:
if (temperature>=28) digitalWrite(ledPin, HIGH);
else digitalWrite(ledPin, LOW);
The code shows that, if the temperature exceeds 28 degrees, the LED will light up.
If the button is in the manual position, then i need transfer control to the “ON” and “OFF” buttons from referring to your project. Maybe there is an example or specify a link? Thank you for your help!
P.S. sorry, but Google translate English, knows more than I do 🙂
Hi.
We don’t have a specific tutorial for what you want to do.
We have the following tutorials that might help with your project:
https://randomnerdtutorials.com/esp32-esp8266-thermostat-web-server/
https://randomnerdtutorials.com/esp8266-nodemcu-async-web-server-espasyncwebserver-library/
https://randomnerdtutorials.com/esp8266-nodemcu-websocket-server-arduino/
Regards,
Sara
Somebody stealing your content (:::::::::)
Hi.
Thanks for letting us know.
There are many websites stealing our content -.-
Unfortunately, there’s nothing we can do about it.
We hope our readers know that ours is the original content.
Thanks.
Regards,
Sara
sad.
i immediately recognized it coz of the good quality pictures
Hi Sara,
Is there anyway to change the sensor readings which shows up in the web server to whole number or 1decimal place? When I tried to change it crashes the program:(
Hey anyone,
is there a way to make a timer after this function and return the webpage without get behind it??
server.on(“/Timer”, HTTP_GET, [](AsyncWebServerRequest *request){
digitalWrite(ledPin, HIGH);(THIS STAYS HIGH and i want it to go low after time (3 sec))
request->send(SPIFFS, “/index.html”, String(),false, processor);
});
or does the javascript as to be adjusted.(i just don’t now how??)
thanks,
Ed
Hi.
Are you looking for something like this?
https://randomnerdtutorials.com/esp32-esp8266-web-server-timer-pulse/
Regards,
Sara
hi sara,
thank you for your tutorials, it’s very useful for a beginner like me. i’m stuck with this tutorial since i’m not able to see any html page after uploading sketch and data files. Instead of using a bme sensor, i replaced a ds18b20 for temperature readings and the others parameters i just hardcoded as constant values.
ino file: https://pastebin.com/QwsVuTuX
css and html files are exactly the same
serial monitor output: https://pastebin.com/11ELMz2L
ms edge explorer message: https://pastebin.com/pxqR72EP
i appreciate any help. Thank you very much in advance
hi sara,
thank you for your tutorials, it’s very useful for a beginner like me. i’m stuck with this tutorial since i’m not able to see any html page after uploading sketch and data files. Instead of using a bme sensor, i replaced a ds18b20 for temperature readings and the others parameters i just hardcoded as constant values.
ino file: pastebin.com/QwsVuTuX
css and html files are exactly the same
serial monitor output: pastebin.com/11ELMz2L
ms edge explorer message: pastebin.com/pxqR72EP
i appreciate any help. Thank you very much in advance
Hi.
Did you place the files on a data folder inside the sketch folder?
Did you upload the files and then the code?
Regards,
Sara
yes, all of these was already checked. finally found the issue, when i switched library spiffs to littleFS i didnt change the corresponding instance. Now it’s working correctly. hope it helps.
thank you very much for your tutorials 😉
Hi,
I have problem with compilation. Please tell mi what is wrong:
In function ‘String processor(const String&)’:
ESP8266_SPIFFS:79:1: error: control reaches end of non-void function [-Werror=return-type]
79 | }
| ^
cc1plus.exe: some warnings being treated as errors
exit status 1
control reaches end of non-void function [-Werror=return-type]
Thanks for help
You need to add
return String();
before the last } of the processor function.
Regards,
Sara
Sara – THANK YOU so much for this article! I am so glad I found it. I have been struggling to get HTML and associated style pages and images to display from an ESP2866 web server with all kinds of hacks from other users that never worked right. This will be such a time saver for several projects I am working on. Excellent example and explanation of each line of code.
BTW: The only small adjustment I made was to use LittleFS instead of SPIFFS since apparently SPIFFS has been deprecated.
Hi.
Yes, SPIFFS still works, but it is recommended to use LittleFS instead.
Regards,
Sara
Hi. first of all, thank you for your job. It is very interesting for me.
I am trying to learn about websocket and a web server for my WEMOS D1. What is the difference between this code and another that uses websocket?
Can I use this like a real time update server?
Thanks again
Hi.
This example works with HTTP requests. This means that the server can only send data to the client, when the client makes a request. The server cannot send data to the client without being requested.
For example, with this method to get real-time data, you need to constantly refresh the web page to get the latest data.
With websockets, once the connection between the client and the server is established, the server and the client can exchange data. The server can send data to the client without being requested. This allows the client to get real time updates from the server.
I hope this is clear.
If you want to learn more about these subjects to build your own web server, consider taking a look at our “Build Web Servers” ebook. You can take a look at the content here and see if it would be helpful: https://randomnerdtutorials.com/build-web-servers-esp32-esp8266-ebook/
Regards,
Sara
Ciao
Caricando il progetto ESP8266_SPIFFS.ino su vscode con estensione platformio quando vado a fare il build mi da questo errore :
C:/Users/user2/Documents/PlatformIO/Projects/230201-162022-esp12e/src/ESP8266_SPIFFS.ino:
In function ‘String processor(const String&)’:
C:/Users/user2/Documents/PlatformIO/Projects/230201-162022-esp12e/src/ESP8266_SPIFFS.ino:81:1: error: control reaches end of non-void function [-Werror=return-type]
81 | }
| ^
cc1plus.exe: some warnings being treated as errors
*** [.pio\build\esp12e\src\ESP8266_SPIFFS.ino.cpp.o] Error 1
Riguarda la funzione processor non ne riesco a risolvere il problema qualche consiglio
grazie
Hi.
Add
return String();
in the processor() function, right before the last “}”
I’ll fix the code soon.
Regards,
Sara
Hello, I just want to ask how to display the output from sensor to web?? how about if all the sensors are on the arduino dual board then the data will be passed to nodemcu then displayed on the web? how is that? please help me
I was really glad to have finally found some information on how to use SPIFFS to store files that I van use as CSS and HTML pages for my application. But after studying a lot on these pages I found out that neither SPIFFS not LITTLEFS work with the current versions of the Arduino IDE. I am not going to go back to some old version to use this tool. So I will have to find another way to make my application work. Hopefully some day this functionality becomes available for the Arduino IDE version 2 and upwards, but until then it seems I cannot use the information on this site.
Hi.
Unfortunately, there isn’t support yet for the LittleFS or SPIFFS uploader tool in Arduino 2.0.
Regards
Sara
Thank you for your clarification.
Regards, Ruud
Dear Sara,
I think I have found out that the exception decoder (https://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html#exception-decoder) is also a tool that cannot be used as of version 2.0 of the Arduino IDE? Would you recommend ignoring version 2.0 until it is mature enough to support the necessary tools or changing towards Platform IO?
Thank you for your educated opinion on this!
Regards, Ruud
Hi.
It’s a matter of preference.
I prefer to wait until it’s mature enough to support those tools.
I use Arduino IDE version 1.8 and it works well enough for most of my projects.
I also use PlatformIO a lot, depending on the project’s complexity.
Learning PlatformIO + VS Code will bring you several advantages in the future, but it may take you some time to get used to it.
Regards,
Sara
Hello I want to ask if the SPIFFS works with the ESP-12E the bare bone version(I mean the version without the usb) if i want to program it with FTDI converter
Hi.
Currently, it is recommended to use LittleFS for ESP8266 instead of SPIFFS.
See how to use LittleFS here: https://randomnerdtutorials.com/install-esp8266-nodemcu-littlefs-arduino/
Regards,
Sara
Thanks a lot for your project. Based on it, I developed a reading lights device for a bed head. if you can give a try, https://github.com/agrgal/LucesLectura
Hello
Please help
How exactly in this project to add
management of another GPIO