ESP32 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server)

This is a in-depth guide for the DS18B20 temperature sensor with ESP32 using Arduino IDE. We’ll show you how to wire the sensor, install the required libraries, and write the code to get the sensor readings from one and multiple sensors. Finally, we’ll build a simple web server to display the sensor readings.

ESP32 with DS18B20 Temperature Sensor using Arduino IDE

You might also like reading other DS18B20 guides:

Introducing DS18B20 Temperature Sensor

The DS18B20 temperature sensor is a one-wire digital temperature sensor. This means that it just requires one data line (and GND) to communicate with your ESP32.

It can be powered by an external power supply or it can derive power from the data line (called “parasite mode”), which eliminates the need for an external power supply.

DS18B20 Temperature Sensor Pinout Pins

Each DS18B20 temperature sensor has a unique 64-bit serial code. This allows you to wire multiple sensors to the same data wire. So, you can get temperature from multiple sensors using just one GPIO.

The DS18B20 temperature sensor is also available in waterproof version.

DS18B20 Temperature Sensor Waterproof version

Here’s a summary of the most relevant specs of the DS18B20 temperature sensor:

  • Communicates over one-wire bus communication
  • Power supply range: 3.0V to 5.5V
  • Operating temperature range: -55ºC to +125ºC
  • Accuracy +/-0.5 ºC (between the range -10ºC to 85ºC)

For more information consult the DS18B20 datasheet.

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 – ESP32

As mentioned previously, the DS18B20 temperature sensor can be powered through the VDD pin (normal mode), or it can derive its power from the data line (parasite mode). You can chose either modes.

If you’re using an ESP32 folllow one of these two schematic diagrams.

Parasite Mode

DS18B20 Temperature Sensor with ESP32 Parasite Mode Wiring Schematic Diagram

Normal Mode

DS18B20 Temperature Sensor with ESP32 Normal Mode Wiring Schematic Diagram

Preparing Your Arduino IDE

We’ll program the ESP32 using Arduino IDE, so make sure you have the ESP32 add-on installed before proceeding:

Installing Libraries

To interface with the DS18B20 temperature sensor, you need to install the One Wire library by Paul Stoffregen and the Dallas Temperature library. Follow the next steps to install those libraries.

1. Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open.

2. Type “onewire” in the search box and install OneWire library by Paul Stoffregen.

Install OneWire library by Paul Stoffregen in Arduino IDE

3. Then, search for “Dallas” and install DallasTemperature library by Miles Burton.

Install DallasTemperature library by Miles Burton in Arduino IDE

After installing the libraries, restart your Arduino IDE.

Code (Single DS18B20)

After installing the required libraries, you can upload the code to the ESP32. The following code reads temperature from the DS18B20 temperature sensor and displays the readings on the Arduino IDE Serial Monitor.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

#include <OneWire.h>
#include <DallasTemperature.h>

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;     

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

void setup() {
  // Start the Serial Monitor
  Serial.begin(115200);
  // Start the DS18B20 sensor
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);
  Serial.print(temperatureC);
  Serial.println("ºC");
  Serial.print(temperatureF);
  Serial.println("ºF");
  delay(5000);
}

View raw code

There are many different ways to get the temperature from DS18B20 temperature sensors. However, if you’re using just one single sensor, this is one of the easiest and simplest ways.

DS18B20 Single OneWire Temperature Sensor with ESP32 and Arduino IDE

How the Code Works

Start by including the OneWire and the DallasTemperature libraries.

#include <OneWire.h>
#include <DallasTemperature.h>

Create the instances needed for the temperature sensor. The temperature sensor is connected to GPIO 4.

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

In the setup(), initialize the Serial Monitor at a baud rate of 115200.

Serial.begin(115200);

Initialize the DS18B20 temperature sensor:

sensors.begin();

Before actually getting the temperature, you need to call the requestTemperatures() method.

sensors.requestTemperatures(); 

Then, get the temperature in Celsius by using the getTempCByIndex() method as shown below:

float temperatureC = sensors.getTempCByIndex(0);

Or use the getTempFByIndex() to get the temperature in Fahrenheit.

float temperatureF = sensors.getTempFByIndex(0);

The getTempCByIndex() and the getTempFByIndex() methods accept the index of the temperature sensor. Because we’re using just one sensor its index is 0. If you want to read more than one sensor, you use index 0 for one sensor, index 1 for other sensor and so on.

Finally, print the results in the Serial Monitor.

Serial.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");

New temperature readings are requested every 5 seconds.

delay(5000);

Demonstration

After uploading the code, you should get your sensor readings displayed in the Serial Monitor:

DS18B20 Temperature readings in Arduino IDE Serial Monitor

Getting Temperature from Multiple DS18B20 Temperature Sensors

DS18B20 Multiple Temperature Sensors OneWire with ESP32 and Arduino IDE

