{"id":87332,"date":"2019-07-19T13:32:52","date_gmt":"2019-07-19T13:32:52","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=87332"},"modified":"2025-03-17T12:26:28","modified_gmt":"2025-03-17T12:26:28","slug":"esp32-esp8266-plot-chart-web-server","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-esp8266-plot-chart-web-server\/","title":{"rendered":"ESP32\/ESP8266 Plot Sensor Readings in Real Time Charts &#8211; Web Server"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Plot Data Chart Web Server BME280 Temperautre Arduino IDE\" class=\"wp-image-87572\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>In this tutorial we&#8217;ll build an asynchronous web server using the <a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\">ESPAsyncWebServer library<\/a>. <\/p>\n\n\n\n<p>The HTML to build the web page will be stored on the ESP32 or ESP8266 Filesystem (LittleFS).<\/p>\n\n\n\n<p>We&#8217;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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\"><strong>ESP32 <\/strong>with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp8266-bme280-arduino-ide\/\"><strong>ESP8266 <\/strong>with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a> <\/li>\n<\/ul>\n\n\n\n<p>To build the charts, we&#8217;ll use the <a rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\" href=\"https:\/\/www.highcharts.com\/docs\/\" target=\"_blank\">Highcharts library<\/a>. We&#8217;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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Watch the Video Demonstration<\/h3>\n\n\n\n<p>To see how the project works, you can watch the following video demonstration:<\/p>\n\n\n<p style=\"text-align:center\"><iframe width=\"720\" height=\"405\" src=\"https:\/\/www.youtube.com\/embed\/1TGuw-cSR_I?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Make sure you check all the prerequisites in this section before continuing with the project in order to compile the code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Install ESP Board in Arduino IDE<\/h3>\n\n\n\n<p>We&#8217;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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp8266-nodemcu-arduino-ide-2-0\/\" title=\"\">Installing ESP8266 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Filesystem Uploader Plugin<\/h3>\n\n\n\n<p>To upload the HTML file to the ESP32 and ESP8266 flash memory, we\u2019ll use a plugin for Arduino IDE:&nbsp;<strong>Filesystem uploader<\/strong>. Follow one of the next tutorials to install the filesystem uploader plugin. The uploader is compatible with both boards.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp8266-littlefs\/\">Arduino IDE 2: Install <strong>ESP8266 <\/strong>NodeMCU LittleFS Uploader (Upload Files to the Filesystem)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp32-littlefs\/\">Arduino IDE 2: Install <strong>ESP32<\/strong> LittleFS Uploader (Upload Files to the Filesystem)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Installing Libraries<\/h3>\n\n\n\n<p>To build the web server you need to install the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ESP32:<\/strong>&nbsp;install the&nbsp;<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer<\/a> and the&nbsp;<a href=\"https:\/\/github.com\/ESP32Async\/AsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">AsyncTCP&nbsp;<\/a>libraries&nbsp;(by ESP32Async).<\/li>\n\n\n\n<li><strong>ESP8266:<\/strong>&nbsp;install the&nbsp;<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncWebServer<\/a>&nbsp;and the&nbsp;<a href=\"https:\/\/github.com\/ESP32Async\/ESPAsyncTCP\" target=\"_blank\" rel=\"noopener\" title=\"\">ESPAsyncTCP<\/a>&nbsp;libraries (by ESP32Async).<\/li>\n<\/ul>\n\n\n\n<p>You can install those libraries in the Arduino IDE Library Manager. Go to <strong>Sketch <\/strong>&gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong> and search for the libraries&#8217; names.<\/p>\n\n\n\n<p>To get readings from the BME280 sensor module you need to have the next libraries installed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/adafruit\/Adafruit_BME280_Library\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit BME280 library<\/a><\/li>\n\n\n\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/github.com\/adafruit\/Adafruit_Sensor\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit Unified Sensor library<\/a><\/li>\n<\/ul>\n\n\n\n<p>You can install these libraries through the Arduino Library Manager.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parts Required<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-BME280-circuit.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 wit BME280 sensor module temperature humidity pressure\" class=\"wp-image-86632\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-BME280-circuit.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-BME280-circuit.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>To follow this tutorial you need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32<\/a> or <a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/esp8266-esp-12e-nodemcu-wi-fi-development-board\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP8266<\/a> (read <a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/esp32-vs-esp8266\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 vs ESP8266<\/a>)<\/li>\n\n\n\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BME280 sensor<\/a><\/li>\n\n\n\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n<p>You can use the preceding links or go directly to <a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\">MakerAdvisor.com\/tools<\/a> to find all the parts for your projects at the best price!<\/p><p style=\"text-align:center;\"><a href=\"https:\/\/makeradvisor.com\/tools\/?utm_source=rnt&utm_medium=post&utm_campaign=post\" target=\"_blank\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2017\/10\/header-200.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\"><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Schematic Diagram<\/h2>\n\n\n\n<p>The BME280 sensor module we\u2019re using communicates via I2C communication protocol, so you need to connect it to the ESP32 or ESP8266 I2C pins.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">BME280 wiring to ESP32<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>BME280<\/strong><\/td><td><strong>ESP32<\/strong><\/td><\/tr><tr><td>SCK (SCL Pin)<\/td><td> <span class=\"rnthl rntcblue\">GPIO 22<\/span><\/td><\/tr><tr><td>SDI (SDA pin) <\/td><td> <span class=\"rnthl rntcgreen\">GPIO 21<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>So, assemble your circuit as shown in the next schematic diagram.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"652\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/03\/ESP32-bme280_bb.png?resize=750%2C652&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"BME280 Sensor Module wiring to ESP32 board\" class=\"wp-image-56623\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/03\/ESP32-bme280_bb.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/03\/ESP32-bme280_bb.png?resize=300%2C261&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\"><strong>Recommended reading:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 Pinout Reference Guide<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">BME280 wiring to ESP8266<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>BME280<\/strong><\/td><td><strong>ESP8266<\/strong><\/td><\/tr><tr><td>SCK (SCL Pin)<\/td><td> <span class=\"rnthl rntcyellow\">GPIO 5<\/span><\/td><\/tr><tr><td>SDI (SDA pin) <\/td><td> <span class=\"rnthl rntclgray\">GPIO 4<\/span><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Assemble your circuit as in the next schematic diagram if you&#8217;re using an ESP8266 board.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"705\" height=\"532\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP8266-BME280-Arduino-IDE.png?resize=705%2C532&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"BME280 Sensor Module wiring to ESP8266 board\" class=\"wp-image-85980\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP8266-BME280-Arduino-IDE.png?w=705&amp;quality=100&amp;strip=all&amp;ssl=1 705w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP8266-BME280-Arduino-IDE.png?resize=300%2C226&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 705px) 100vw, 705px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\"><strong>Recommended reading:<\/strong> <a href=\"https:\/\/randomnerdtutorials.com\/esp8266-pinout-reference-gpios\/\">ESP8266 Pinout Reference Guide<\/a> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Organizing your Files<\/h2>\n\n\n\n<p>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&nbsp;<em><strong>data<\/strong>&nbsp;<\/em>inside the Arduino sketch folder, as shown below:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"511\" height=\"358\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/folder-structure-1.png?resize=511%2C358&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"LittleFS Web Server to Display Charts File Organization\" class=\"wp-image-158912\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/folder-structure-1.png?w=511&amp;quality=100&amp;strip=all&amp;ssl=1 511w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/folder-structure-1.png?resize=300%2C210&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 511px) 100vw, 511px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Creating the HTML File<\/h2>\n\n\n\n<p>Create an&nbsp;<em>index.html<\/em>&nbsp;file with the following content or&nbsp;<strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Chart_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">download all project files here<\/a><\/strong>: <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!DOCTYPE HTML&gt;&lt;html&gt;\n&lt;!-- Rui Santos - Complete project details at https:\/\/RandomNerdTutorials.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files.\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software. --&gt;\n&lt;head&gt;\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;script src=&quot;https:\/\/code.highcharts.com\/highcharts.js&quot;&gt;&lt;\/script&gt;\n  &lt;style&gt;\n    body {\n      min-width: 310px;\n    \tmax-width: 800px;\n    \theight: 400px;\n      margin: 0 auto;\n    }\n    h2 {\n      font-family: Arial;\n      font-size: 2.5rem;\n      text-align: center;\n    }\n  &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h2&gt;ESP Weather Station&lt;\/h2&gt;\n  &lt;div id=&quot;chart-temperature&quot; class=&quot;container&quot;&gt;&lt;\/div&gt;\n  &lt;div id=&quot;chart-humidity&quot; class=&quot;container&quot;&gt;&lt;\/div&gt;\n  &lt;div id=&quot;chart-pressure&quot; class=&quot;container&quot;&gt;&lt;\/div&gt;\n&lt;\/body&gt;\n&lt;script&gt;\nvar chartT = new Highcharts.Chart({\n  chart:{ renderTo : 'chart-temperature' },\n  title: { text: 'BME280 Temperature' },\n  series: [{\n    showInLegend: false,\n    data: []\n  }],\n  plotOptions: {\n    line: { animation: false,\n      dataLabels: { enabled: true }\n    },\n    series: { color: '#059e8a' }\n  },\n  xAxis: { type: 'datetime',\n    dateTimeLabelFormats: { second: '%H:%M:%S' }\n  },\n  yAxis: {\n    title: { text: 'Temperature (Celsius)' }\n    \/\/title: { text: 'Temperature (Fahrenheit)' }\n  },\n  credits: { enabled: false }\n});\nsetInterval(function ( ) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 &amp;&amp; this.status == 200) {\n      var x = (new Date()).getTime(),\n          y = parseFloat(this.responseText);\n      \/\/console.log(this.responseText);\n      if(chartT.series[0].data.length &gt; 40) {\n        chartT.series[0].addPoint([x, y], true, true, true);\n      } else {\n        chartT.series[0].addPoint([x, y], true, false, true);\n      }\n    }\n  };\n  xhttp.open(&quot;GET&quot;, &quot;\/temperature&quot;, true);\n  xhttp.send();\n}, 30000 ) ;\n\nvar chartH = new Highcharts.Chart({\n  chart:{ renderTo:'chart-humidity' },\n  title: { text: 'BME280 Humidity' },\n  series: [{\n    showInLegend: false,\n    data: []\n  }],\n  plotOptions: {\n    line: { animation: false,\n      dataLabels: { enabled: true }\n    }\n  },\n  xAxis: {\n    type: 'datetime',\n    dateTimeLabelFormats: { second: '%H:%M:%S' }\n  },\n  yAxis: {\n    title: { text: 'Humidity (%)' }\n  },\n  credits: { enabled: false }\n});\nsetInterval(function ( ) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 &amp;&amp; this.status == 200) {\n      var x = (new Date()).getTime(),\n          y = parseFloat(this.responseText);\n      \/\/console.log(this.responseText);\n      if(chartH.series[0].data.length &gt; 40) {\n        chartH.series[0].addPoint([x, y], true, true, true);\n      } else {\n        chartH.series[0].addPoint([x, y], true, false, true);\n      }\n    }\n  };\n  xhttp.open(&quot;GET&quot;, &quot;\/humidity&quot;, true);\n  xhttp.send();\n}, 30000 ) ;\n\nvar chartP = new Highcharts.Chart({\n  chart:{ renderTo:'chart-pressure' },\n  title: { text: 'BME280 Pressure' },\n  series: [{\n    showInLegend: false,\n    data: []\n  }],\n  plotOptions: {\n    line: { animation: false,\n      dataLabels: { enabled: true }\n    },\n    series: { color: '#18009c' }\n  },\n  xAxis: {\n    type: 'datetime',\n    dateTimeLabelFormats: { second: '%H:%M:%S' }\n  },\n  yAxis: {\n    title: { text: 'Pressure (hPa)' }\n  },\n  credits: { enabled: false }\n});\nsetInterval(function ( ) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 &amp;&amp; this.status == 200) {\n      var x = (new Date()).getTime(),\n          y = parseFloat(this.responseText);\n      \/\/console.log(this.responseText);\n      if(chartP.series[0].data.length &gt; 40) {\n        chartP.series[0].addPoint([x, y], true, true, true);\n      } else {\n        chartP.series[0].addPoint([x, y], true, false, true);\n      }\n    }\n  };\n  xhttp.open(&quot;GET&quot;, &quot;\/pressure&quot;, true);\n  xhttp.send();\n}, 30000 ) ;\n&lt;\/script&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Chart_Web_Server\/data\/index.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Let&#8217;s take a quick look at the relevant parts to build a chart.<\/p>\n\n\n\n<p>First, you need to include the highcharts library:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;script src=\"https:\/\/code.highcharts.com\/highcharts.js\"&gt;&lt;\/script&gt;<\/code><\/pre>\n\n\n\n<p>You need to create a <span class=\"rnthl rntliteral\">&lt;div&gt;<\/span> section for each graphic with a unique id. In this case: <span class=\"rnthl rntliteral\">chart-temperature<\/span>, <span class=\"rnthl rntliteral\">chart-humidity<\/span> and <span class=\"rnthl rntliteral\">chart-pressure<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;div id=\"chart-temperature\" class=\"container\"&gt;&lt;\/div&gt;\n&lt;div id=\"chart-humidity\" class=\"container\"&gt;&lt;\/div&gt;\n&lt;div id=\"chart-pressure\" class=\"container\"&gt;&lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p>To create the charts and add data to the charts, we use javascript code. It should go inside the <span class=\"rnthl rntliteral\">&lt;script&gt;<\/span> and <span class=\"rnthl rntliteral\">&lt;\/script&gt;<\/span> tags.<\/p>\n\n\n\n<p>The following spinet creates the temperature chart. You define the chart id, you can set the title, the axis labels, etc&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>var chartT = new Highcharts.Chart({\n  chart:{ renderTo : 'chart-temperature' },\n  title: { text: 'BME280 Temperature' },\n  series: &#091;{\n    showInLegend: false,\n    data: &#091;]\n  }],\n  plotOptions: {\n    line: { animation: false,\n      dataLabels: { enabled: true }\n    },\n    series: { color: '#059e8a' }\n  },\n  xAxis: { type: 'datetime',\n    dateTimeLabelFormats: { second: '%H:%M:%S' }\n  },\n  yAxis: {\n    title: { text: 'Temperature (Celsius)' }\n    \/\/title: { text: 'Temperature (Fahrenheit)' }\n  },\n  credits: { enabled: false }\n});<\/code><\/pre>\n\n\n\n<p>Then, the <span class=\"rnthl rntliteral\">setInterval()<\/span> function adds points to the charts. Every 30 seconds it makes a request to the<em> \/temperature<\/em> URL to get the temperature readings from your ESP32 or ESP8266.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>setInterval(function ( ) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (this.readyState == 4 &amp;&amp; this.status == 200) {\n      var x = (new Date()).getTime(),\n          y = parseFloat(this.responseText);\n      \/\/console.log(this.responseText);\n      if(chartT.series&#091;0].data.length &gt; 40) {\n        chartT.series&#091;0].addPoint(&#091;x, y], true, true, true);\n      } else {\n        chartT.series&#091;0].addPoint(&#091;x, y], true, false, true);\n      }\n    }\n  };\n  xhttp.open(\"GET\", \"\/temperature\", true);\n  xhttp.send();\n}, 30000 ) ;<\/code><\/pre>\n\n\n\n<p>The other graphics are created in a similar way. We make a request on the <em>\/humidity<\/em> and <em>\/pressure<\/em> URLs to get the humidity and pressure readings, respectively.<\/p>\n\n\n\n<p>In the Arduino sketch, we should handle what happens when we receive those requests: we should send the corresponding sensor readings.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arduino Sketch<\/h2>\n\n\n\n<p>Copy the following code to the Arduino IDE or&nbsp;<strong><a href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Chart_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"download all project files here (opens in a new tab)\">download all project files here<\/a><\/strong>. Then, you need to type your network credentials (SSID and password) to make it work. <\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-esp8266-plot-chart-web-server\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*********\/\n#ifdef ESP32\n  #include &lt;WiFi.h&gt;\n  #include &lt;ESPAsyncWebServer.h&gt;\n  #include &lt;LittleFS.h&gt;\n#else\n  #include &lt;Arduino.h&gt;\n  #include &lt;ESP8266WiFi.h&gt;\n  #include &lt;Hash.h&gt;\n  #include &lt;ESPAsyncTCP.h&gt;\n  #include &lt;ESPAsyncWebServer.h&gt;\n  #include &lt;LittleFS.h&gt;\n  #include &lt;FS.h&gt;\n#endif\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n\n\/*#include &lt;SPI.h&gt;\n#define BME_SCK 18\n#define BME_MISO 19\n#define BME_MOSI 23\n#define BME_CS 5*\/\n\nAdafruit_BME280 bme; \/\/ I2C\n\/\/Adafruit_BME280 bme(BME_CS); \/\/ hardware SPI\n\/\/Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); \/\/ software SPI\n\n\/\/ Replace with your network credentials\nconst char* ssid = &quot;REPLACE_IWTH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_IWTH_YOUR_PASSWORD&quot;;\n\n\/\/ Create AsyncWebServer object on port 80\nAsyncWebServer server(80);\n\nString readBME280Temperature() {\n  \/\/ Read temperature as Celsius (the default)\n  float t = bme.readTemperature();\n  \/\/ Convert temperature to Fahrenheit\n  \/\/t = 1.8 * t + 32;\n  if (isnan(t)) {    \n    Serial.println(&quot;Failed to read from BME280 sensor!&quot;);\n    return &quot;&quot;;\n  }\n  else {\n    Serial.println(t);\n    return String(t);\n  }\n}\n\nString readBME280Humidity() {\n  float h = bme.readHumidity();\n  if (isnan(h)) {\n    Serial.println(&quot;Failed to read from BME280 sensor!&quot;);\n    return &quot;&quot;;\n  }\n  else {\n    Serial.println(h);\n    return String(h);\n  }\n}\n\nString readBME280Pressure() {\n  float p = bme.readPressure() \/ 100.0F;\n  if (isnan(p)) {\n    Serial.println(&quot;Failed to read from BME280 sensor!&quot;);\n    return &quot;&quot;;\n  }\n  else {\n    Serial.println(p);\n    return String(p);\n  }\n}\n\nvoid setup(){\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n  \n  bool status; \n  \/\/ default settings\n  \/\/ (you can also pass in a Wire library object like &amp;Wire2)\n  status = bme.begin(0x76);  \n  if (!status) {\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\n    while (1);\n  }\n\n  \/\/ Initialize LittleFS\n  if(!LittleFS.begin()){\n    Serial.println(&quot;An Error has occurred while mounting LittleFS&quot;);\n        return;\n  }\n\n  \/\/ Connect to Wi-Fi\n  WiFi.begin(ssid, password);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(1000);\n    Serial.println(&quot;Connecting to WiFi..&quot;);\n  }\n\n  \/\/ Print ESP32 Local IP Address\n  Serial.println(WiFi.localIP());\n\n  \/\/ Route for root \/ web page\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(LittleFS, &quot;\/index.html&quot;);\n  });\n  server.on(&quot;\/temperature&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, readBME280Temperature().c_str());\n  });\n  server.on(&quot;\/humidity&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, readBME280Humidity().c_str());\n  });\n  server.on(&quot;\/pressure&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/plain&quot;, readBME280Pressure().c_str());\n  });\n\n  \/\/ Start server\n  server.begin();\n}\n \nvoid loop(){\n  \n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Chart_Web_Server\/ESP_Chart_Web_Server.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the code works<\/h3>\n\n\n\n<p>Let&#8217;s take a quick look at the code and see how it works.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Including libraries<\/h4>\n\n\n\n<p>First, include the necessary libraries. You include different libraries depending on the board you&#8217;re using. If you&#8217;re using an ESP32, the code loads the following libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;WiFi.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n#include &lt;LittleFS.h&gt;<\/code><\/pre>\n\n\n\n<p>If you&#8217;re using an ESP8266, the code loads these libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Arduino.h&gt;\n#include &lt;ESP8266WiFi.h&gt;\n#include &lt;Hash.h&gt;\n#include &lt;ESPAsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n#include &lt;LittleFS.h&gt;\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;<\/code><\/pre>\n\n\n\n<p>Create an instance to communicate with the BME280 sensor using I2C:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_BME280 bme; \/\/ I2C<\/code><\/pre>\n\n\n\n<p>Insert your network credentials in the following variables:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Replace with your network credentials\nconst char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<p>Create <span class=\"rnthl rntliteral\">AsyncWebServer<\/span> object on port 80:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>AsyncWebServer server(80);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Read Temperature, Humidity and Pressure<\/h4>\n\n\n\n<p>Then, we create three functions <span class=\"rnthl rntliteral\">readBME280Temperature()<\/span>, <span class=\"rnthl rntliteral\">readBME280Humidity()<\/span> and <span class=\"rnthl rntliteral\">readBME280Pressure()<\/span>. These functions request the temperature, humidity and pressure from the BME280 sensor and return the readings as a String type.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String readBME280Temperature() {\n  \/\/ Read temperature as Celsius (the default)\n  float t = bme.readTemperature();\n  \/\/ Convert temperature to Fahrenheit\n  \/\/t = 1.8 * t + 32;\n  if (isnan(t)) {\n    Serial.println(\"Failed to read from BME280 sensor!\");\n    return \"\";\n  }\n  else {\n    Serial.println(t);\n    return String(t);\n  }\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Init BME280<\/h4>\n\n\n\n<p> In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the sensor:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>status = bme.begin(0x76);\nif (!status) {\n  Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Init LittleFS<\/h4>\n\n\n\n<p>Initialize the filesystem (LittleFS):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(!LittleFS.begin()){\n  Serial.println(\"An Error has occurred while mounting LittleFS\");\n  return;\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Connect to Wi-Fi<\/h4>\n\n\n\n<p>Connect to Wi-Fi and print the IP address in the Serial Monitor:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>WiFi.begin(ssid, password);\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(1000);\n  Serial.println(\"Connecting to WiFi..\");\n}\n\n\/\/ Print ESP32 Local IP Address\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Handle requests<\/h4>\n\n\n\n<p>Then, we need to handle what happens when the ESP receives a request.<\/p>\n\n\n\n<p>When it receives a request on the root URL, we send the HTML text that is saved in LittleFS under the <em>index.html<\/em> name:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send(LittleFS, \"\/index.html\");\n});<\/code><\/pre>\n\n\n\n<p>When we receive a request on the <em>\/temperature<\/em>, <em>\/humidity<\/em> or <em>\/pressure<\/em> URLs, call the functions that return the sensor readings.<\/p>\n\n\n\n<p>For example, if we receive a request on the <em>\/temperature<\/em> URL, we call the <span class=\"rnthl rntliteral\">readBME280Temperature()<\/span> function that returns the temperature.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/temperature\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send_P(200, \"text\/plain\", readBME280Temperature().c_str());\n});<\/code><\/pre>\n\n\n\n<p>The same happens for the other readings.<\/p>\n\n\n\n<p>Finally, start the server:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.begin();<\/code><\/pre>\n\n\n\n<p>Because this is an asynchronous web server we don&#8217;t need to write anything in the <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop(){\n\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Uploading Code and Files<\/h2>\n\n\n\n<p>Save the code as&nbsp;<em>ESP_Chart_Web_Server<\/em>&nbsp;or&nbsp;<a aria-label=\"download all project files here (opens in a new tab)\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP\/ESP_Chart_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">download all project files here<\/a>. Go to&nbsp;<strong>Sketch<\/strong>&nbsp;&gt;&nbsp;<strong>Show Sketch Folder<\/strong>, and create a folder called&nbsp;<strong>data<\/strong>. Inside that folder you should save the HTML file created previously.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"351\" height=\"271\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?resize=351%2C271&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE Open Sketch Folder to create data folder\" class=\"wp-image-158892\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?w=351&amp;quality=100&amp;strip=all&amp;ssl=1 351w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-show-sketch-folder.png?resize=300%2C232&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 351px) 100vw, 351px\" \/><\/figure><\/div>\n\n\n<p><strong>Now you need to upload the HTML file to the ESP32 or ESP8266 filesystem.<\/strong><\/p>\n\n\n\n<p>Press [<strong>Ctrl<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on Windows or [<strong>\u2318<\/strong>] + [<strong>Shift<\/strong>] + [<strong>P<\/strong>] on MacOS to open the command palette. Search for the&nbsp;<strong>Upload LittleFS to Pico\/ESP8266\/ESP32<\/strong>&nbsp;command and click on it.<\/p>\n\n\n\n<p>If you don\u2019t have this option is because you didn\u2019t install the filesystem uploader plugin.<a href=\"https:\/\/randomnerdtutorials.com\/arduino-ide-2-install-esp32-littlefs\/\">&nbsp;Check this tutorial<\/a>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"744\" height=\"401\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?resize=744%2C401&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32\/ESP8266 Data Sketch Upload filesystem Uploader \" class=\"wp-image-158893\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?w=744&amp;quality=100&amp;strip=all&amp;ssl=1 744w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/upload-files-little-fs-esp32-arduino-ide.png?resize=300%2C162&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 744px) 100vw, 744px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntcred\"><strong>Important:&nbsp;<\/strong>make sure the Serial Monitor is closed before uploading to the filesystem. Otherwise, the upload will fail.<\/p>\n\n\n\n<p>Then, upload the code to your board. Make sure you have the right board and COM port selected. Also, make sure you\u2019ve inserted your networks credentials in the code.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"36\" height=\"39\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?resize=36%2C39&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Upload Button\" class=\"wp-image-146269\"\/><\/a><\/figure><\/div>\n\n\n<p>When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the board \u201c<strong>EN\/RST<\/strong>\u201d button, and it should print its IP address.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"728\" height=\"413\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP-IP-address.png?resize=728%2C413&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 IP Address Serial Monitor\" class=\"wp-image-86414\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP-IP-address.png?w=728&amp;quality=100&amp;strip=all&amp;ssl=1 728w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/06\/ESP-IP-address.png?resize=300%2C170&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 728px) 100vw, 728px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Here is an example of the humidity chart:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 Chart Web Server BME280 Humidity Arduino IDE\" class=\"wp-image-87571\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>You can select each point to see the exact timestamp.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"376\" height=\"798\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?resize=376%2C798&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 ESP8266 BME280 Temperature Pressure Humidity Plot Sensor readings chart web server\" class=\"wp-image-87574\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?w=376&amp;quality=100&amp;strip=all&amp;ssl=1 376w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Humidity-Arduino-IDE.jpg?resize=141%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 141w\" sizes=\"(max-width: 376px) 100vw, 376px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial you&#8217;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.<\/p>\n\n\n\n<p>Next, we recommend building a project that <a href=\"https:\/\/randomnerdtutorials.com\/visualize-esp32-esp8266-sensor-readings-from-anywhere\/\">displays charts from data stored on your database<\/a>. Here are other tutorials that you might like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/visualize-esp32-esp8266-sensor-readings-from-anywhere\/\">Visualize Your ESP32\/ESP8266 Sensor Readings from Anywhere in the World<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-mysql-database-php\/\">ESP32\/ESP8266 Insert Data into MySQL Database using PHP and Arduino IDE<\/a><\/li>\n<\/ul>\n\n\n\n<p>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: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\" title=\"\">Build Web Servers with ESP32 and ESP8266 eBook<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 and ESP8266 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/home-automation-using-esp8266\/\" title=\"\">Home Automation Using ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/smart-home-ebook\/\">SMART HOME with Raspberry Pi, ESP32, and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266 (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">Free ESP32 Projects and Tutorials\u2026<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp8266\/\" title=\"\">Free ESP8266 Projects and Tutorials&#8230;<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thank you for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32\/ESP8266 Plot Sensor Readings in Real Time Charts &#8211; Web Server\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-plot-chart-web-server\/#more-87332\" aria-label=\"Read more about ESP32\/ESP8266 Plot Sensor Readings in Real Time Charts &#8211; Web Server\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":87572,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-87332","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2019\/07\/ESP32-ESP8266-Plot-Data-Chart-Web-Server-BME280-Temperautre-Arduino-IDE.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/87332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=87332"}],"version-history":[{"count":7,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/87332\/revisions"}],"predecessor-version":[{"id":168093,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/87332\/revisions\/168093"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/87572"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=87332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=87332"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=87332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}