Learn how to plot sensor readings (temperature, humidity, and pressure) on a web server using the ESP32 or ESP8266 with Arduino IDE. The ESP will host a web page with three real-time charts that have new readings added every 30 seconds.
Project Overview
In this tutorial we’ll build an asynchronous web server using the ESPAsyncWebServer library.
The HTML to build the web page will be stored on the ESP32 or ESP8266 Filesystem (LittleFS).
We’ll display temperature, humidity and pressure readings from a BME280 sensor on a chart, but you can modify this project to display sensor readings from any other sensor. To learn more about the BME280, read our guides:
- ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)
- ESP8266 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)
To build the charts, we’ll use the Highcharts library. We’ll create three charts: temperature, humidity and pressure over time. The charts display a maximum of 40 data points, and a new reading is added every 30 seconds, but you change these values in your code.
Watch the Video Demonstration
To see how the project works, you can watch the following video demonstration:
Prerequisites
Make sure you check all the prerequisites in this section before continuing with the project in order to compile the code.
1. Install ESP Board in Arduino IDE
We’ll program the ESP32 and ESP8266 using Arduino IDE. So, you must have the ESP32 or ESP8266 add-on installed. Follow one of the next tutorials to install the ESP add-on:
- Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, Linux)
- Installing ESP8266 Board in Arduino IDE (Windows, Mac OS X, Linux)
2. Filesystem Uploader Plugin
To upload the HTML file to the ESP32 and ESP8266 flash memory, we’ll use a plugin for Arduino IDE: Filesystem uploader. Follow one of the next tutorials to install the filesystem uploader plugin. The uploader is compatible with both boards.
- Arduino IDE 2: Install ESP8266 NodeMCU LittleFS Uploader (Upload Files to the Filesystem)
- Arduino IDE 2: Install ESP32 LittleFS Uploader (Upload Files to the Filesystem)
3. Installing Libraries
To build the asynchronous web server, you need to install the following libraries.
- ESP32: you need to install the ESPAsyncWebServer and the AsyncTCP libraries.
- ESP8266: you need to install the ESPAsyncWebServer and the ESPAsyncTCP libraries.
These libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino Installation folder.
To get readings from the BME280 sensor module you need to have the next libraries installed:
You can install these libraries through the Arduino Library Manager.
Parts Required
To follow this tutorial you need the following parts:
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
The BME280 sensor module we’re using communicates via I2C communication protocol, so you need to connect it to the ESP32 or ESP8266 I2C pins.
BME280 wiring to ESP32
BME280 | ESP32 |
SCK (SCL Pin) | GPIO 22 |
SDI (SDA pin) | GPIO 21 |
So, assemble your circuit as shown in the next schematic diagram.
Recommended reading: ESP32 Pinout Reference Guide
BME280 wiring to ESP8266
BME280 | ESP8266 |
SCK (SCL Pin) | GPIO 5 |
SDI (SDA pin) | GPIO 4 |
Assemble your circuit as in the next schematic diagram if you’re using an ESP8266 board.
Recommended reading: ESP8266 Pinout Reference Guide
Organizing your Files
To build the web server you need two different files. The Arduino sketch and the HTML file. The HTML file 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><html>
<!-- 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. -->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.highcharts.com/highcharts.js"></script>
<style>
body {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto;
}
h2 {
font-family: Arial;
font-size: 2.5rem;
text-align: center;
}
</style>
</head>
<body>
<h2>ESP Weather Station</h2>
<div id="chart-temperature" class="container"></div>
<div id="chart-humidity" class="container"></div>
<div id="chart-pressure" class="container"></div>
</body>
<script>
var chartT = new Highcharts.Chart({
chart:{ renderTo : 'chart-temperature' },
title: { text: 'BME280 Temperature' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: '#059e8a' }
},
xAxis: { type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Temperature (Celsius)' }
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000 ) ;
var chartH = new Highcharts.Chart({
chart:{ renderTo:'chart-humidity' },
title: { text: 'BME280 Humidity' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
}
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Humidity (%)' }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 30000 ) ;
var chartP = new Highcharts.Chart({
chart:{ renderTo:'chart-pressure' },
title: { text: 'BME280 Pressure' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: '#18009c' }
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Pressure (hPa)' }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartP.series[0].data.length > 40) {
chartP.series[0].addPoint([x, y], true, true, true);
} else {
chartP.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/pressure", true);
xhttp.send();
}, 30000 ) ;
</script>
</html>
Let’s take a quick look at the relevant parts to build a chart.
First, you need to include the highcharts library:
<script src="https://code.highcharts.com/highcharts.js"></script>
You need to create a <div> section for each graphic with a unique id. In this case: chart-temperature, chart-humidity and chart-pressure.
<div id="chart-temperature" class="container"></div>
<div id="chart-humidity" class="container"></div>
<div id="chart-pressure" class="container"></div>
To create the charts and add data to the charts, we use javascript code. It should go inside the <script> and </script> tags.
The following spinet creates the temperature chart. You define the chart id, you can set the title, the axis labels, etc…
var chartT = new Highcharts.Chart({
chart:{ renderTo : 'chart-temperature' },
title: { text: 'BME280 Temperature' },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: '#059e8a' }
},
xAxis: { type: 'datetime',
dateTimeLabelFormats: { second: '%H:%M:%S' }
},
yAxis: {
title: { text: 'Temperature (Celsius)' }
//title: { text: 'Temperature (Fahrenheit)' }
},
credits: { enabled: false }
});
Then, the setInterval() function adds points to the charts. Every 30 seconds it makes a request to the /temperature URL to get the temperature readings from your ESP32 or ESP8266.
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 30000 ) ;
The other graphics are created in a similar way. We make a request on the /humidity and /pressure URLs to get the humidity and pressure readings, respectively.
In the Arduino sketch, we should handle what happens when we receive those requests: we should send the corresponding sensor readings.
Arduino 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 make it work.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-plot-chart-web-server/
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.
*********/
#ifdef ESP32
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#else
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#include <FS.h>
#endif
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
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_IWTH_YOUR_SSID";
const char* password = "REPLACE_IWTH_YOUR_PASSWORD";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
String readBME280Temperature() {
// Read temperature as Celsius (the default)
float t = bme.readTemperature();
// Convert temperature to Fahrenheit
//t = 1.8 * t + 32;
if (isnan(t)) {
Serial.println("Failed to read from BME280 sensor!");
return "";
}
else {
Serial.println(t);
return String(t);
}
}
String readBME280Humidity() {
float h = bme.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read from BME280 sensor!");
return "";
}
else {
Serial.println(h);
return String(h);
}
}
String readBME280Pressure() {
float p = bme.readPressure() / 100.0F;
if (isnan(p)) {
Serial.println("Failed to read from BME280 sensor!");
return "";
}
else {
Serial.println(p);
return String(p);
}
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
bool status;
// default settings
// (you can also pass in a Wire library object like &Wire2)
status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
// Initialize LittleFS
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting LittleFS");
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(LittleFS, "/index.html");
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readBME280Temperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readBME280Humidity().c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readBME280Pressure().c_str());
});
// Start server
server.begin();
}
void loop(){
}
How the code works
Let’s take a quick look at the code and see how it works.
Including libraries
First, include the necessary libraries. You include different libraries depending on the board you’re using. If you’re using an ESP32, the code loads the following libraries:
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
If you’re using an ESP8266, the code loads these libraries:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Create an instance to communicate with the BME280 sensor using I2C:
Adafruit_BME280 bme; // I2C
Insert your network credentials in the following variables:
// 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);
Read Temperature, Humidity and Pressure
Then, we create three functions readBME280Temperature(), readBME280Humidity() and readBME280Pressure(). These functions request the temperature, humidity and pressure from the BME280 sensor and return the readings as a String type.
String readBME280Temperature() {
// Read temperature as Celsius (the default)
float t = bme.readTemperature();
// Convert temperature to Fahrenheit
//t = 1.8 * t + 32;
if (isnan(t)) {
Serial.println("Failed to read from BME280 sensor!");
return "";
}
else {
Serial.println(t);
return String(t);
}
}
Init BME280
In the setup(), initialize the sensor:
status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Init LittleFS
Initialize the filesystem (LittleFS):
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting LittleFS");
return;
}
Connect to Wi-Fi
Connect to Wi-Fi and print the IP address in the Serial Monitor:
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());
Handle requests
Then, we need to handle what happens when the ESP receives a request.
When it receives a request on the root URL, we send the HTML text that is saved in LittleFS under the index.html name:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html");
});
When we receive a request on the /temperature, /humidity or /pressure URLs, call the functions that return the sensor readings.
For example, if we receive a request on the /temperature URL, we call the readBME280Temperature() function that returns the temperature.
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readBME280Temperature().c_str());
});
The same happens for the other readings.
Finally, start the server:
server.begin();
Because this is an asynchronous web server we don’t need to write anything in the loop().
void loop(){
}
Uploading Code and Files
Save the code as ESP_Chart_Web_Server or download all project files here. Go to Sketch > Show Sketch Folder, and create a folder called data. Inside that folder you should save the HTML file created previously.
Now you need to upload the HTML file to the ESP32 or ESP8266 filesystem.
Press [Ctrl] + [Shift] + [P] on Windows or [⌘] + [Shift] + [P] on MacOS to open the command palette. Search for the Upload LittleFS to Pico/ESP8266/ESP32 command and click on it.
If you don’t have this option is because you didn’t install the filesystem uploader plugin. Check this tutorial.
Important: make sure the Serial Monitor is closed before uploading to the filesystem. Otherwise, the upload will fail.
Then, upload the code to your board. Make sure you have the right board and COM port selected. Also, make sure you’ve inserted your networks credentials in the code.
When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the board “EN/RST” button, and it should print its IP address.
Demonstration
Open a browser on your local network and type the ESP32 or ESP8266 IP address. You should see three charts. A new data point is added every 30 seconds to a total of 40 points. New data keeps being displayed on the charts as long as you have your web browser tab open.
Here is an example of the humidity chart:
You can select each point to see the exact timestamp.
Wrapping Up
In this tutorial you’ve learned how to create charts to display data in your web server. You can modify this project to create as many charts as you want and using any other sensors.
Next, we recommend building a project that displays charts from data stored on your database. Here are other tutorials that you might like:
- Visualize Your ESP32/ESP8266 Sensor Readings from Anywhere in the World
- ESP32/ESP8266 Insert Data into MySQL Database using PHP and Arduino IDE
If you would like to learn more about building web servers with the ESP32 and ESP8266 boards, we have an eBook dedicated to that subject:
Learn more about the ESP32 and ESP8266 with our resources:
- Learn ESP32 with Arduino IDE (eBook)
- Home Automation Using ESP8266
- SMART HOME with Raspberry Pi, ESP32, and ESP8266
- Build Web Servers with ESP32 and ESP8266 (eBook)
- Free ESP32 Projects and Tutorials…
- Free ESP8266 Projects and Tutorials…
Thank you for reading.
Thank you for making all of these free tutorials. They are well done easy to follow and the explanations of how it works are very good. Again thanks.
Hi Rui, hi Sara, thanks for this other amazing tutorial!!!
It would be really cool to have the opportunity to generate a log file in .csv file from the web page, the web server should be password protected.
I see wen we make the web server the ESP8266 is set in AP and Station mode simultaneously and I see on my network another network with different IP classe. Could it be possible to use this network to set the SSID and WiFi password in order to avoid everytime to get connected to the laptop the device and fix the credentials data?
Think about it, it will be the maximum!!!!
You can check out my project there I have an csv export: github.com/pknoe3lh/ESP32_ReflowOvenController
Thanks for sharing! Regards,
Rui
try to add below script to generate menu button.
menu button will show different types of export and table data display.
https://code.highcharts.com/modules/exporting.js
https://code.highcharts.com/modules/offline-exporting.js
https://code.highcharts.com/modules/export-data.js
hope this will help
Great tutorial, very useful
Hi Ruis.
Thanks for this good tutorial. You can use any JS library chart guys.
I compiled all this using recommended libraries with my ESP32 DEVKIT V1, sont if you get errors when compiling do not remove ESPAsyncTCP library because it is used for ESP8266 MCUs as Ruis said. if you get errors during code compilation using ESP32 MCU Below are some changes to make in AsyncTCP library :
Rename ESPAsyncTCP.cpp and ESPAsyncTCP.h files to AsyncTCP.cpp
AsyncTCP.h files
Rename ESPAsyncTCPbuffer.cpp and ESPAsyncTCPbuffer.h files to AsyncTCPbuffer.cpp
AsyncTCPbuffer.h files
In AsyncPrinter.cpp and SyncClient.cpp files, change the library ESPAsyncTCP.h to AsyncTCP.h.
Once done, Inside every files correct ESPAsync to Async in order to get everything linked properly
Also commenting panic() method helped me.
The only update you have to make it’s regarding Arduino OTA. If you upgrade to the Arduino ESP32 latest library, make sure to update the Arduino OTA also to the latest.
Thanks guys
Thanks for sharing your helpful feedback
thanks, I am a bit confused, are you in fact saying the library is faulty? or do we have to undo it again when using an esp8266?
Hi;
get a failure after installation on ESP32-WROOM:
E (446) SPIFFS: mount failed, -10025
An Error has occurred while mounting SPIFFS
Van you help me?
Unfortunately I’ve never encountered that error before… Make sure you’ve uploaded properly the data folder to your ESP chip.
Hi
I also had the same problem, then i have changed in the menu: Tools / Flash size / assigned 2M for SPIFFS (otherwise set to zero).
Now it Works…
Hi Rui and Sara, thanks for this great tutorial.
I need to change the time zone for + 2 hours.
Can you show us what to add in code.
Thanks in advance.
Hi
One of our readers suggested the following to fix that:
”
I fixed my time zone problems by adding this in the start of the script.
// Highcharts.setOptions({
// global: {
// useUTC: false
// }
// });
By adding the code above it will use the time zone of the browser.”
I hope this helps.
Regards,
Sara
It does 🙂
Works fine! Thanks
download js from site https://code.highcharts.com/highcharts.js and edit in line 136 find in line useUTC:!0 and change it to useUTC:!+2
now save that file on your server as highcharts.js and instead of https://code.highcharts.com/highcharts.js
call your address that is highcharts.js on your web server
It worked for me 🙂
I also changed c code for reading dht sensors not bme280 and I added heat index, fahrenheit … Also managed to add to database senzor values automaticly every minute (IIS 10.0 server asp classic)
Nice piece of coding
Keep up… =)
Hello. Anyone could explain please how to use local file instead of “https://code.highcharts.com/highcharts.js” ? I tried but didn’t managed. I put the file in SPIFFS (beside HTML/CSS/JS files in data folder) and it doesnt’ work. Regards
Did you remember to change this
https://code.highcharts.com/highcharts.js
to this
http://highcharts.js
in your index file.
Do not hope this is commented out, due to security of this site.
Thank you JB it works, I don’t know why I cannot reply to you post. I wrote src=”highcharts.js” and adding http:// as you tell make it working fine ! Thank you
thanks Roberto, it work
Thank you, it works for me. Also, I had to add a delay in my js functions to let the highcharts library to be downloaded. If not, I had “Uncaught ReferenceError: Highcharts is not defined”. Regards
Hi Harwey.
Unfortunately some of my comment has been removed
as often happens here when trying to display some code.
you do not need this http: //
only this
src = “/ highcharts.js”
between the scrip start and script end tags.
I hope all the text is shown this time.
Hi.
If you want to share code, share a link to github, google drive, or pastebin, for example.
Regards,
Sara
With http:// it works only with FF and not Chrome (or the opposite I don’t remember). I’m going to try you last advice JB, thank you
I finally have managed to do it ! I forgot to implement server.on for this file in main.cpp. Also, I had to put delays in my code because it is longer to load than from internet. Regards !
Hi Harvey
Sorry for spelling your name wrong.
Thank you to you all !
Hi Harvey. I’m glad you made it work.
I know from personal experience how teasing coding can be.
Hi, Today i try to make this code with BMP , all works good,but, how i can set my local time in code?
Thanks
Hi.
One of our readers suggested the following to fix that:
”
I fixed my time zone problems by adding this in the start of the script.
// Highcharts.setOptions({
// global: {
// useUTC: false
// }
// });
By adding the code above it will use the time zone of the browser.”
I hope this helps.
Regards,
Sara
Hello
The temperature is always 26.09 C. The humidity 47.89%. The air pressure always 1006.34. The serial monitor shows no values. The BME280 runs correctly with another program.
Where could the problem be? I am using an ESP32.
Mfg Andreas
The problem is probably the Internet explorer. Chrome and Safari are running correctly ..
Kind regards
Hi.
We’ve tested with Chrome and everything was working fine.
Sometimes our projects have some issues with internet explorer.
Regards,
Sara
FYI, Opera, Firefox, Brave and Samsung Browser (SmartPhone) have no issues either
Unfortunately the time is not correct. Difference 2 hours. I live in Germany. How can I change this?
Kind regards
Andreas
Hi Andreas
One of our readers suggested the following to fix that:
”
I fixed my time zone problems by adding this in the start of the script.
// Highcharts.setOptions({
// global: {
// useUTC: false
// }
// });
By adding the code above it will use the time zone of the browser.”
I hope this helps.
Regards,
Sara
Excelente, funcionou.
Grande abraço.
Really enjoying your tutorials and learning a lot in the process. Wondering how to use the ESP32-CAM for this project. I can’t seem to figure out how to connect the BME280 to I2C to get this to work. Any help would be appreciated.
Thank you!
Hi Greg.
Do you want to use an ESP32-CAM to do this project?
The I2C pins of the ESP32-CAM are internally connected to the camera, so I don’t think you can use the camera with the BME280 at the same time. Unless, you configure your code to use other pins as I2C. For example, GPIO 12 and GPIO 13 if you’re not using SD card. However, I don’t know if this I2C will conflict with the camera I2C.
Regards,
Sara
Hi Rui and Sara.
I fixed my time zone problems by adding this in the start of the script.
// Highcharts.setOptions({
// global: {
// useUTC: false
// }
// });
By adding the code above it will use the time zone of the browser.
Hi.
That’s great!
Thanks for sharing that. It will certainly be useful for our readers.
Regards,
Sara
Thank you very much for your great work hear.
Thanks 😀
Hi, thanks for the great tutorial.
I installed and it was working very well. But after trying to change the intervall time in the html file and some header text changes i don’t get this again on the server. I changes into the data folder within the Sketch Folder and reloaded with the ESP8266 Sketch Data Upload , but no change on the Server output.
Do you have an idea what can be wrong on my changes.
Thanks in advance
Now I found out the issue. The ESP8286 Sketch Data Upload do not use the html file in the folder I created under Arduino/data instead it used the data folder I downloaded unter Download like your description.
So i changed the data in this folder and it works fine.
Regards Hans.
Hello Hans
ESP32/ESP8266 Plot Sensor Readings in Real Time Charts – Web Server
bmp is recognized and the ip address can be connected to but blank page.
Is this the problem you had?
Yes it looks like the index.html file not used.
Not sure what to do
Hi.
You probably didn’t upload the HTML file to the filesystem.
Check the section “Uploading Code and Files” in detail. You probably missed one of the steps.
Regards,
Sara
Hello,
Thank you for sharing your work, this looks very interesting, particularly the use of the charting libraries. However, I cannot access the code, GitHub returns an error 500 each time, even if I try to access your repo directly from my account.
Is there something wrong at Github, or did you remove your code?
Thank you.
Hello Jacques, I’m not sure what happened.
Can you try to open this link again to download all the code?
https://github.com/RuiSantosdotme/Random-Nerd-Tutorials/raw/master/Projects/ESP/ESP_Chart_Web_Server.zip
Another cracking tutorial…..well done guys.
Had it up and running in a jiffy. I’ve registered with a DDNS supplier and have configured remote access so that I can access from anywhere on the internet.
Waiting for the DB access that you mentioned in the write up as I have an SQL database set up for the same readings as per your last tutorial.
See below my URL address so you can check my live readings.
Keep up the great work……..
Regards
Alan
Sorry, Web URL didn’t get posted…..here’s the link
http://hometph.ddns.net:51000
Regards
Alan
Hi Rui and Sara.
it is also possible to change the time zone by adding this in the start of the script.
the minus sign is necessary to add the 2 hours.
// Highcharts.setOptions({
// time: {
// timezoneOffset: -2 * 60
// }
// });
Regards J.B.
All without the // I presume?
Not sure if that last correction will take care of the DaylightSavingTime
👍👍everything is fine
Hi again.
I think this should take care of daylight saving time crossover if the other options don’t
place this where the other scripts are declared without the //
// https://code.highcharts.com/highcharts.js
// https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js
// https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js
and replace the Highcharts.setOptions with this, without the //
// Highcharts.setOptions({
// time: {
// /**
// * Use moment-timezone.js to return the timezone offset for individual
// * timestamps, used in the X axis labels and the tooltip header.
// */
// getTimezoneOffset: function (timestamp) {
// var zone = ‘Europe/Oslo’,
// timezoneOffset = -moment.tz(timestamp, zone).utcOffset();
//
// return timezoneOffset;
// }
// }
// });
Where do I add this command? I put in the sketch, but returned an error saying that the Highcharts function was not declared.
I’ve auto-translated your comments. Please only speak in English on my blog, otherwise other readers will not benefit from your answer. Thank you.
hello,
my code does’nt work with an esp32. message : Could not find a valid BME280 sensor, check wiring!
I checked the wiring and it’s ok
any idea ?
Thanks,
marc,
Hi Marc.
Please check the I2C address of your BME280.
To do that, with the BME280 wired to the ESP32, run this sketch: https://raw.githubusercontent.com/RuiSantosdotme/Random-Nerd-Tutorials/master/Projects/LCD_I2C/I2C_Scanner.ino
Then, insert your BME280 I2C address in the following line of code, if it is different than 0x76:
status = bme.begin(0x76);
If this doesn’t work, it is probably the wiring: a faulty wire, connection to the wrong pin, etc…
Regards,
Sara
Guys, you’re just too good! I always follow this site and I have never being disappointed, in fact, I think I just need to buy one of your ebooks now.
Please keep up the good job
Hi.
Thank you so much for your nice words and for supporting our work.
All the best,
Sara
This is a great example. I got it running in no time. I made a couple of changes. I added FTP ( handle in loop) and added a few additional lines in loop to write the data to a file in SPIFFS, tmp.csv. I would like index.html to use the data in the csv file rather than the async data so the data is non-volatile. I have looked all over the web for an example of how to use Highcharts in this manner with no success.
Can you give me enough hints to get me started?
Bill,
write sensor data to a csv (which i believe you already did)
File sensordata = SPIFFS.open(“/sensorresults.csv,”a”);
sensordata.print(unixtime);
sensordata.print(‘,’);
sensordata.println(temperature);
sensordata.close();
read the csv file
while (sensordata.available())
{
String T += char(configurations.read());
}
and separate the lines into a JSON (by looking for the EOL character
or do it directly with a library such as ‘boost’ or ‘jsoncons’
send the JSON to the client
server.on(“/temperature”, HTTP_GET, [](AsyncWebServerRequest *request){
String payload = “{YOUR JSON}”;
request->send(200, “text/plain”, payload.c_str());
});
use JSON as input to e.g. HIGHCHARTS, use the time with every sensorreading for x axis
Hi Bill,
have you solved that and can help me?
seems I am the first to have a problem compiling. lots of errors:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘void _handle_async_event(lwip_event_packet_t*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:166:68: error: no matching function for call to ‘AsyncClient::_s_dns_found(const char*&, ip_addr_t*, void*&)’
AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg);
^
In file included from /home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:24:0:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.h:137:17: note: candidate: static void AsyncClient::_s_dns_found(const char*, ip_addr*, void*)
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.h:137:17: note: no known conversion for argument 2 from ‘ip_addr_t* {aka _ip_addr*}’ to ‘ip_addr*’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘bool _start_async_task()’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:204:141: error: ‘xTaskCreateUniversal’ was not declared in this scope
xTaskCreateUniversal(_async_service_task, “async_tcp”, 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘void _tcp_dns_found(const char*, ip_addr*, void*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:303:55: error: invalid application of ‘sizeof’ to incomplete type ‘ip_addr’
memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr));
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: At global scope:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:32: error: field ‘call’ has incomplete type ‘tcpip_api_call_data’
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: forward declaration of ‘struct tcpip_api_call_data’
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_output(tcp_pcb*, AsyncClient*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:368:70: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:368:70: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_write(tcp_pcb*, const char*, size_t, uint8_t, AsyncClient*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:391:69: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:391:69: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_recved(tcp_pcb*, size_t, AsyncClient*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:413:70: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:413:70: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_close(tcp_pcb*, AsyncClient*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:433:69: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:433:69: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_abort(tcp_pcb*, AsyncClient*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:453:69: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:453:69: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_connect(tcp_pcb*, ip_addr_t*, uint16_t, tcp_connected_fn)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:472:71: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:472:71: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘esp_err_t _tcp_bind(tcp_pcb*, ip_addr_t*, uint16_t)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:490:68: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:490:68: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In function ‘tcp_pcb* _tcp_listen_with_backlog(tcp_pcb*, uint8_t)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:508:70: error: invalid conversion from ‘err_t (*)(tcpip_api_call_data*) {aka signed char (*)(tcpip_api_call_data*)}’ to ‘tcpip_api_call_fn {aka signed char (*)(tcpip_api_call*)}’ [-fpermissive]
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg);
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:508:70: error: cannot convert ‘tcpip_api_call_data*’ to ‘tcpip_api_call*’ for argument ‘2’ to ‘err_t tcpip_api_call(tcpip_api_call_fn, tcpip_api_call*)’
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:328:12: note: class type ‘tcpip_api_call_data’ is incomplete
struct tcpip_api_call_data call;
^
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp: In member function ‘void AsyncClient::_dns_found(ip_addr*)’:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:926:33: error: invalid use of incomplete type ‘struct ip_addr’
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
^
In file included from /home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.cpp:24:0:
/home/dave/Arduino/libraries/AsyncTCP-master/src/AsyncTCP.h:53:8: note: forward declaration of ‘struct ip_addr’
struct ip_addr;
^
Multiple libraries were found for “WiFi.h”
Used: /home/dave/Arduino/hardware/espressif/esp32/libraries/WiFi
Not used: /home/dave/Documents/arduino-1.8.8/libraries/WiFi
Multiple libraries were found for “Adafruit_BME280.h”
Used: /home/dave/Arduino/libraries/Adafruit_BME280_Library
Not used: /home/dave/Arduino/libraries/BME280-I2C-ESP32-master
exit status 1
Error compiling for board ESP32 Dev Module.
What board type are you using and what board type did you select?
ESP32 Dev Module is selected
MH-ET Live -ESP32 DEVKIT
has a VROOM-32
using the chip on a different sketch, it does run my OLED and display the pair of DS18B20 sensors and the pair of BME280 sensors.
even selecting the MH-ET LIVE ESP32DevKIT
it still shows the errors.
Arduino IDE 1.8.8
preferences boards ; separated by a comma
arduino.esp8266.com/stable/package_esp8266com_index.json, dl.espressif.com/dl/package_esp32_index.json
ESP32 sketch data upload is shown in tools
MHET LIVE32devKIT board is selected
AsyncTCP-master.zip in my library folder and added as a zip
ESPAsyncWebServer-master.zip also present and added as zip
since all the errors are from AsyncTCP-master
I am not sure if that is getting bad data, or not handling things.
I added the ESPAsyncTCP.h for an ESP8266
changed the board to an ESP8266 and it complied.
then, changed the board back to the ESP32
and it compiled without errors.
===============
E (440) SPIFFS: mount failed, -10025
An Error has occurred while mounting SPIFFS
===============
now I just have to play with the unit to figure out what is going on.
Did you upload the data folder with the index.html using “Tools > ESP32/ESP8266 Data Sketch Upload”?
Hi, Sara and Rui,
Thanks for uploading this nice tutorial, I wanted to plot the waveform of current but problem is that this code is updates the values after every 30 seconds which is not suitable for my case. So, please can you inform what I have to change to plot my current wave with zero delay?
Thanks for the tutorial!
I am using ESP8266-01 and the BME280 sensor did not return any data. To correct, I called the function Wire.begin (0,2);
If anyone else has this problem, the tip is
Hi Rui,
Is it possible to store the data first in SPIFFS or on a SD card and plot the data within a selected period into the webbrowser, whenever you want to check it?
Thx
Wim
Yes, it’s definitely possible, but I don’t have any tutorials on that subject…
I hoped to do the same thing you describe. I made some progress, got frustrated and set it aside for a while. Here’s what I have got so far. This is my sketch:
https://1drv.ms/u/s!AmXKqAwyCrbxiMArt67eeBAKWoy9Bg?e=ikLvVL
I have made little progress on the HighChart side. I was not able to make HighCharts grab data from a local file. Using the sketch I shared the data can be downloaded by Highcharts using something like: xmlhttp.open(“GET”, “http://your externalshare:port/temp.csv”, true); Just using file://temp.csv does not appear possible. I guess that there is a security issue of a Java script exposing a local file. Even to make the working example function, I had to put an extension in Chrome ‘Allow-Control-Allow-Origin:’ because I was serving /temp.csv via http and not https. That’s where I gave up. I hope some of this help. Perhaps Rui can shine a light on a better way.
Bill
Wouldnt it be possible that if you make a request as in e.g. in Rui’s example, that you let the server.on”/xxxxxx ” routine read data from an SDcard?
Sure Ed, that works. As Dave suggested the Sketch side can be modified to provide more data. The trick is how to modify index.html.
ah OK, then i misunderstood.
About changing the index file, I think I replied that in tw posts below.
Adding lines check arduinodiy.wordpress.com/2019/08/05/esp8266-plot-sensor-readings-in-real-time-charts-on-a-web-server/
Using the date: var x = (new Date()).getTime(),
in which ‘getTime()’ is your function of reading in the time, but it could e.g. be:
var x=(newDate()).UTC(hh,min,sec)
in order to fill in a chart with stored data, you may be able to send a post/get request to the ESP. something like sending a command to turn on a switch.
but, when you set the flag the ESP would open the spiff and read the last 20 saved data sets, then post one every second.
that would use the ESP in the same way this is being done for you now.
my need is for a garden temp , soil, rain. so I only want one reading a day.
Dave, that is a good idea. Should work. Even nicer, I can use most of the code that I have already written. The only drawback to this approach that I can see is the limited life of EEPROM. That’s a lot of reading and writing. My weather station using Wview and a Raspberry PI uses a somewhat similar data structure. I have worn out a couple of uSDs.
That being said, I don’t have any better ideas.
Just occurred to me, If multiple points are sent then the data will also have to include the time and date. I can revise the sketch to create the three responses, temp, humidity and pressure..
Example, /temp could yield:
08/06/2019, 08:09, 78.8
08/06/2019, 08:10, 78.7
08/06/2019, 08:11, 80.1
Now, does any one know how to revise index.html to work with that data and is what I wrote above the easiest format to work with?
in Every setInterval function, you will find this section
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
The value ‘x’, being the date. Instead of ‘getTime()), you need to supply the date that you save
Makes sense to me. Now to figure out how to make HighCharts plot a series.
For testing, I wrote:
String hTest = “38 50.3 30.3 28.5 50.5”;
server.on(“/humidity”, HTTP_GET, [](AsyncWebServerRequest * request) {
request->send_P(200, “text/plain”, hTest.c_str());
});
As I expected Highchart only display the first value, 38.
Try this: arduinodiy.wordpress.com/2019/08/05/esp8266-plot-sensor-readings-in-real-time-charts-on-a-web-server/
Thanks for this link, but going from this code to that, is not easy!
Thanks Ed. Now I am closer.
That example does not address retaining the data but it does describe how to encode the data in the sketch in the familiar JSON string and how to read it to generate multiple lines. In that it address bringing multiple point into HighCharts, that’s pretty close. I think, however, the JSON string would need to be brought into HighCharts as a Series so that an unknown number of points could be plotted.
This get me a bit closer but not all the way. I may have to read up on HighCharts. Sadly, I know a fair amount of C but not much Java Script.
Hello, I find many of your tutorials very useful.
I’m trying to modify this tutorial to work with an AD8232 Heart Rate Monitor and my ESP32. Before I tried to implement the web server, I was able to get the AD8232 working and displaying the output in the serial monitor and serial plotter. So I adjusted all of the Arduino code and the html file in this tutorial and was able to connect to the web server. The problem is that the graph only shows one value (4095).
Do you have any idea how to get the proper values to display?
Hi Warren.
What ADC pin are you using to get the Heart Rate?
When using Wi-Fi with the ESP32, you should use ADC1 pins. ADC2 pins won’t work with Wi-Fi.
That’s probably your issue.
Take a look at our ESP32 GPIO guide to learn more: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
Regards,
Sara
I am actually using ADC2 pins. I will reconfigure it and try again. Thank you very much for responding. I’ll post back and let you know if the issue is resolved.
Hello, so I changed the pins to ADC1 and that get the proper values showing. Thank you. Now, since it’s a heart rate monitor that I’m using, I need to increase the number of data points showing as well as increase the rate at which the data is displayed. I’ve tried changing the polling interval in the index.html file, but the rate of display hasn’t changed. Also, I thought I knew which line to change the number of data points shown, but when I changed it
(if(chartH.series[0].data.length > 40),
nothing much happened. Can you point me in the right direction to do those two things, please,
Does anyone know how to change the script to plot the first reading immediately on load and then after every 30 seconds.
It would be nice to be able to plot the first reading immediately, if you increase the time interval to more than 30 sec.
Hope someone can show this in code.
If anyone is interested, I have solved my problem plotting the first reading immediately on load and then after every 30 seconds, by adding this on top of the new chart section. without //
// var myVar = setInterval(myTimer, 1000);
// function myTimer() {
// var xhttp = new XMLHttpRequest();
// xhttp.onreadystatechange = function() {
// if (this.readyState == 4 && this.status == 200) {
// var x = (new Date()).getTime(),
// y = parseFloat(this.responseText);
// //console.log(this.responseText);
// chartT.series[0].addPoint([x, y], true, false, true);
// }
// };
// xhttp.open(“GET”, “/temperature”, true);
// xhttp.send();
// clearInterval(myVar);
//};
Jørgen B
here is the code for the three readouts if anyone has trouble implementing it in the code.
And of course you have to keep the original set interval functions.
// var myVar = setInterval(myTimer, 1000);
// function myTimer() {
// var xhttp = new XMLHttpRequest();
// xhttp.onreadystatechange = function() {
// if (this.readyState == 4 && this.status == 200) {
// var x = (new Date()).getTime(),
// y = parseFloat(this.responseText);
// //console.log(this.responseText);
// chartT.series[0].addPoint([x, y], true, false, true);
//
// }
// };
// xhttp.open(“GET”, “/temperature”, true);
// xhttp.send();
//
// var xhttp = new XMLHttpRequest();
// xhttp.onreadystatechange = function() {
// if (this.readyState == 4 && this.status == 200) {
// var x = (new Date()).getTime(),
// y = parseFloat(this.responseText);
// //console.log(this.responseText);
// chartH.series[0].addPoint([x, y], true, false, true);
//
// }
// };
// xhttp.open(“GET”, “/humidity”, true);
// xhttp.send();
//
// var xhttp = new XMLHttpRequest();
// xhttp.onreadystatechange = function() {
// if (this.readyState == 4 && this.status == 200) {
// var x = (new Date()).getTime(),
// y = parseFloat(this.responseText);
// //console.log(this.responseText);
// chartP.series[0].addPoint([x, y], true, false, true);
//
// }
// };
// xhttp.open(“GET”, “/pressure”, true);
// xhttp.send(); clearInterval(myVar);
// clearInterval(myVar);
// };
Correction: There is no need for the second clearInterval (myVar); at the end of the code. sorry.
Jørgen B.
This is a better way to get first reading immediately, the first time you are loading the page.
var myFnc = function() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/temperature”, true);
xhttp.send();
}
setInterval(myFnc, 30000);
myFnc();
var myFnc = function() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/humidity”, true);
xhttp.send();
}
setInterval(myFnc, 30000);
myFnc();
var myFnc = function() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartP.series[0].data.length > 40) {
chartP.series[0].addPoint([x, y], true, true, true);
} else {
chartP.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/pressure”, true);
xhttp.send();
}
setInterval(myFnc, 30000);
myFnc();
Graph not appearing when trying to access from another computer? Only the main title is showed but not the graph
What happens in your Arduino IDE serial monitor? Is the other computer in the same local network?
Found the problem issue, it is due to my router wasnt connected to the internet. Anyone know how to download the highcharts library into the arduino? Otherwise it wouldnt work without internet connection
go to the website https://code.highcharts.com/highcharts.js
copy the text to a textfile and name it highcharts.js..
put that in data folder and upload to spiff…
change in html
http://highcharts.js <- now there is no url..
add handler to ino file done:
server.on(“/highcharts.js”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/highcharts.js”, “text/javascript”);
});
Hi Moes.
Thanks for answering this.
Regards,
Sara
Hello Moes!
I’ve done this steps, but I stiil get no information excep the header text!
In addition, my router doesn’t connect to the Internet.
The reading on /temperature URL is working, but just the graph is not showing up. It was actually working fine a few days ago and I dont remember changing anything in the code
Hello,
Thank you for sharing this very helpful post.
I tried to use the same code but for the DHT22 and it doesn’t work.
Could you help me ? I used this code:
(…)
Thank you very much !
Hi.
What do you mean by “it doesn’t work”?
What error messages do you get, if any?
Regards,
Sara
Hi.
I tried many times. I get no error messages. I just think that the functions to read temperature and humidity didn’t start. On the serial monitor, the last thing printed is the IP adress. No error.
Could you help me ? I used a DHT22 and I want to plot the temperature and humidity.
Thanks a lot for your help and have a nice day.
Best regards
Hi.
That could be something to do with the sensor.
You can read this post and see if it helps: https://randomnerdtutorials.com/solved-dht11-dht22-failed-to-read-from-dht-sensor/
Regards,
Sara
Is there already a solution for showing logged data?
Regards
Jan
check the ‘Beginners guide for ESP8266’ chapter 16.
I did not try it myself but I think that describes what you need tttapa.github.io/ESP8266/Chap16%20-%20Data%20Logging.html
Why do we need to leave the loop function empty?
You do not need to leave it empty, you can put anything in there that you like, you just do not need it for the described functionality in here.
In the setup() function you create the webpage. That page contains javascript. The javascript makes 30 sec calls to routines in your program file. That is all you ‘need’.
But if you want you could just read sensors in your loop and have the Javascript use those, there is just no need to do that
Dear Sara and Rui
Is there a way to implement the project without an internet access, I mean, the graphs entirely genereated on chip?
Best regards.
Carlos.
Hi Carlos.
This approach uses the highcharts library from the internet. So, I don’t think you can do this without internet access.
There should be another way to do that, but we don’t have any tutorial about it.
Regards,
Sara
Please read this comment from one of our readers. That should do the trick.
”
If anyone needs to run in access point mode, offline.
Then add this
/highcharts.js
to the index.html
and remove this
https://code.highcharts.com/highcharts.js
from the index.html
Download the highcharts.js file, and put it in the data folder, together with index html.
Remember to upload data to spiffs.
Add this to your sketch.
server.on(“/highcharts.js”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/highcharts.js”, “text/javascript”);
});
that’s how I did it, to make it work offline in access point mode.”
I hope this helps.
Regards,
Sara
Hey Sara!
It worked for me in offline mode
Regards
Hey Sara thank you for your tutorials!!
I have downloaded the highcharts zip file. But know i am unsure what i have to put in the data folder on spiffs.
Do you have any advice for me?
Thank you in andvance and best regards,
Fabian
check: https://tttapa.github.io/ESP8266/Chap16%20-%20Data%20Logging.html
that does ask for access to a time server, but you could replace that with an RTC and keep it all local.
A question: If I would like to host a JSON file that takes care of plotting the points on a graph and the arduino uses that instead of high charts, how would I do that? I am creating a project that is supposed to last a long time in a remote location and am worried that if for whatever reason high charts removes that JSON file from their server, then my project will stopping plotting points.
Hi. Vlad.
Please read this comment from one of our readers. That should do the trick.
”
If anyone needs to run in access point mode, offline.
Then add this
/highcharts.js
to the index.html
and remove this
https://code.highcharts.com/highcharts.js
from the index.html
Download the highcharts.js file, and put it in the data folder, together with index html.
Remember to upload data to spiffs.
Add this to your sketch.
server.on(“/highcharts.js”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/highcharts.js”, “text/javascript”);
});
that’s how I did it, to make it work offline in access point mode.”
I hope this helps.
Regards,
Sara
If anyone needs to run in access point mode, offline.
Then add this
/highcharts.js
to the index.html
and remove this
https://code.highcharts.com/highcharts.js
from the index.html
Download the highcharts.js file, and put it in the data folder, together with index html.
Remember to upload data to spiffs.
Add this to your sketch.
server.on(“/highcharts.js”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/highcharts.js”, “text/javascript”);
});
that’s how I did it, to make it work offline in access point mode.
Hi.
Thank you for sharing.
That’s something that we were looking for and many of our readers too.
Regards,
Sara
Hi I am posting it again.
I can see there is missing some of my text in my post.
Remove the slashes when inserting the code.
If anyone needs to run in access point mode, offline.
Then add this
// /highcharts.js
to the index.html
and remove this
//https://code.highcharts.com/highcharts.js
from the index.html
Download the highcharts.js file, and put it in the data folder, together with index html.
Remember to upload data to spiffs.
Add this to your sketch.
// server.on(“/highcharts.js”, HTTP_GET, [](AsyncWebServerRequest *request){
// request->send(SPIFFS, “/highcharts.js”, “text/javascript”);
// });
that’s how I did it, to make it work offline in access point mode.
Thanks this worked great, also nice to know this code will still run even when the Highcharts will stop.
Small note is that copy pasting your code resulted in bad ” and I had to replace them.
I can see that some of my text is still missing.
I don’t know if it is for security reasons that some of my text has been removed from my post.
I don’t know how to post my code to avoid some of the text being removed.
Can you help me solve this.
Regards, J. Bredahl.
Hi.
Some text is omitted for security reasons.
You can use pastebin to show your code.
However, I think it was posted correctly now.
Regards,
Sara
hi Sara.Thank you very much for your response.
I can see that some of my comment is still missing.
I hope your readers can figure out where to put the code and what to remove from the s c r i p t part in the index.html.
//src=”/highcharts.js
best regards to you
J. Bredahl.
Not sure I got this right. Tried following on the different replies and slashes, but all I get is a blank white screen when I connect to my ESP32… I loaded the large file in my data directory, and then to my SPIFFS, but still no go…Any ideas or a way you can post your complete code on get hub to eliminate the slashes // problem?
Hi.
You probably did not load the files correctly to the board.
When opening the web browser on the ESP32 IP address, open the javascript console and check if you have any errors.
Tell me what errors do you get.
Regards,
Sara
It was all syntax…
I made a github folder showing what worked for the info file and the html file. https://github.com/Travis-O-Weber/ESP32_Access_Point
Really appreciate the work you all do! Hope this helps others… Thank you
Thank you.
Can you double-check the link you shared?
I can’t open it.
Regards,
Sara
This link works
https://github.com/Travis-O-Weber/ESP32_Acces_Point.git
As my BME280 sometimes sends corrupted data, e.g.
temperature -280° or humidity 0% or 100% or pressure 0, all from my living-room, wich results in a nearly straight line with one or two spikes,
I added the following to avoid these spikes –
for the temperature:
if (t>50) {t = 20;
}
if (t98) {h = 50;
}
if (h<10) {h = 50;
}
for pressure:
if (p1200) {p = 1000;
}
To get a wide chart over about 30 hours, in the index.html file I changed
max-width: 1900px;
if(chartP.series[0].data.length > 180)
and interval to 600000 (= 10 min.)
For better overview I added to title: { text: “… Interval 10 min.”
For the time zone problem I added
Highcharts.setOptions({
global: {
useUTC: false
}
});
as Sara suggested in July. It works fine.
Regards,
Siegfried
Hi Sarah and Rui !
With your i2c scanner sketch, I find my BME280 at address x076. So far so good!
But with ESP_chart_web_server.ino I get this error message.
Could not find a valid BME280 sensor, check wiring!
Problem with Adafruit_BME280 library (not used by i2c scanner) ? I am stuck…
I use an ESP32
Alain
Hi Sarah and Rui !
With your i2c scanner sketch, I find my BME280 at address x076. So far so good!
But with ESP_chart_web_server.ino I get this error message.
Could not find a valid BME280 sensor, check wiring!
Problem with Adafruit_BME280 library (not used by i2c scanner) ? I am stuck…
I use an ESP32
Alain
same problem with a ESP8266
Alain
Try Changing the address to x077
I really love this tutorial! I made a PID slowcooker!
I know there is also a slow-cooker version. but that was not for the esp32 version, and rewriting it was way to difficult!
This one I understand and now can mostly modify it myself.
I just have issues with the Highchart, was someone able to add the lines into one graph?
I would like to add the setpoint to the graph.
var value1 = ;
var value2 = ;
var value3 = ;
var reading_time = ;
window.addEventListener(‘load’, reading_time);
// Create Temperature Chart
var chartT = new Highcharts.Chart({
chart:{
renderTo:’chart-temperature’
},
series: [
{
name: ‘Temperature’,
type: ‘line’, animation: {duration: 5000},
color: ‘red’,
data:value1,
dataLabels: { enabled: true },
marker: {
symbol: ‘circle’,
radius: 3,
fillColor: ‘#101D42’,
}
},
{
name: ‘Himidity’,
type: ‘line’, animation: {duration: 5000},
color: ‘blue’,
data:value2,
dataLabels: { enabled: true },
marker: {
symbol: ‘square’,
radius: 3,
fillColor: ‘#00A6A6’,
}
},
{
name: ‘Pressure’,
type: ‘line’, animation: {duration: 5000},
color: ‘lightblue’,
data:value3,
dataLabels: { enabled: true },
marker: {
symbol: ‘triangle’,
radius: 3,
fillColor: ‘#8B2635’,
}
},
],
title: {
text: undefined
},
xAxis: {
type: ‘reading_time’,
categories: reading_time
},
yAxis: {
title: {
text: ‘Temperature \u00B0C Humidity % Pressure hPa’
}
},
credits: {
enabled: false
}
});
//Plot temperature in the temperature chart
function plotTemperature(jsonValue) {
var keys = Object.keys(jsonValue);
console.log(keys);
console.log(keys.length);
for (var i = 0; i 40) {
chartT.series[i].addPoint([x, y], true, true, true);
} else {
chartT.series[i].addPoint([x, y], true, false, true);
}
}
}
// Function to get current readings on the webpage when it loads for the first time
function getReadings(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
console.log(myObj);
plotTemperature(myObj);
}
};
xhr.open(“GET”, “/readings”, true);
xhr.send();
}
if (!!window.EventSource) {
var source = new EventSource(‘/events’);
source.addEventListener(‘open’, function(e) {
console.log(“Events Connected”);
}, false);
source.addEventListener(‘error’, function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log(“Events Disconnected”);
}
}, false);
source.addEventListener(‘message’, function(e) {
console.log(“message”, e.data);
}, false);
source.addEventListener(‘new_readings’, function(e) {
console.log(“new_readings”, e.data);
var myObj = JSON.parse(e.data);
console.log(myObj);
plotTemperature(myObj);
}, false);
}
Thank you!!!
Excellent Tutorial, works great…Thank You.
Great! 🙂
Thank you for the tutorial!
How can i display the current temperature reading on the top if the chart updates?
Something just like:
Tempereature: 21°C
In html file it would be:
Temperature Celsius %TEMPERATUREC% °C
If you want to display the new temperature as soon as it “arrives”, I recommend using SSE (Server-Sent Events).
We’ll publish a tutorial about that soon. But, you can check the ESPAsyncWebServer Documentation: https://github.com/me-no-dev/ESPAsyncWebServer#async-event-source-plugin
Regards,
Sara
This is awesome and i love. were in lock down and the thermostat has broken so were having to manualy control the central heating, fortunately i have all the bits lying around here. what i dont have is the experience of coding html. im trying to splice this project in to this:
Input Data on HTML Form ESP32/ESP8266 Web Server using Arduino IDE
so we can set the temperature we want online. Its really not going well. I have figured out how to get the input boxes to display, but everything falls apart after that if i press submit. Has anyone done this? or know where i can find some code that will do it, im just bumbling around in the dark here trying not to break things.
Thanks
Hi Mike.
Maybe this project helps: https://randomnerdtutorials.com/esp32-esp8266-thermostat-web-server/
Regards,
Sara
Hi,
I had used Nodemcu instead of ESP8266. Everything is perfect also I could visualize the graph in the web server but that doesn’t print any output data on the Chart. It is still showing empty graph. please anybody have an idea about it? please help me to find out the solution for this problem.
Hello!
Thank you very much for the tutorial!
However, there’s been a few things that are still confusing me:
First of, you never declare any pins and you also only create a bme variable in your code, but don’t initialize it.
Since I only have a bmp280 and no bme280 yet, I’ve tweaked your code slightly by adding
#include <Adafruit_BMP280.h> to the imports and
Adafruit_BMP280 bme;
further below, commenting out the original lines for bme.
Compiling and uploading the code works, but throws the following exception:
17:31:38.454 -> ————— CUT HERE FOR EXCEPTION DECODER —————
17:31:38.454 ->
17:31:38.454 -> Soft WDT reset
17:31:38.454 ->
17:31:38.454 -> >>>stack>>>
17:31:38.454 ->
17:31:38.454 -> ctx: cont
17:31:38.454 -> sp: 3ffffde0 end: 3fffffc0 offset: 01a0
17:31:38.454 -> 3fffff80: 3fffdad0 3ffeec5c 3ffeec5c 40201430
17:31:38.454 -> 3fffff90: feefeffe feefeffe feefeffe feefeffe
17:31:38.454 -> 3fffffa0: 3fffdad0 00000000 3ffeed4c 40209eb0
17:31:38.454 -> 3fffffb0: feefeffe feefeffe 3ffe84f4 40100fb5
17:31:38.488 -> <<<stack<<<
17:31:38.488 ->
17:31:38.488 -> ————— CUT HERE FOR EXCEPTION DECODER —————
17:31:38.488 ->
17:31:38.488 -> ets Jan 8 2013,rst cause:2, boot mode:(3,6)
17:31:38.488 ->
17:31:38.488 -> load 0x4010f000, len 3664, room 16
17:31:38.488 -> tail 0
17:31:38.488 -> chksum 0xee
17:31:38.488 -> csum 0xee
17:31:38.523 -> v39c79d9b
17:31:38.523 -> ~ld
17:31:38.592 -> Could not find a valid BME280 sensor, check wiring!
I am quite confused how the code should ever work? Maybe I just misunderstood something, but I must say I find it somewhat weird that you’ve added pin declariations in your code, but commented it out without ever explaining why it’s there.
Also, my ESP8266 looks different than the one you’ve shown – it has less GPIOs. Why do you only use 2 of the 4 GPIOs from the BME?
I’d really appreciate an explanation, thanks again for the tutorial!
Best regards,
Stefan
Hi.
The pins declared are used for SPI communication. Because we are not using that communication protocol, we’re using I2C instead, we commented those lines. Those lines are in the code commented so that people can see how to use SPI if they wanted.
When you call Adafruit_BME280 bme; this creates an Adafruit_BME280 object called bme on the ESP32 default I2C pins (GPIO 21 and GPIO 22). This is how the library works.
I hope my explanation is clear.
Regards,
Sara
Hello!
Thank you very much for the explanation – after searching around a bit more I figured that it had something to do with that. I got it to work now 🙂
I have another question though if you don’t mind.
Is it possible to save and display more than 40 points?
Now bear with me, I already found someone else in the comments explaining how to do it. I noticed though, that the graphs are not saved anywhere, so if I refresh the site, I start with 0 dots on each graph.
How would I go on to write an algorithm that saves all of the data every few seconds and instead of calling for new input, the website just takes a, for example csv I’m generating on the Sketch-part of the programm and uses that to feed all the dots into the graph?
Best regards,
Stefan
Hello everyone,
First of all, I admire those tutorials which are very helpful,
However, I want to ask for help for my project.
I am working on a load detection algorithm so that I can display in real time the power consumption curve and the list of running equipments. If I am going to use ESP32 and the webserver where should I put my algorithm,
Thank you very much !
How do I change the time format to show 21:45 no seconds. Currently it is:
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
I have tried { minute: ‘%H:%M:’}
and
xAxis: { type: ‘datetime’,
labels: {
format: ‘{value:%Y-%b-%e %H:%M}’
}
Hi
is there any free host ?
how can I use sensor with analog read ?
instead of making a call to the BME, make a call to your analogRead
I want the Temperatur Chart to only show one decimal point, so in index.html i changed line 64 from y = parseFloat(this.responseText); to y = parseFloat(this.responseText).ToFixed(1);
But now the Temperature Chart stopped showing the numbers! How can change the code to only show one decimal point in Celsius degrees?
All right, i managed to change de decimals length by adding the format property in index.html, line 52:
plotOptions: {
line: { animation: false,
dataLabels: {
enabled: true,
format: ‘{y:.1f}’
}
},
series: { color: ‘#059e8a’ }
},
Plus i update the tooltip text to change this same format, by adding this in line 40:
tooltip: {
valueDecimals: 1,
pointFormat: ‘{point.y} °C’
},
But i think the highcharts can see the second decimal, because 31.4 and another 31.4 in the temperature chart are not in the same line!
Anyone knows how to send only one decimal to the chart, or to make the same number appears in the same line?
Hi Rui and Sara, I hope you are well.
If anyone is interested in having all three readings in
same chart container, window.
Here’s how I did it.
Highcharts.setOptions({
colors: [‘#059e8a’, ‘#5DADE2’, ‘#ED561B’]
});
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart = new Highcharts.Chart({
chart:{ renderTo : ‘chart-weather’,
},
tooltip: {
crosshairs: true,
shared: true,
},
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
credits: {
enabled: false
},
title: { text: ‘Weather data’,
margin: 0,
style: {
fontSize: ’15px’,
}
},
yAxis: [{
title: {
enabled:false,
text: ‘Temperature (Celsius)’,
}
},
{
opposite: true,
title: {
enabled:false,
text: 'Temperature (Celsius)',
}
},
{
opposite: true,
title: {
enabled:false,
text: 'Temperature (Celsius)',
}
}],
series: [
{
yAxis: 0,
// data: []
name: ‘Temperature’
},
{
yAxis: 1,
// data: []
name: ‘Humidity’,
marker: {
symbol: ’round’
}
},
{
yAxis: 2,
// data: []
name: ‘Pressure’,
marker: {
symbol: ’round’
}
}],
});
var myFnc = function() {
var time = (new Date()).getTime();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = time,
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chart.series[0].data.length > 40) {
chart.series[0].addPoint([x, y], true, true, true);
} else {
chart.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/temperature”, true);
xhttp.send();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = time,
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chart.series[1].data.length > 40) {
chart.series[1].addPoint([x, y], true, true, true);
} else {
chart.series[1].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/humidity”, true);
xhttp.send();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = time,
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chart.series[2].data.length > 40) {
chart.series[2].addPoint([x, y], true, true, true);
} else {
chart.series[2].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/pressure”, true);
xhttp.send();
}
setInterval(myFnc, 30000);
myFnc();
I forgot this line
<div id="chart-weather" class="chart-container"></div>
Hi there –
the arduino code part i am OK with, but would you mind helping with your mods to get all lines in one chart – where exactly does the section above paste in to the html file?
Thanks!
Hi EB .
Sorry for my late answer
hope this helps you
<div id="chart-weather" class="chart-container"></div>
<
script>
Highcharts.setOptions({
colors: [‘#059e8a’, ‘#5DADE2’, ‘#ED561B’],
exactly between the body tag and the script tag.
I can see that some text is omitted for security reasons.
so if you can’t make it work.
I can send you the code in an email.
I got it thank you, it was my misunderstanding of the LOCATION of that snippet 🙂
Thanks for helping.
These signs ’ are shown incorrectly .
you need to change them manually.
otherwise the code will not work.
I am interested in having all three readings in same chart container, window. But I am a very beginner in HTML,CSS and JS. My copy/paste makes error. If you can, Please help me with complete code for all lines in one chart.
This sign ’ and this sign ” are shown incorrectly .
you need to change them manually.
otherwise the code will not work.
ESP Weather Station
(…)
ESP Weather Station
after the above line
add this without the Quotes
”
“
Some text is omitted for security reasons
you will have to go back in my comments
where I write “I forgot this line”
and copy that line
and add it
between
ESP Weather Station
and the
Highcharts.setOptions
Hi.
If you want to share code, please share a link to github or pastebin, for example.
The formatting will be messed up and some lines may be omitted automatically.
Regards,
Sara
Hi.
You can also try to adapt this tutorial that displays all readings on the same chart.
Regards,
Sara
here is a link to the index file.
https://1drv.ms/u/s!AgJdN1PffFfFhZAnyaID9IAithL4Yg?e=cPr3kL
the link will be removed in a few days.
Great job, Rui and Sara.
I had a question: are the data, after each request / reading, written to the flash (….When it receives a request on the root URL, we send the HTML text that is saved in SPIFFS….)? If this is true, there is a usage limit, as the flash must accept around 100k burns, right?
I managed to fix my problem….
The text editor was saving the file as index.html.txt (with the .txt bit not displayed)
I had to run example SPIFFS sketch to see the file directory, and simply had to rename the file (using a line from the same SPIFFS sketch – It basically demonstrates name changes etc.)
How I narrowed it down to this before even scratching is the IP address followed by /temperature (yes I have slightly different variables due to using BME680), it would display temperature etc… only the root / would give 404, or calling for /index.html explicitly gives server error 500.
So if you can access the parameters directly, your problem like mine might be simply wrong name of file in SPIFFS.
Hi, Im running your code on ESP8266 and everything works fine. But I see one issue if I have no internet connection when using this line of code
https://code.highcharts.com/highcharts.js
Any idea how to modify the code in order to use downloaded .js files and not uploaded one on internet?
Hi great tutorial
I have added a ccs811 air quality sensor. Every thing is working fine if i replace the temperature and pessure graphic by the CO2 and VOC graphics respectively.
If for some reason, i try to add the new graphics instead ( a forth and a fifth graphic). I get the additional graphic frames but no data updates ???
Is there a limit to the number of graphics in the webpage or some details that i could have forgot ??
Hi.
I don’t think there is a limit of graphics.
You should have something wrong in your code.
Check that you are using the right events for the sensor readings and corresponding charts.
Regards,
Sara
How can l add the temperature value in this chart that is coming from another esp32 sender board? (Mesh)
Do you know how to change the theme of the chart to Dark theme?
Hi.
I think this will help you: https://www.highcharts.com/forum/viewtopic.php?t=43396
https://www.highcharts.com/docs/chart-design-and-style/themes
Regards,
Sara
You are very kind. Thank you!!
Hi, that is a great tutorial!
How can I use the plots with an accsess point on the esp8266? I want to use it in my sons school as an co2 warner. There is no wifi network. 🙁
Go through the comments, there is a solution for that described. It involves downloading the highcharts.js library, putting that in spiffs and making a few code alterations
Hello guys. Thanks for this great tutorial.
Everything working fine but I have some question.
My ESP8266 working for over 48 hours right now.
When I woke up and check my phone I can’t see any data. I have to wait until next data entry. But I like to see what happened last night.
I’m editing index.html to setup 20minutes for updates but when I close my browser or refresh it everything gone. I just see empty graphics not old data.
Hi.
This particular example doesn’t save the readings.
Old readings are lost when you close the browser.
If you want to permanently save your readings, it is better to save the readings on a file (in the filesystem or on an SD card) and then, load that file to build the charts.
Regards.
Sara
Well I don’t need 5 days old data. I just want to see last 40 entry.
for example my setup was 20 minutes. for temp & humidty. 5 minutes for pressure but when I closed my computer or change my phone screen all datas are gone.
will try another one I guess
That’s because the data is not being saved.
You can save the last data point in a moving array, for example.
Regards,
Sara
Does anyone know how to plot 2 or more lines in the same chart.
I have 3 temp. probes in my garden. at different heights.
check: https://arduinodiy.wordpress.com/2019/08/05/esp8266-plot-sensor-readings-in-real-time-charts-on-a-web-server/
Is there a Micropython equivalent of this guide? Or any guide for plotting ESP readings to a phone?
Hi.
We have this tutorial: https://randomnerdtutorials.com/micropython-bme280-esp32-esp8266/
Displays sensor readings on a web page using a table (not charts)
You can see all our free MicroPython projects here: https://randomnerdtutorials.com/projects-esp32-esp8266-micropython/
Regards,
Sara
Thank you for the reply.
It should work with all those suggestions.
Amazing tutorial.
You think it would be possible for 2 ESP32s to post to one database? And then have 6 charts instead of 3?
In this case is it enough if I change the location value in one of them?
Do I need 2 users? Or 2 API keys?
Hi, so I wanted to ask about the high chart function that makes the height of the graph change. For example, when you have a reading that’s abnormally high the whole graph gets taller. Is there any way to set your graph to always be at a certain height? (Like 100 max)
Hi.
Yes.
You can edit the axis properties with a certain maximum and minimum value.
You can use the floor and ceiling properties to set a minimum and a maximum: https://api.highcharts.com/highcharts/yAxis
For example, the yAxis would look like this if you wanted a minimum of 0 and a maximum of 100:
yAxis: {
floor: 0,
ceiling: 100,
title: { text: 'Temperature (Celsius)' }
//title: { text: 'Temperature (Fahrenheit)' }
},
I hope this helps.
Regards,
Sara
Please Can I get code Using LDR light sensor. I dont have BME sensor and incooperating code for light is a bit difficult
Hey!
Great Project, funcionality is perfect.
Is there a way to save the Sensordata to an Excel sheet?
Best regards
Niklas
Hi.
We have this tutorial that shows how to save data to google sheets.
Regards,
Sara
So let’s say i want to update the readings of temperature at an interval of 10sec and humidity at 30 seconds then how do i do that
Hi.
You need to have different timers.
Alternatively, you can use the TaskScheduler library to do different tasks at different time intervals.
https://github.com/arkhipenko/TaskScheduler
Regards,
Sara
Hello, I need your help please. I am making a similar project, a battery monitor that can send data from esp8266 to graph on my phone – all without internet. Can you point me in the right direction?
Hi.
You can set the ESP8266 via access point: https://randomnerdtutorials.com/esp8266-nodemcu-access-point-ap-web-server/
Regards,
Sara
Sara
I don’t think highcharts can function without access to the internet. I have tried:
src=”/highcharts.js”>
and
src=”/js/highcharts.js”>
both result in the same issue.
Hi.
Yes, you are right. It won’t work without access to the internet unless you load the library to a microSD card or to the filesystem and then, serve the library file when the board receives a request.
Regards,
Sara
Sara
Interestingly, I was able to get the Highcharts to work offline using my laptop after I downloaded the jquery script and added /jquery.min.js to the index.html page.
However the same page will not load on my phone. Perhaps a mobile version of query will help, I shall try that.
Hello,
I am working on a similar project where the server is offline. Did you manage to get the charts working on a phone? If so, how?
Thanks
Alex
No I am still battling with this.
Save file highcharts.js to your server and add path to your code where the file is located on your server…
Hi thank for the tutorial.
I encountered a problem when i followed the tutorial. It says error compiling for DOIT ESP32 DEVKITV1. Is there any problems with the libraries like ESP32AsyncWebServer.h and AsyncTCP.h and SPIFFS.h ?
Hi.
What’s exactly the error?
Have you installed all the required libraries?
Regards,
Sara
Hi!! great tutorial!! Is there any easy way to store historical data on SPIFFS (let’s say the 10 last measurements) and load them each time the website is requested?
Hi.
Yes.
That is possible.
We have a project like that in our “Build Web Servers with ESP32 and ESP8266” course: https://randomnerdtutorials.com/build-web-servers-esp32-esp8266-ebook/
We don’t have any similar free projects published on our website.
Regards,
Sara
Oi Sara!! Parabéns pelo projeto. Eu consegui com 1 sensor bme280. Você conseguiria me ajudar a colocar 2x bme280 para fazer a leitura? O que preciso modificar no código?
Obrigado,
Mateus
Olá.
Terá que ter diferentes variáveis para guardar os resultados das leituras do segundo sensor.
Tem também de criar dois charts na página de HTML.
Para aprender a ler dois sensores em simultâneo, recomendo dar uma olhadela nestet tutorial: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
Tem uma secção que mostra como ler dois BME280.
Cumprimentos,
Sara
Hi.
Thank you for this tutorial Rui and Sara.
Setting chart timezone.
For those who wonder (as I did), where to put the before mentioned configuration script in order to change chart time zone correct. Here is the answer.
Open index.html file and add text after tag.
<
script>
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chartT = new Highcharts.Chart({
Now you have correct time (your computer system time) in your charts.
Hi! I substract a value of the variable x
var x = ((new Date()).getTime() – 10800000),
My time zone is -3h transform in 3000
3000 * 60 * 60 = 10800000
A Macgyver solution kkkkk
Hey, really useful tutorial. Saving me hours of time.
By the way, it looks like this entire webpage is being ripped off here:
XXXXXXXXXXXXXXXXXXXXXXX
It looks like someone that’s trying to plagiarize by rewriting some text around and redrawing the graphs. But the code is basically the same, and the whole flow is as well.
Hi.
That website plagiarizes almost all our tutorials.
It’s really annoying, but there’s nothing we can do about it.
I hope people can tell the difference and understand that ours are the original tutorials.
Thanks for telling us.
Regards,
Sara
As seen on random nerd tutorials –
thanks to Rui & Sara Santos. I left all your credentials in the code.
https://randomnerdtutorials.com/esp32-esp8266-plot-chart-web-server/
I just added security, logging, registering new user, pagination system, live searcher for database, php file to change room temperature for cron job. Results sent on two email adresses. One treshold is set in php file (email 1) other one thru website php page (email 2)…
Supreme work Rui & Sara. I hope you don’t mind for tweeking your code
javascript file is only edited to set the time zone gmt+2.
Hi.
Thank you for sharing.
Your project looks great!
Keep up the good work.
Regards,
Sara
can you please share your codes!!!!!!!!
As seen on random nerd tutorials – randomnerdtutorials.com
thanks to Rui & Sara Santos. I left all your credentials in the code. I strongly recommend your website and knowledge to anyone… Everyone… =)
I just added security as you mentioned on your channel and website it is recommended to add some kind of security. So i added logging, registering new user, added pagination system for database, live searcher for database – search by ***… Also added php file to change room temperature. Results sent on two email adresses. One treshold is set in php file (email 1 – set to 45 degrees celsius – urgent – trigger whatever with cron) other one thru website php page (email 2)… Third action is added through cron job (cron job checks every minute if treshold is reached) and accordingly triggers relay (second microcontroller), which turns on big fan in room. As long as tempreture treshold is reached fan is turned on otherwise cron job turns off the fan.
Thank you so very much and keep up with great even Supreme work. 😉
and my link on utube
Thank you so much.
I liked your video.
Regards,
Sara
Hello Robert! Care to share your code with us?
Hi! Thanks for the best project of ESP WebServer of the internet!
If is not much, you can help me to make the graphic no resize de axis Y? I have show a scale 0 to 10 always.
Hi.
You can see here how to set axis range: https://www.chartjs.org/docs/latest/axes/#axis-range-settings
I hope this helps.
Regards,
Sara
I love your tutorials! Question: what would I change to remove the value of the reading from being plotted on the chart? I want to be able to hover and see that data still, just not have any text on the point otherwise. Thx!
Answered my question: dataLabels: { enabled: false}
Hi! I love this code. I am using it in my thesis about energy consumption and protection. I would like to make 2 plotlines in the chart, to set maximum and minimum values. I did it manually in HTML code, but I would like to transfer the variable of maximum and minimum to HTML automatically as we do with the readings.
Sorry, but my knowledge about HTML and Jave Script is inverse of my knowledge about c++.
var chartH = new Highcharts.Chart({
chart:{ renderTo:’chart-corrente’ },
title: { text: ‘Corrente em Amperes’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
}
},
xAxis: {
type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Corrente’ },
plotLines: [{
value: “0”,
color: ‘green’,
dashStyle: ‘shortdash’,
width: 2,
label: {
text: ‘Corrente minima’
}
}, {
value: “1.0”, //<== I would like to put “correnteMax” varieble here.
color: ‘red’,
dashStyle: ‘shortdash’,
width: 2,
label: {
text: ‘Corrente maxima’
}
}]
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/corrente”, true);
xhttp.send();
}, 1000 ) ;
// I tried to make this code to read the variable, but don’t work.
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var correnteMax = parseFloat(this.responseText);
}
};
xhttp.open(“GET”, “/correnteMax”, true);
xhttp.send();
}, 1000 ) ;
Thank you for the wonderful tutorial, it was really helpful. I have modified the codes a bit so that I display values from the dht11 and soil moisture sensor. The code is compiling but whenever I access the web server so that I can view the charts the esp8266 gets into a continuous loop/ continuously restarts. I get the following error in the serial monitor : ets Jan 8 2013, rst cause: 2, boot mode: (3,6) and this followed by a very long code which comprises of
what I think are addresses. May you please kindly assist, what could be the problem?
Hi.
I’m not sure, but it’s probably because of the following:
That’s because you can’t pass the function to read the DHT on the send() method. I guess you’ve changed the readBME280Temperature() function to get the DHT temperature.
The DHT is a slow sensor and it has a delay() in its method to get the temperature. So, instead of passing that function, you should get the readings in the loop() every X number of seconds (the number of seconds that is more suitable for you) and save them in variables, for example, temp and hum.
Then, use those variables in the send() method. For example:
Like it’s done in this tutorial: https://randomnerdtutorials.com/esp8266-dht11dht22-temperature-and-humidity-web-server-with-arduino-ide/
I hope this helps.
Regards,
Sara
Thank you, I will give it a try.
This fixed the problem, thank you so much.
Great!
Good day, I was about to use it to monitor my sensor’s data. I’m planning to leave my prototype overnight then check the previous record data in the morning. But I noticed that when the webserver being refresh, the previous data that has been plotted will vanish.
Is it possible in this project of yours that even I refresh the webserver the previous data will still be there?
Hello Rui and Sara, I hope you are doing well!
First off, I want to say thanks so much for uploading your tutorials – they have been of great help to myself and everyone else here.
I’m trying to get the multiple graphs working. I am using a DS18b20 sensor and am successfully able to load the HTML code to SPIFFS and can visualize this single graph in real-time. But just now I have tried to add a second graph (readings from an ADS1115 converter) and have tried for hours but cannot get these readings to plot. BUT: The values are indeed being read and updated by the HTML or ESP32 code (I’m not sure exactly which does this) which can be seen when I go to the corresponding “/ads” URL.
Do you have any ideas? Thanks so much!
Hi.
Without checking the code, it is very difficult to find out what might be wrong.
If you want, share your code using a link to github gist or pastebin, for example.
Regards,
Sara
I want to plot second sensor data on x axis… Instate of time… Like voltage vs current graph….. Please help me to modify html file…
Hi.
You need to create multiple series in the chart.
Then add the data to the corresponding series.
See how that works with this example: https://randomnerdtutorials.com/esp32-plot-readings-charts-multiple/
Regards,
Sara
Hi, I have a problem regarding multiple clients accessing the IP Adress to view the charts, All charts works fine on all of the clients but they do not display the same readings, What I wanted was, what is seen on one client it is also seen on the other clients. THank you very much!
Hi! Is it possible to do this same tutorial but with websockets?
Yes.
Check all our projects related to websocket: https://randomnerdtutorials.com/?s=websocket
Regards,
Sara
Excellent stepping stone for my project. Thank you.
I’ve downloaded highcharts.js and uploaded it to the Flash using LittleFS.
I would like to change the line:
https://code.highcharts.com/highcharts.js
so that I can access it locally on the ESP8266.
I’ve tried everything like
http://highcharts.js
/data/highcharts.js
/highcharts.js
It works with
script src=”https://code.highcharts.com/highcharts.js”>
anything else, and I get this error:
Loading failed for the with source “http://192.168.1.55/highcharts.js”.
Can I use this file from local storage? How?
Thanks.
Hi Mai. I was also unable to use a local copy of highcharts.js despite trying all the suggests made in comments on this tutorial webpage and verifying that the file was stored in the SPIFFS of my ESP8266.
What finally worked for me was to modify the sketch C code so that it explicitly served the highcharts.js file when requested. The code snippet to do that is pasted here : https://pastebin.com/DmtWwByM
First, thank you for a great tutorial.
I have a problem running this without ESP8266 crashing.
I’ve located the error to be these 2 lines.
server.on(“/temperature”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, readBMPTemperature().c_str());
});
server.on(“/pressure”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, readBMPPressure().c_str());
});
If I comment them out, no crash and I get the index.html showing up (no data of course) !
I have removed Humidity portions since I’m using a BMP180 and have also removed humidity from index.html. So to only process Temperature and Pressure.
I’ve tried everything I can think of and don’t know what else to try.
Tested every other part of the code, including values returned and they all works.
For example;
String readBMPTemperature() {
// Read temperature as Celsius (the default)
//T = bmp.readTemperature(); commented out
//T is declared as float globally.
T=random(10,30);
return String(T);
}
Plots the random points!
!!! H E L P !!!
Hi.
Save the readings on a global variable and get the readings on the loop().
Then, instead of calling the function readBMPPressure() inside the server.on(), you’ll use the variable value.
Regards,
Sara
After days of trying to figure out what is wrong, I find that request->send_P(200, “text/plain”, readBMPPressure().c_str()); is not valid. This function does not accept a function call.
I had to read the Temperature and pressure in the loop section into global variables, then pass the string of the number to request->send_P
But you knew that, and didn’t bother updating your page.
The code the way it is, will not work for anyone.
Thanks for wasting days of my life. I was going to buy your ESP webserver book, but I’m glad I didn’t. It too is probably full of errors.
Hi. I’m sorry for that issue.
The code works fine as it is, with the BME280 sensor.
However, if you’re using another sensor, depending on the library you’re using, you might need to get the readings on the loop() as I suggested.
I guess you’re not using the BME280 sensor (because you changed the name of the function).
Regards,
Sara
Hi there,
Thank you for the great tutorial! I am always learning new things from your website tutorial!
But I have a question to ask, seem like this graph can only be visualised when there is internet, it there by any chance I could do it with access point?
If so can you guide me with similar post so I could understand and work on it!
Thank you
Hi.
Read Harvey’s comments.
He explains how he did it.
Let me know if you need further help.
Regards,
Sara
Hi Sara!
Thank you! i managed to make it work offline! But i meet with a problem is that when the data reached the end of the graph, the data is not displaying anymore, it just showed a full graph, is this normal?
thanks!
What do you mean?
Older readings are replaced with newer readings is the normal behavior of this example.
Regards,
Sara
hi sara,
What i mean is that data was displaying perfectly until it reaches a point the data is not displaying anymore. For eg, it only manage to log the data from 19:34 to 19:36 and then I stopped right there
thanks!
Hello rosey! Would you care to share your code with us?
Hello Rui and Sara,
Thank you for the useful tutorial!
My project have been modified from your materials to my project about Pets water bowl
and release to github (https://github.com/jasonbirdd/ESP32_pet_water_bowl).
If there is any problem that offend you, please let me know and I will deal with it as soon as possible.
Thanks a lot for the great tutorial again!
That’s a very interesting project.
Thanks for sharing.
It’s interesting that you’re sharing this right now as we are currently preparing a tutorial about load cells. Your project is a great application of how they can be used.
Regards,
Sara
I’ve got this working with a radiation detector.
However, I am storing the time/date and other data, on to a SPIFFS file, every 10 minutes.
Is there a way to draw the graph on previous data, every time the browser opens?
The way it is, the chart will chart, only if the browser stays open.
40 samples per chart is good enough for me.
Is there a way to process the array of records like these;
typedef struct {
int lcnt;
String ltime;
String temp;
String pres;
unsigned short radcount;
} record_type;
record_type sensor_data[record_size]; // Define the data array
I’ve tried ESP32WebServer library to see if it works. It does, but unfortunately it doesn’t play well with AsynWebServer, AsynTCP and ElegentOTA libraries. I assume conflict of port 80.
Any guidance would be greatly appreciated.
Hi Sara, I have tried to make a fourth graph, but I have had problems, can you help me.
Hi.
What is exaclty the problem?
Regards,
Sara
Hi Sara !!
Your tutorial is phenomenal!!
I think of making an asynchronous server like the one shown in this tutorial and at the same time I want to save the data on a micro sd, I wanted to ask if there would be any interference between the server that contains the graphics and the NTP server since I want to save the data data with the time in which they were recorded in the micro sd.
Hi.
I think you can use both without problem.
Regards,
Sara
Hi Sara !
I have made my code and I have my page working and saving data but without the time on the microSD, that is why I wanted to see if you send me your email and so I can share my code with you to see what my mistake is, please.
Hello friends, I have a problem with the time of the graph.
Despite adding the lines,
//Highcharts.setOptions({
//global: {
//useUTC:false
//}
//});
due to the summer time change, there is 1 hour difference to the real one. how can I solve it ?
Hi.
I think this is your issue: https://www.highcharts.com/forum/viewtopic.php?t=31279
Regards,
Sara
Hello,
How do i upload the index.html file by hand in the new arduino ide 2.0.3? I am not eable to find the “ESP32/ESP8266 Data Sketch Upload”-Button.
Hi.
That functionality is not yet supported on Arduino 2.0.
You can either use Arduino 1.8 with the SPIFFS or LittleFS plugin:
– https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/
– https://randomnerdtutorials.com/install-esp8266-nodemcu-littlefs-arduino/
Or use VS Code instead:
– https://randomnerdtutorials.com/esp32-vs-code-platformio-spiffs/
– https://randomnerdtutorials.com/esp8266-nodemcu-vs-code-platformio-littlefs/
Or you can upload files via the command line (we don’t have instructions for that at the moment).
Regards,
Sara
Hello. The code works great, but I want it to always work without having the browser open. how do i do it
Hi.
You can save the values (timestamp and reading) in a JSON file in the ESP filesystem or on a microSD card and then load all the points when you open the web browser.
Unfortunately, at the moment, we don’t have any tutorials showing that specific scenario.
But, you should look for how to save and load data from a file.
Regards,
Sara
Hello, great tutorial! Is there any way to decrease the time data updates? Maybe to see the charts update by second or less? I’m asking this so I don’t use a websocket server for my project, thanks!!
What a great tutorial! Thank you.
I have the code that calculates the number of ticks produced by a GM radiation tube.
I therefore don’t need the setInterval(function ( ) ) since it will read at wrong times.
How do I pass a number to the chart. Basically the same as what goes on inside each setInterval(function ( )) but without the timer part.
I’ve tried this instead of setInterval();
function updateTicks( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(), y = parseFloat(this.responseText);
console.log(“ticks:”);
console.log(this.responseText);
if(chartT.series[0].data.length > 60) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
}
/*added this to the setup /
source.addEventListener(‘ticks’, function(e) {
console.log(“ticks”, e.data);
update_ticks();
}, false);
There must be a way that I could pass real-time data to the charts plotter as they come it.
Please help if you know how. The charts docs are very cryptic and hard to understand.
Hi.
For that scenario, please follow this tutorial instead and adapt for your sensor:
https://randomnerdtutorials.com/esp32-plot-readings-charts-multiple/
You are an angel. That’s what I needed. Will give it a go.
There are a lot of improvements that can be done.. for example you can easily combine the readings data in one single request instead to have multiple endpoints, even better, use WebSockets instead of Ajax so it’s the server that send the data to client = less network overhead and more responsive updates. Also it’s better to include all the files (js/css) in your LittleFS (SPIFFS is deprecated) so it can work without any internet connection.
Hi.
Thanks for your feedback.
Yes. I know, our most recent tutorials (like the ones in the Web Servers eBook), already use those improvements.
We’ll also have to update the tutorials in our website.
Regards,
Sara
Thank you so much for this project guide.
I’d like to also have a line on the server where it shows us the max pressure so fsr and im struggling to do so. could you help me by any chance?
Hey there,
do you know a way where i could save the data from the weather station to txt or excel format. thank you
Hey, this is really cool! I’m just getting started with web servers and sensors, and I was wondering if you could explain a bit more about the BME280 sensor. What exactly does it do?
Hi.
For an introduction to the BME280 sensor with the ESP32/EPS8266, you can check the following tutorials:
– https://randomnerdtutorials.com/esp32-bme280-arduino-ide-pressure-temperature-humidity/
– https://randomnerdtutorials.com/esp8266-bme280-arduino-ide/
Regards,
Sara
Hey! You have a typo in your Project!
https://randomnerdtutorials.com/esp32-esp8266-plot-chart-web-server/#:~:text=Then%2C%20the-,setInvertal(),-function%20adds%20points
setInvertal()→setInterval()
Hi.
Thanks.
It’s fixed now.
Regards,
Sara
Hello,
I have tried following every step in this tutorial and can’t seem to get the code working. I ahve two issues.
The first issue is with the <LittleFS.h> library. In Step 3, you don’t include this library as one to download, implying that it already comes with the standard Arduino library package, but that is not the case for me. I have Arduino version 2.3.2. I found a <LittleFS.h> library on GitHub from author earlephilhower, but it doesn’t seem to work. I also noticed that in your YouTube video you don’t include <LittleFS.h>, but in the code you do. Can you give me any advice on where I can find a <LittleFS.h> library that works?
The second issue is with the Filesystem uploader. I get a message “ERROR: No filesystem specified, check flash size menu”. Do you know why this is happening?
Thanks,
Denis
Hi.
The LittleFS library is installed by default.
Make sure you have the latest version of the ESP32 boards installed in your Arduino IDE and that you have an ESP32 board selected in Tools > Board before compiling the code.
Regards,
Sara