The DS18B20 temperature sensor communicates using one-wire protocol and each sensor has a unique 64-bit serial code, so you can read the temperature from multiple sensors using just one single GPIO. You just need to wire all data lines together as shown in the following schematic diagram:

DS18B20 Multiple Temperature Sensors with ESP32 Wiring Schematic Diagram

Code (Multiple DS18B20s)

Then, upload the following code. It scans for all devices on GPIO 4 and prints the temperature for each one. (This sketch is based on an example provided by the DallasTemperature library).

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged TO GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Number of temperature devices found
int numberOfDevices;

// We'll use this variable to store a found device address
DeviceAddress tempDeviceAddress; 

void setup(){
  // start serial port
  Serial.begin(115200);
  
  // Start up the library
  sensors.begin();
  
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Loop through each device, print out address
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      Serial.println();
    } else {
      Serial.print("Found ghost device at ");
      Serial.print(i, DEC);
      Serial.print(" but could not detect address. Check power and cabling");
    }
  }
}

void loop(){ 
  sensors.requestTemperatures(); // Send the command to get temperatures
  
  // Loop through each device, print out temperature data
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      // Output the device ID
      Serial.print("Temperature for device: ");
      Serial.println(i,DEC);
      // Print the data
      float tempC = sensors.getTempC(tempDeviceAddress);
      Serial.print("Temp C: ");
      Serial.print(tempC);
      Serial.print(" Temp F: ");
      Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
    }
  }
  delay(5000);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
  }
}

View raw code

Demonstration

In this example, we’re using three DS18B20 temperature sensors. This is what we get on the Arduino IDE Serial Monitor.

ESP32 Multiple DS18B20 Temperature Sensors Serial Monitor Print readings

We have a dedicated article on how to interface multiple DS18B20 temperature sensors with the EPS32. Just follow the next tutorial:

ESP32 with multiple DS18B20 temperature sensors Arduino IDE

Display DS18B20 Temperature Readings in a Web Server

Display DS18B20 Temperature Readings in ESP32 Web Server using Arduino IDE

To build the web server we’ll use the ESPAsyncWebServer library that provides an easy way to build an asynchronous web server. Building an asynchronous web server has several advantages. We recommend taking a quick look at the library documentation on its GitHub page.

Installing the ESPAsyncWebServer library

The ESPAsyncWebServer library is not available to install in the Arduino IDE Library Manager. So, you need to install it manually.

Follow the next steps to install the ESPAsyncWebServer library:

  1. Click here to download the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get ESPAsyncWebServer-master folder
  3. Rename your folder from ESPAsyncWebServer-master to ESPAsyncWebServer
  4. Move the ESPAsyncWebServer folder to your Arduino IDE installation libraries folder

Installing the Async TCP Library

The ESPAsyncWebServer library requires the AsyncTCP library to work. Follow the next steps to install that library:

  1. Click here to download the AsyncTCP library. You should have a .zip folder in your Downloads folder
  2. Unzip the .zip folder and you should get AsyncTCP-master folder
  3. Rename your folder from AsyncTCP-master to AsyncTCP
  4. Move the AsyncTCP folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Code (DS18B20 Async Web Server)

Open your Arduino IDE and copy the following code.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
#endif
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is connected to GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

// 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);

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempF = sensors.getTempFByIndex(0);

  if(int(tempF) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <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">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP DS18B20 Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius</span> 
    <span id="temperaturec">%TEMPERATUREC%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit</span>
    <span id="temperaturef">%TEMPERATUREF%</span>
    <sup class="units">&deg;F</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
}, 10000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturef").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
}, 10000) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return readDSTemperatureC();
  }
  else if(var == "TEMPERATUREF"){
    return readDSTemperatureF();
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Start up the DS18B20 library
  sensors.begin();
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readDSTemperatureC().c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readDSTemperatureF().c_str());
  });
  // Start server
  server.begin();
}
 
void loop(){
  
}

View raw code

Insert your network credentials in the following variables and the code will work straight away.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

How the Code Works

In the following paragraphs we’ll explain how the code works. Keep reading if you want to learn more or jump to the “Demonstration” section to see the final result.

Importing libraries

First, import the required libraries for the ESP32 board:

#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>

Instantiate DS18B20 Sensor

Define the GPIO that the DS18B20 data pin is connected to. In this case, it’s connected to GPIO 4.

#define ONE_WIRE_BUS 4

Instantiate the instances needed to initialize the sensor:

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

Setting your network credentials

Insert your network credentials in the following variables, so that the ESP8266 can connect to your local network.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Create an AsyncWebServer object on port 80.

AsyncWebServer server(80);

Read Temperature Functions

Then, we create two functions to read the temperature.

The readDSTemperatureC() function returns the readings in Celsius degrees.

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

In case the sensor is not able to get a valid reading, it returns -127. So, we have an if statement that returns two dashes (–-) in case the sensor fails to get the readings.

