In this tutorial, we will learn to create a DS18B20 web server using ESP32 and Arduino IDE. DS18B20 is used to measure temperature in Celsius and temperature in Fahrenheit. This web server will act as a weather station as it will show temperature readings in Celsius and Fahrenheit on the web page. The DS18B20 sensors readings will update automatically on a web page. Because we will build a web server using Server-Sent Events (SSE) and an asynchronous web server library. The ESP Async Web Server library is pretty straightforward to build asynchronous web servers. The device which wants to access sensor readings should be connected to the same network to which the ESP32 board is connected.
We will use Arduino IDE to build a responsive EP32 web server that can be accessed through any device which has a web browser, and the ESP32 should be connected to your local area network. That means the mobile or computer should be connected to the same network to which the ESP32 board is connected.
We have a similar guide for ESP32 with MicroPython firmware:
MicroPython: DS18B20 Web Server with ESP32/ESP8266(Weather Station)
Prerequisites
Before we start this lesson make sure you are familiar with and have the latest version of Arduino IDE installed and also have ESP32 add-on installed in Arduino IDE:
Install ESP32 add-on in Arduino IDE
ESP32 DS18B20 Web Server Introduction
Have you ever seen a remote monitoring system where an HMI-based system displays remote sensor values? Did you ever try to make a web server that can control or display the values of different sensors on your local server?
If yes, then this tutorial is a getting started step by step guide for you. We will learn the example of interfacing DS18B20 temperature sensor with ESP32 and how to display temperature, readings on the web server.
- The client starts the server-sent events connection with ESP32 server as an HTTP request. This will cause the ESP32 server to send events to the web page.
- ESP32 connected with DS18B20 receives sensor readings after every 3 seconds.
- These readings are marked as ‘events’ of the following names: ‘temperature_Celsius’, and ‘temperature_Fahrenheit’.
- These events sent by ESP32 have event listeners associated with them on the client-side. All the updated readings are received by the client on the said events.
- As in the case with SSE, only the ESP32 server will be able to send events to the webpage. The web page gets updated accordingly and the process continues.
DS18B20 Introduction
DS18B20 is a temperature sensor that is single wire programmable in nature. It is widely used to measure the temperature of chemical solutions and substances which are present in a hard environment. One of the advantages of using this sensor is that we only require a single pin of our ESP boards to transfer data. Thus, it is extremely convenient to use with the micro-controller as we can measure multiple temperatures by using the least number of pins on our development board.
The table below shows some key characteristics of the ds18b120 sensor.
Feature | Value |
---|---|
Operating Voltage | 3-5V |
Temperature Range | -55°C to +125°C |
Accuracy | ±0.5°C |
Output Resolution | 9-12 bit |
Pinout Diagram
A waterproof version of this sensor is also available in the market. The following figures show the pinout of the DS18B20 sensors.
The following diagram shows the pinout of the normal DS18B20 temperature sensor.
The table below lists the pin configurations:
Pin | Description |
---|---|
VCC | This is the pin that powers up the sensor. It is 3.3V for ESP boards. |
Data | This pin gives the temperature reading. |
Ground | This pin is connected with the ground |
This temperature sensor also comes in a single package module which contains a sensor and a pull-up resistor. If you are using a module, you do not need to connect an external 4.7K ohm resistor. This is because the module already has an onboard pull-up resistor.
You can have a look at articles related to DS18B20 by accessing the links below:
- MicroPython: DS18B20 Web Server with ESP32/ESP8266(Weather Station)
- DS18B20 Temperature Module interfacing with arduino
Installing DS18B20 Web Server Required Arduino Libraries
We will use Arduino IDE to program our ESP32 development board. Thus, you should have the latest version of Arduino IDE. Additionally, you also need to install the ESP32 plugin.
If your IDE does not have the plugin installed you can visit the link below: Installing ESP32 library in Arduino IDE and upload code.
Installing DS18B20 Libraries
To use the Dallas DS18B20 sensor we will have to install two libraries.
- OneWire library
- DallasTemperature library
Follow the steps below to successfully install them. We will use the Library Manager in our Arduino IDE to install the latest versions of the libraries. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type each library name in the search bar and install them both.
Installing ESPAsyncWebServer Libraries
The ESPAsyncWebServer library will help us in creating our web server easily. With this library, we will set an asynchronous HTTP server. AsyncTCP is another library that we will be incorporating as a dependency for the ESPAsyncWebServer library. This library will not be used directly inside our program code and only acts as the base for the first library.
Both of these libraries are not available in the Arduino library manager so we will have to download and load them in the IDE ourselves. We will use GitHub to download the respective libraries and then place them in the library folder of our Arduino IDE.
Click ESPAsyncWebServer library and AsyncTCP library to open the respective GitHub pages for the libraries. The webpage when you open the ESPAsyncWeb Server link will look something like this.
Click the Code button and go to the Download Zip option as highlighted in the figure. Your zip file will get downloaded to your computer right away. After the download is complete, extract the .zip file to the Arduino library folder. A similar process will apply to the installation of the AsyncTCP library as well. Make sure you rename the extracted files as ESPAsyncWebServer and AsyncTCP accordingly.
You can also go to Sketch > Include Library > Add .zip Library inside the IDE to add the libraries as well. Through this procedure now we will be able to use the functionalities of the libraries inside our Arduino IDE.
After installation of the libraries, restart your IDE.
ESP32 DS18B20 Web Server Circuit diagram
The connection of DS18B20 with the ESP32 boards is very simple. The DS18B20 sensor can be powered in two different modes.
- Normal Mode: The sensor is powered through an external source through the VDD pin and 4.7K ohm pull-up resistor.
- Parasite Mode: The sensor obtains power from its own data line. Hence, no external power supply is required.
For this article, we will power the sensor in the normal mode. Thus, we have to connect the VCC terminal with 3.3V, ground with the ground (common ground), and the data pin of the sensor with an appropriate GPIO pin of ESP32 via a pull-up resistor.
Required Components
- ESP32
- DS18B20 sensor
- 4.7k ohm resistor
- Breadboard
- Connecting Wires
ESP32 with DS18B20 Schematic Diagram
As you can see in the schematic diagram below, we have used DS10B20 in normal mode and powered the sensor with its VCC pin from the 3.3V pin of ESP32 board. Connect ESP32 device with DS18B20 as shown in the schematic diagram below:
As you can see above, we have powered the sensor using the normal mode. The DS18B20 sensor has three terminals which we saw above in the pinout. The first terminal is grounded with the ESP32 board. The data line of the sensor, which is the middle terminal, is connected through GPIO14 through a pull-up resistor of 4.7k-ohm. You can choose any other GPIO pin as well. The third terminal is powered by 3.3V from the ESP board.
You may like to read this in-depth guide on DS18B20 interfacing with ESP32:
Single and Multiple DS18B20 with ESP32: Display Readings on OLED
ESP32 DS18B20 Web Server Arduino Code
Copy the following sketch and replace the wifi credentials with your own.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
// Replace with your network credentials
const char* ssid = "Enter Your WiFi Name";
const char* password = "Enter your WiFi Password";
const int SensorDataPin = 14;
OneWire oneWire(SensorDataPin);
DallasTemperature sensors(&oneWire);
float temperature_Celsius;
float temperature_Fahrenheit;
AsyncWebServer server(80);
AsyncEventSource events("/events");
unsigned long lastTime = 0;
unsigned long timerDelay = 30000; // send readings timer
void getDS18B20Readings(){
sensors.requestTemperatures();
temperature_Celsius = sensors.getTempCByIndex(0);
temperature_Fahrenheit = sensors.getTempFByIndex(0);
}
String processor(const String& var){
getDS18B20Readings();
//Serial.println(var);
if(var == "TEMPERATURE_C"){
return String(temperature_Celsius);
}\
else if(var == "TEMPERATURE_F"){
return String(temperature_Fahrenheit);
}
}
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>DS18B20 Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
p { font-size: 1.2rem;}
body { margin: 0;}
.topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }
.content { padding: 20px; }
.card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
.cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.reading { font-size: 2.8rem; }
.card.temperature { color: #0e7c7b; }
</style>
</head>
<body>
<div class="topnav">
<h3>DS18B20 WEB SERVER</h3>
</div>
<div class="content">
<div class="cards">
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_celcius">%TEMPERATURE_C%</span> °C</span></p>
</div>
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_fahrenheit">%TEMPERATURE_F%</span> °F</span></p>
</div>
</div>
</div>
<script>
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('temperature_Celsius', function(e) {
console.log("temperature", e.data);
document.getElementById("temp_celcius").innerHTML = e.data;
}, false);
source.addEventListener('temperature_Fahrenheit', function(e) {
console.log("temperature", e.data);
document.getElementById("temp_fahrenheit").innerHTML = e.data;
}, false);
}
</script>
</body>
</html>)rawliteral";
void setup() {
Serial.begin(115200);
// Set the device as a Station and Soft Access Point simultaneously
//WiFi.mode(WIFI_AP_STA);
// Set device as a Wi-Fi Station
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Setting as a Wi-Fi Station..");
}
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.println();
// Handle Web Server
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Handle Web Server Events
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis
// and set reconnect delay to 1 second
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
server.begin();
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
getDS18B20Readings();
Serial.printf("Temperature = %.2f ºC \n", temperature_Celsius);
Serial.printf("Temperature = %.2f ºF \n", temperature_Fahrenheit);
Serial.println();
// Send Events to the Web Server with the Sensor Readings
events.send("ping",NULL,millis());
events.send(String(temperature_Celsius).c_str(),"temperature_Celsius",millis());
events.send(String(temperature_Fahrenheit).c_str(),"temperature_Fahrenheit",millis());
lastTime = millis();
}
}
How does the Code Works?
We will include all the necessary libraries e.g., OneWire.h, and DallasTemperature.h. Additionally, the WiFi.h and the ESPAsyncWebServer.h libraries are included to connect to router and create an asynchronous web server, respectively.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
We will specify our network credentials through which ESP32 will connect to WiFi router. The WiFi name and password will be saved in character variables named ssid and password. Make sure to replace the credentials with the ones for your router local network.
// Change according to your network credentials
const char* ssid = "Enter your WiFi name here";
const char* password = "Enter your WiFi password";
Secondly, we will create a variable to store the GPIO pin through which the sensor’s data pin is connected. We have used GPIO14 in this example.
const int SensorDataPin = 14;
We will require the following instances as well to access the temperature readings. First, we will create a oneWire instance and use the SensorDataPin as an argument inside it. Then we will call the DallasTemperature sensor and pass the oneWire reference which we created above as an argument inside it.
OneWire oneWire(SensorDataPin);
DallasTemperature sensors(&oneWire);
Next, we will declare variables to hold DS18B20 sensor temperature in celsius and Fahrenheit. These are declared as floating types because we will be dealing with numerical values which could have floating decimal points. In other words, the values returned by the DS18B20 sensor library are floating-point values.
float temperature_Celsius;
float temperature_Fahrenheit;
Here, we define two variables lastTime and timerDelay. We will include a delay of 3000ms or 3 seconds before updating the sensor readings to the DS18B20 web server page. The updating time is being stored in the variable ‘timerDelay.’
unsigned long lastTime = 0;
unsigned long timerDelay = 3000; // send readings timer
Create Server Sent Event Source
After that, we will create an object of the class AsyncWebServer. This will help us in the setup of the server routes. We have assigned it a port 80 which is the HTTP default port.
AsyncWebServer server(80);
As mentioned earlier, We will use Server-Sent Events known as SSE to update new sensor readings automatically from the DS18B20 web server and display them on the web page. We will create a new event source on /events. The Server-Sent Events (SSE) will update sensor reading automatically whenever a new reading is available without the need to refresh the web browser page.
AsyncEventSource events("/events");
Get DS18B20 Sensor Readings
Next, we will use obtain the sensor data for temperature, humidity, and pressure by using the getDS18B20Readings() function.
void getDS18B20Readings(){
sensors.requestTemperatures();
temperature_Celsius = sensors.getTempCByIndex(0);
temperature_Fahrenheit = sensors.getTempFByIndex(0);
}
HTML Placeholders Replacement Function
We will also create a processor() function. This function will take care of the placeholders inside the HTML text by setting them up for the current sensor readings. Until the next set of readings come up, the current sensor readings will be displayed on the web page through this function.
String processor(const String& var){
getDS18B20Readings();
//Serial.println(var);
if(var == "TEMPERATURE_C"){
return String(temperature_Celsius);
}\
else if(var == "TEMPERATURE_F"){
return String(temperature_Fahrenheit);
}
}
HTML and CSS File
In this HTML document, we use cards, paragraphs, links, icons, headings, and title tags to create a web page. This web page displays temperature readings of the DS18B20 sensor.
On a web page, we display icons of temperature from the Font Awesome Icons website. To create a font, we will use the fontawesome.com website. Go to this link (fontawesome). You should include the following line in your HTML document to use icons from fontawesome:
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
To create the web page, we will use index_html. To handle the events sent by the web browser client, we will use the following code for each sensor reading. Below is the example code for the line which displays the temperature readings in celsius units.
<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_celcius">%TEMPERATURE_C%</span> °C</span></p>
In this case, we are using the id temp_celcius to update new sensor readings regarding temperature in Celcius. For temperature in Fahrenheit variables, we are using the id temp_fahrenheit. This id describes which CSS style to apply to each reading and also JavaScript code uses this id to access and change elements related to that id.
Handle Server Events
To handle events, we will initialize a new object of EventSource called /events.
if (!!window.EventSource) {
var source = new EventSource('/events');
After initializing the server events, we will listen to all the messages received from the server through addEventListener(). In this block of code, we are creating addEventListener for open, error, and message. These event listeners are set in default as mentioned in the AsyncWebServer documentation.
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);
Now, to create an addEventListener for the DS18B20 sensor readings. For example, for temperature in Celcius, we will add the event listener with the name of temperature_Celsius. This will send this event to the web page whenever a new reading will be accessible.
source.addEventListener('temperature_Celsius', function(e)
Inside the function, the following lines send the new temperature(Celsius) readings event to the web browser client whenever the new value of temperature is available. This temperature(Celsius) reading is related to the id temp_celcius.
{
console.log("temperature", e.data);
document.getElementById("temp_celcius").innerHTML = e.data;
}, false);
Likewise, the same addEventListener() function will be defined for temperature in Fahrenheit with its respective ID.
source.addEventListener('temperature_Fahrenheit', function(e) {
console.log("temperature", e.data);
document.getElementById("temp_fahrenheit").innerHTML = e.data;
}, false);
setup() Function
In the setup() function, we will first initiate the serial communication with the serial monitor with a baud rate of 115200 by using the begin() function.
Serial.begin(115200);
By using the WiFi.begin() function, the ESP32 will connect to the local network with the given network credentials as parameters. This will then print the IP address which is assigned to ESP32 and we will use this IP address to access the web server later.
// Set the device as a Station and Soft Access Point simultaneously
WiFi.mode(WIFI_AP_STA);
// Set device as a Wi-Fi Station
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Setting as a Wi-Fi Station..");
}
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.println();
Handle Clients Requests
When a user accesses the web page with an ESP32 IP address on the root / URL ESP32 serve will respond with the data stored inside index_html. The processor will be one of the arguments so that new sensor readings are updated and replaced with placeholders.
// Handle Web Server
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
Server Event Source
This block of code will create the event source on the server.
// Handle Web Server Events
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis
// and set reconnect delay to 1 second
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
By using the server.begin() function, we will start the server.
server.begin();
In loop(), we will obtain the new readings from the DS18B20 sensor by using the getDS18B20Readings() function. These will then be displayed in the serial monitor through their respective variables.
getDS18B20Readings();
Serial.printf("Temperature = %.2f ºC \n", temperature_Celsius);
Serial.printf("Temperature = %.2f ºF \n", temperature_Fahrenheit);
Serial.println();
These updated readings will be sent to the web page through events.send
/ Send Events to the Web Server with the Sensor Readings
events.send("ping",NULL,millis());
events.send(String(temperature_Celsius).c_str(),"temperature_Celsius",millis());
events.send(String(temperature_Fahrenheit).c_str(),"temperature_Fahrenheit",millis());
Demonstration
Copy the above code to Arduino IDE. Choose the correct board and COM port before uploading your code to the ESP32 board. Go to Tools > Board and select ESP32 Dev Module.
Next, go to Tools > Port and select the appropriate port through which your board is connected.
Now click on the upload button to upload code to ESP32. After that open the Arduino serial monitor and press the enable button on ESP32:
You will receive the IP address of the ESP32 development board printed on your serial monitor. Copy that address and paste it into a new browser window. Press Enter. The web server will display sensor readings for temperature, pressure, humidity, and gas which will be updated by new ones after every 3 seconds.
If you access the web server from your mobile device, you will see the DS18B20 reading as follows:
In this guide, we have learned how to build a DS18B20 web server with ESP32 and Arduino IDE and how to display the sensor readings on a web page using an asynchronous server sent events web server. Additionally, new sensor readings will be updated automatically.
You may like to read ESP32 web server tutorials with other sensors:
- BME280 Web Server with ESP32 (Arduino IDE)
- Plot Sensor Readings in Real Time Charts with ESP32 and ESP8266 Web Server
- ESP32/ESP8266 Thermostat Web Server
- MicroPython: BME680 Web Server with ESP32
- LM35 Temperature Sensor with ESP32 – Web Server
- MicroPython: BME280 Web Server with ESP32/ESP8266
- ESP32 BMP180 Web Server using Arduino IDE
- MicroPython: DS18B20 Web Server with ESP32/ESP8266
- Interface DHT11/DHT22 with ESP32 and display values on Web Server
- MicroPython: DHT11/DHT22 Web Server with ESP32/ESP8266
Hi there,
nice walkthrough. One remark, the code does not work as intended. There is one statement missing:
sensors.begin();
For a strange reason I had to add this two more lines:
delay(5000);
sensors.begin();
Otherwise I kept only seeing the following temperature in Celsius degrees: -127
Which in turn is an error code for the DS18B20: “-127C indicates that either the sensor is not properly connected or you aren’t using the library properly”.
Do you have an idea why?
Best regards, Pedro
We did not face any issue when we were created demo for this article, we will check it again.