Description
- In this guide, we will build a web server with the ESP32 to display temperature sensor readings on the analog gauge.
- We will use the DS18B20 temperature sensor as an example. It is a digital temperature sensor that measures temperature in the range of -55°C to 125°C
- To build the web server page we will use HTML, CSS, and Javascript programming languages.
- Here we will use the SPIFFS filesystem to save the HTML, CSS, and JavaScript files in a better-organized form and easier to understand.
DS18B20 Interfacing Diagram with ESP32
Install required libraries
First download and install the ESPAsyncWebServer library from the below link
https://github.com/me-no-dev/ESPAsyncWebServer
then download and install the AsyncTCP library from the below link
https://github.com/me-no-dev/AsyncTCP
and download and install the Arduino JSON library from the below link
https://github.com/arduino-libraries/Arduino_JSON
Download and extract the above library and add the folder to the libraries folder path of Arduino IDE.
For information about how to add a custom library to the Arduino IDE and use examples from it, refer to Adding Library To Arduino IDE in the Basics section.
Here we are using DallasTemperature libraries for the temperature measurement. We need to install the DallasTemperature library using the Arduino Library Manager.
- Open the Arduino IDE
- Navigate to Sketch ► Include Library ► Manage Libraries…
- The library Manager window will pop up. Now enter DS18B20 into the search box, and click Install on the DallasTemperature option to install version 3.9.0 or higher. As shown below image.
- If you don’t have the OneWire library, then this pop-up will come then click on Install all.
Files Organization
For web server building we need four different files. Arduino sketch, HTML file, CSS file, and javascript file Here we will save the HTML, CSS, and javascript files inside data folder and Arduino sketch in the Arduino folder, as shown below:
HTML File code
Create a index.html
file inside the data folder and paste the below code inside index.html
file
<!DOCTYPE html>
<html>
<head>
<title>ESP IOT DASHBOARD</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="http://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>
</head>
<body>
<div class="topnav">
<h1>ESP32 Temperature Gauge</h1>
</div>
<div class="content">
<div class="card-grid">
<div class="card">
<p class="card-title">DS18B20 Temperature gauge</p>
<canvas id="gauge-temperature"></canvas>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
let’s understand the code
All html pages start with the <!DOCTYPE html>
declaration, it is just information to the browser about what type of document is expected.
<!DOCTYPE html>
The html
tag is the container of the complete html page which represents on the top of the html code.
<html>
The below code snippet is sets up the viewport for the web page's display. It specifies a favicon, which is the icon displayed in the browser tab.
The CSS file provides access to font and icons properties. The stylesheet links a local CSS file called "style.css
" for styling the HTML document.
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
Here we have added a JavaScript file called "gauge.min.js
" from a CDN (Content Delivery Network). This file is used for creating and displaying gauge visualizations. The gauge.min.js file is retrieved from the specified URL and loaded into the web page for use.
<script src="http://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js"></script>
This is the HTML division element with the class name "topnav".
Inside the division, there is a heading level 1 (h1) element displaying the text "ESP32 Temperature Gauge".
This code is typically used to create a navigation bar or header section on a web page.
<div class="topnav">
<h1>ESP32 Temperature Gauge</h1>
</div>
The card contains a paragraph element with the class "card-title" displaying the text "DS18B20 Temperature gauge".
Here is a canvas element with the id "gauge-temperature
" used to create a card-based layout for displaying temperature gauge information on a web page.
<div class="content">
<div class="card-grid">
<div class="card">
<p class="card-title">DS18B20 Temperature gauge</p>
<canvas id="gauge-temperature"></canvas>
</div>
</div>
</div>
CSS File code
Create a style.css
file inside the data folder and paste the below code inside style.css
file
html {
font-family: Arial, Helvetica, sans-serif;
display: inline-block;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
p {
font-size: 1.4rem;
}
.topnav {
overflow: hidden;
background-color: #ff0000;
}
body {
margin: 0;
}
.content {
padding: 5%;
}
.card-grid {
max-width: 1200px;
margin: 0 auto;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
background-color: white;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}
.card-title {
font-size: 1.2rem;
font-weight: bold;
color: #ff0000;
}
Java Script File code
Create a script.js
file inside the data folder and paste the below code inside script.js
file
window.addEventListener('load', getReadings);
var gaugeTemp = new RadialGauge({
renderTo: 'gauge-temperature',
width: 300,
height: 300,
units: "Temperature (DegC)",
minValue: 0,
maxValue: 100,
colorValueBoxRect: "#ff0000",
colorValueBoxRectEnd: "#ff0000",
colorValueBoxBackground: "#ffffff",
valueInt: 2,
majorTicks: [
"0",
"10",
"20",
"30",
"40",
"50",
"60",
"70",
"80",
"90",
"100"
],
minorTicks: 4,
strokeTicks: true,
highlights: [
{
"from": 60,
"to": 100,
"color": "#ff0000"
}
],
colorPlate: "#ababab",
borderShadowWidth: 0,
borders: true,
needleType: "line",
colorNeedle: "#ff0000",
colorNeedleEnd: "#ff0000",
needleWidth: 1,
needleCircleSize: 4,
colorNeedleCircleOuter: "#ff0000",
needleCircleOuter: true,
needleCircleInner: false,
animationDuration: 1500,
animationRule: "linear"
}).draw();
// 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);
var temp = myObj.temperature;
gaugeTemp.value = temp;
}
};
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);
gaugeTemp.value = myObj.temperature;
}, false);
}
let’s understand the code
- The below function initializes a radial gauge using the RadialGauge library to render the element with the ID "
gauge-temperature
". - It has a width and height of 300 pixels and displays temperature values in degrees Celsius.
- The gauge has a minimum value of 0 and a maximum value of 100.
- The color of the value box is set to red, with a white background.
- Major ticks are displayed at intervals of 10, ranging from 0 to 100.
- There are 4 minor ticks between each major tick.
- The gauge has a highlighted range from 60 to 100, which is colored in red.
- The color plate is set to a light gray color.
- The needle type is set to a line, colored in red.
- The gauge has animation enabled with a duration of 1500 milliseconds and a linear animation rule.
var gaugeTemp = new RadialGauge({
renderTo: 'gauge-temperature',
width: 300,
height: 300,
units: "Temperature (DegC)",
minValue: 0,
maxValue: 100,
colorValueBoxRect: "#ff0000",
colorValueBoxRectEnd: "#ff0000",
colorValueBoxBackground: "#ffffff",
valueInt: 2,
majorTicks: [
"0",
"10",
"20",
"30",
"40",
"50",
"60",
"70",
"80",
"90",
"100"
],
minorTicks: 4,
strokeTicks: true,
highlights: [
{
"from": 60,
"to": 100,
"color": "#ff0000"
}
],
colorPlate: "#ababab",
borderShadowWidth: 0,
borders: true,
needleType: "line",
colorNeedle: "#ff0000",
colorNeedleEnd: "#ff0000",
needleWidth: 1,
needleCircleSize: 4,
colorNeedleCircleOuter: "#ff0000",
needleCircleOuter: true,
needleCircleInner: false,
animationDuration: 1500,
animationRule: "linear"
}).draw();
- The below function named
getReadings()
retrieves temperature readings from the server. - It creates a new
XMLHttpRequest
object to send an HTTP GET request to the "/readings
" endpoint. - When the response is received, if the request is successful (status code 200) and the response text is valid JSON, the code parses the JSON response and retrieves the temperature value.
- The temperature value is then assigned to the value property of the
gaugeTemp
object, updating the gauge display.
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);
var temp = myObj.temperature;
gaugeTemp.value = temp;
}
};
xhr.open("GET", "/readings", true);
xhr.send();
}
- The code checks if the browser supports
EventSource
, which is a mechanism for receiving server-sent events. If supported, it creates a new EventSource object connected to the "/events
" endpoint. - It adds event listeners for different events that can occur during the communication.
- When the 'open' event is triggered, it logs a message indicating that the connection to the server for events is established.
- If the 'error' event occurs and the readyState of the event target is not
EventSource.OPEN
, it logs a message indicating that the connection for events is disconnected. - The 'message' event listener logs the received message data.
- The 'new_readings' event listener is specific to a custom event named 'new_readings'.
- When this event is received, it logs the event data, parses it as JSON, and assigns the temperature value to the value property of the
gaugeTemp
object, updating the gauge display.
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);
gaugeTemp.value = myObj.temperature;
}, false);
}
Upload the Files using the Filesystem Uploader
To upload the files, in the Arduino IDE, you just need to go to Tools > ESP32 Sketch Data Upload.
Now upload the below code
Before uploading the code make sure you have added your SSID, and Password as follows.
const char* ssid = "*Your SSID*"; /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/
Analog Gauge code for ESP32 using Arduino ide
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Arduino_JSON.h>
#include "SPIFFS.h"
#include <OneWire.h>
#include <DallasTemperature.h>
const char* ssid = "SSID";
const char* password = "PASSWORD";
AsyncWebServer server(80);
AsyncEventSource events("/events");
JSONVar readings;
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
String getSensorReadings(){
sensors.requestTemperatures();
readings["temperature"] = String(sensors.getTempCByIndex(0));
String jsonString = JSON.stringify(readings);
return jsonString;
}
void initSPIFFS() {
if (!SPIFFS.begin()) {
Serial.println("An error has occurred while mounting SPIFFS");
}
Serial.println("SPIFFS mounted successfully");
}
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void setup() {
Serial.begin(115200);
pinMode (2, INPUT_PULLUP);
initWiFi();
initSPIFFS();
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
server.serveStatic("/", SPIFFS, "/");
server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
String json = getSensorReadings();
request->send(200, "application/json", json);
json = String();
});
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
sensors.begin();
server.begin();
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
events.send("ping",NULL,millis());
events.send(getSensorReadings().c_str(),"new_readings" ,millis());
lastTime = millis();
}
}
- Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
- After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image
- Now open any mobile browser and type the IP address which is shown in the serial monitor and hit the enter button.
- If all are ok, then the web page will start the showing current temperature on the web server like in the below image.
Note: make sure your ESP32 and mobile are connected to the same router/server, if they are connected to the same router or server then only you will be able to visible the web page.
let’s understand the code
Add the necessary libraries:
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Arduino_JSON.h>
#include "SPIFFS.h"
#include <OneWire.h>
#include <DallasTemperature.h>
set your wifi network credentials in the below:
const char* ssid = " SSID";
const char* password = " PASSWORD";
Set the pin number 2 for DS1307 of ESP32
#define ONE_WIRE_BUS 2
Setup a oneWire
instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
Pass oneWire
reference to DallasTemperature.
DallasTemperature sensors(&oneWire);
The below code function set the WiFi as an STA mode and connects to the given SSID and password after successfully connecting to the server print the local IP address on the serial window.
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
The getSensorReadings()
function gets the temperature sensor reading and saves it on the readings JSON array.
String getSensorReadings(){
sensors.requestTemperatures();
readings["temperature"] = String(sensors.getTempCByIndex(0));
String jsonString = JSON.stringify(readings);
return jsonString;
}
When you visit the IP address of the ESP32 on the main / URL, the content of the index.html
file is sent to create the web page. Additionally, any other requested static files such as style.css
and script.js
are served to the client.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});
server.serveStatic("/", SPIFFS, "/");
Now send JSON string with the updated temperature reading when request is receive a on the /readings URL.
server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
String json = getSensorReadings();
request->send(200, "application/json", json);
json = String();
});
Finally, start the server.
server.begin();
inside loop function
In the loop function, send events to the browser every 10 seconds with the latest sensor readings to update the web page.
events.send("ping",NULL,millis());
events.send(getSensorReadings().c_str(),"new_readings" ,millis());
events.send("ping",NULL,millis());
Components Used |
||
---|---|---|
ESP32 WROOM WiFi Development Tools - 802.11 ESP32 General Development Kit, embeds ESP32-WROOM-32E, 4MB flash. |
X 1 | |
DS18B20 Waterproof temperature sensor DS18B20 Waterproof temperature sensor |
X 1 |
Downloads |
||
---|---|---|
|
ESP32_analog_gauge | Download |