if(tempC == -127.00){
  Serial.println("Failed to read from DS18B20 sensor");
  return "--";

The reaDSTemperatureF() function works in a similar way but returns the readings in Fahrenheit degrees.

The readings are returned as string type. To convert a float to a string, use the String() function.

return String(tempC);

Building the Web Page

The next step is building the web page. The HTML and CSS needed to build the web page are saved on the index_html variable.

In the HTML text we have TEMPERATUREC and TEMPERATUREF between % signs. This is a placeholder for the temperature values.

This means that this %TEMPERATUREC% text is like a variable that will be replaced by the actual temperature value from the sensor. The placeholders on the HTML text should go between % signs.

We’ve explained in great detail how the HTML and CSS used in this web server works in a previous tutorial. So, if you want to learn more, refer to the next project:

Processor

Now, we need to create the processor() function, that will replace the placeholders in our HTML text with the actual temperature values.

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return readDSTemperatureC();
  }
  else if(var == "TEMPERATUREF"){
    return readDSTemperatureF();
  }
  return String();
}

When the web page is requested, we check if the HTML has any placeholders. If it finds the %TEMPERATUREC% placeholder, we return the temperature in Celsius by calling the readDSTemperatureC() function created previously.

if(var == "TEMPERATUREC"){
  return readDSTemperatureC();
}

If the placeholder is %TEMPERATUREF%, we return the temperature in Fahrenheit.

else if(var == "TEMPERATUREF"){
  return readDSTemperatureF();
}

setup()

In the setup(), initialize the Serial Monitor for debugging purposes.

Serial.begin(115200);

Initialize the DS18B20 temperature sensor.

sensors.begin();

Connect to your local network and print the ESP32 IP address.

WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println();

// Print ESP8266 Local IP Address
Serial.println(WiFi.localIP());

Finally, add the next lines of code to handle the web server.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureC().c_str());
});
server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

When we make a request on the root URL, we send the HTML text that is stored in the index_html variable. We also need to pass the processor function, that will replace all the placeholders with the right values.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

We need to add two additional handlers to update the temperature readings. When we receive a request on the /temperaturec URL, we simply need to send the updated temperature value. It is plain text, and it should be sent as a char, so, we use the c_str() method.

server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureC().c_str());
});

The same process is repeated for the temperature in Fahrenheit.

server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

Lastly, we can start the server.

server.begin();

Because this is an asynchronous web server, we don’t need to write anything in the loop().

void loop(){

}

That’s pretty much how the code works.

Demonstration

After uploading the code, open the Arduino IDE Serial Monitor at a baud rate of 115200. Press the ESP32 on-board RST button and after a few seconds your IP address should show up.

In your local network, open a browser and type the ESP32 IP address.

Now you can see temperature in Celsius and Fahrenheit in your web server. The sensor readings update automatically without the need to refresh the web page.

ESP32 Web Server with DS18B20 OneWire Temperature Sensor Arduino IDE

Wrapping Up

We hope you’ve found this tutorial useful. We have guides for other sensors and modules with the ESP32 that you may like:

If you want to learn more about the ESP32 take a look at our course, or check or ESP32 free resources:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

6 thoughts on “ESP32 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server)”

  1. The above code works really well on my Heltec Lora ESP32 board at 240MHz, but the onewire library breaks down if you reduce the speed of the processor to save energy or for compatibility with other interfaces. Current thinking seems to be this is because the onewire interface is bitbashed and processor interrupts smooth operation.

    Reply
  2. I’ve used the one sensor example and it works fine.

    When I add a second sensor as depicted and run the multiple sensor code it can’t find any sensors (“Location devices…Found 0devices”).

    Any Idea what might be happening?

    Reply
    • Hi Peter.
      I don’t know what can be the problem.
      Please double-check your wiring and that each sensor works fine individually before hooking up the two sensors at the same time.
      Regards,
      Sara

      Reply
  3. Sara;

    Got both sensors working with one of the Dallas examples but they still refuse to work with the multiple sensor code above???

    I’ll do some more analysis tomorrow to try to determine what may be happening.

    Reply
  4. Sara;

    I’ve checked the sensor waveform with an oscilloscope and data looks good (clean transitions between 3.3 and 0 V).

    I’ve noticed that the Dallas example also returns 0 devices found using the “sensors.getDeviceCount()” command but the example then does an address assignment by index and finds both devices and then continues by reading the temperatures.

    In the multiple sensor code above it looks like the code extracts the address for each device found in a loop but since no devices are found….

    Seems like either the DS18B20 sensors I have are defective (in not correctly responding to the .getdevicecount command or the library has an issue with the same command.

    Anyway I’m moving forward as I can now read the sensor temperatures.

    Reply

Leave a Reply to Peter Laneville Cancel reply

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.