ESP32 DHT11/DHT22 Web Server – Temperature and Humidity using Arduino IDE

In this project, you’ll learn how to build an asynchronous ESP32 web server with the DHT11 or DHT22 that displays temperature and humidity using Arduino IDE.

ESP32 DHT11/DHT22 Web Server - Temperature and Humidity using Arduino IDE

The web server we’ll build updates the readings automatically without the need to refresh the web page.

With this project you’ll learn:

  • How to read temperature and humidity from DHT sensors;
  • Build an asynchronous web server using the ESPAsyncWebServer library;
  • Update the sensor readings automatically without the need to refresh the web page.

For a more in-depth explanation on how to use the DHT22 and DHT11 temperature and humidity sensors with the ESP32, read our complete guide: ESP32 with DHT11/DHT22 Temperature and Humidity Sensor using Arduino IDE

Watch the Video Tutorial

You can watch the video tutorial or keep reading this page for the written instructions.

Asynchronous Web Server

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 as mentioned in the library GitHub page, such as:

  • “Handle more than one connection at the same time”;
  • “When you send the response, you are immediately ready to handle other connections while the server is taking care of sending the response in the background”;
  • “Simple template processing engine to handle templates”;
  • And much more.

Take a look at the library documentation on its GitHub page.

Parts Required

ESP32 DHT11 DHT22 Temperature and Humidity Arduino IDE Circuit Schematic

To complete 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

Before proceeding to the web server, you need to wire the DHT11 or DHT22 sensor to the ESP32 as shown in the following schematic diagram.

In this case, we’re connecting the data pin to GPIO 27, but you can connect it to any other digital pin. You can use this schematic diagram for both DHT11 and DHT22 sensors.

ESP32 DHT11 DHT22 Temperature and Humidity Arduino IDE Circuit Schematic Diagram

(This schematic uses the ESP32 DEVKIT V1 module version with 36 GPIOs – if you’re using another model, please check the pinout for the board you’re using.)

Note: if you’re using a module with a DHT sensor, it normally comes with only three pins. The pins should be labeled so that you know how to wire them. Additionally, many of these modules already come with an internal pull up resistor, so you don’t need to add one to the circuit.

Installing Libraries

You need to install a couple of libraries for this project:

Follow the next instructions to install those libraries:

Installing the DHT Sensor Library

To read from the DHT sensor using Arduino IDE, you need to install the DHT sensor library. Follow the next steps to install the library.

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

Installing the Adafruit Unified Sensor Driver

You also need to install the Adafruit Unified Sensor Driver library to work with the DHT sensor. Follow the next steps to install the library.

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

Installing the ESPAsyncWebServer library

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

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

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

Open your Arduino IDE and copy the following code.

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

// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <Adafruit_Sensor.h>
#include <DHT.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

#define DHTPIN 27     // Digital pin connected to the DHT sensor

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readDHTTemperature() {
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float t = dht.readTemperature(true);
  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {    
    Serial.println("Failed to read from DHT sensor!");
    return "--";
  }
  else {
    Serial.println(t);
    return String(t);
  }
}

String readDHTHumidity() {
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  if (isnan(h)) {
    Serial.println("Failed to read from DHT sensor!");
    return "--";
  }
  else {
    Serial.println(h);
    return String(h);
  }
}

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; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP32 DHT Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="dht-labels">Temperature</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-tint" style="color:#00add6;"></i> 
    <span class="dht-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">&percnt;</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return readDHTTemperature();
  }
  else if(var == "HUMIDITY"){
    return readDHTHumidity();
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  dht.begin();
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

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

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readDHTTemperature().c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readDHTHumidity().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. The WiFi, ESPAsyncWebServer and the ESPAsyncTCP are needed to build the web server. The Adafruit_Sensor and the DHTlibraries are needed to read from the DHT11 or DHT22 sensors.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <ESPAsyncTCP.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

Setting your network credentials

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

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

Variables definition

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

#define DHTPIN 27  // Digital pin connected to the DHT sensor

Then, select the DHT sensor type you’re using. In our example, we’re using the DHT22. If you’re using another type, you just need to uncomment your sensor and comment all the others.

#define DHTTYPE DHT22   // DHT 22 (AM2302)

Instantiate a DHTobject with the type and pin we’ve defined earlier.

DHT dht(DHTPIN, DHTTYPE);

Create an AsyncWebServerobject on port 80.

AsyncWebServer server(80);

Read Temperature and Humidity Functions

We’ve created two functions: one to read the temperature (readDHTTemperature()) and the other to read humidity (readDHTHumidity()).

String readDHTTemperature() {
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float t = dht.readTemperature(true);
  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) { 
    Serial.println("Failed to read from DHT sensor!");
    return "--";
  }
  else {
    Serial.println(t);
    return String(t);
  }
}

Getting sensor readings is as simple as using the readTemperature() and readHumidity() methods on the dht object.

float t = dht.readTemperature();
float h = dht.readHumidity();

We also have a condition that returns two dashes (–) in case the sensor fails to get the readings.

if (isnan(t)) {
  Serial.println("Failed to read from DHT sensor!");
  return "--";
}

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

return String(t);

By default, we’re reading the temperature in Celsius degrees. To get the temperature in Fahrenheit degrees, comment the temperature in Celsius and uncomment the temperature in Fahrenheit, so that you have the following:

//float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float t = dht.readTemperature(true);

Building the Web Page

Proceeding to the web server page.

ESP32 DHT11 DHT22 Temperature and Humidity web page

As you can see in the above figure, the web page shows one heading and two paragraphs. There is a paragraph to display the temperature and another to display the humidity. There are also two icons to style our page.

Let’s see how this web page is created.

All the HTML text with styles included is stored in the index_html variable. Now we’ll go through the HTML text and see what each part does.

The following <meta> tag makes your web page responsive in any browser.

<meta name="viewport" content="width=device-width, initial-scale=1">

The <link> tag is needed to load the icons from the fontawesome website.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">

Styles

Between the <style></style> tags, we add some CSS to style the web page.

<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; }
  .dht-labels{
    font-size: 1.5rem;
    vertical-align:middle;
    padding-bottom: 15px;
  }
</style>

Basically, we’re setting the HTML page to display the text with Arial font in block without margin, and aligned at the center.

html {
  font-family: Arial;
  display: inline-block;
  margin: 0px auto;
  text-align: center;
}

We set the font size for the heading (h2), paragraph (p) and the units(.units) of the readings.

h2 { font-size: 3.0rem; }
p { font-size: 3.0rem; }
.units { font-size: 1.2rem; }

The labels for the readings are styled as shown below:

dht-labels{
  font-size: 1.5rem;
  vertical-align:middle;
  padding-bottom: 15px;
}

All of the previous tags should go between the <head> and </head> tags. These tags are used to include content that is not directly visible to the user, like the <meta> , the <link> tags, and the styles.

HTML Body

Inside the <body></body> tags is where we add the web page content.

The <h2></h2> tags add a heading to the web page. In this case, the “ESP32 DHT server” text, but you can add any other text.

<h2>ESP32 DHT Server</h2>

Then, there are two paragraphs. One to display the temperature and the other to display the humidity. The paragraphs are delimited by the <p> and </p> tags. The paragraph for the temperature is the following:

<p>
  <i class="fas fa-thermometer-half" style="color:#059e8a;"</i> 
  <span class="dht-labels">Temperature</span> 
  <span id="temperature">%TEMPERATURE%</span>
  <sup class="units">°C</sup>
</p>

And the paragraph for the humidity is on the following snipet:

<p>
  <i class="fas fa-tint" style="color:#00add6;"></i> 
  <span class="dht-labels">Humidity</span>
  <span id="humidity">%HUMIDITY%</span>
  <sup class="units">%</sup>
</p>

The <i> tags display the fontawesome icons.

How to display icons

To chose the icons, go to the Font Awesome Icons website.

Font Awesome Icons website

Search the icon you’re looking for. For example, “thermometer”.

Font Awesome Icons website thermometer

Click the desired icon. Then, you just need to copy the HTML text provided.

<i class="fas fa-thermometer-half">
Font Awesome Icons website thermometer half

To chose the color, you just need to pass the style parameter with the color in hexadecimal, as follows:

<i class="fas fa-tint" style="color:#00add6;"></i> 

Proceeding with the HTML text…

The next line writes the word “Temperature” into the web page.

<span class="dht-labels">Temperature</span>

The TEMPERATURE text between % signs is a placeholder for the temperature value.

<span id="temperature">%TEMPERATURE%</span>

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

Finally, we add the degree symbol.

<sup class="units">°C</sup>

The <sup></sup> tags make the text superscript.

We use the same approach for the humidity paragraph, but it uses a different icon and the %HUMIDITY% placeholder.

<p>
  <i class="fas fa-tint" style="color:#00add6;"></i> 
  <span class="dht-labels">Humidity</span>
  <span id="humidity">%HUMIDITY%</span>
  <sup class="units">%</sup>
</p>

Automatic Updates

Finally, there’s some JavaScript code in our web page that updates the temperature and humidity automatically, every 10 seconds.

Scripts in HTML text should go between the <script></script> tags.

<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>

To update the temperature on the background, we have a setInterval() function that runs every 10 seconds.

Basically, it makes a request in the /temperature URL to get the latest temperature reading.

  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

When it receives that value, it updates the HTML element whose id is temperature.

if (this.readyState == 4 && this.status == 200) {
  document.getElementById("temperature").innerHTML = this.responseText;
}

In summary, this previous section is responsible for updating the temperature asynchronously. The same process is repeated for the humidity readings.

Important: since the DHT sensor is quite slow getting the readings, if you plan to have multiple clients connected to an ESP32 at the same time, we recommend increasing the request interval or remove the automatic updates.

Processor

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

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return readDHTTemperature();
  }
  else if(var == "HUMIDITY"){
    return readDHTHumidity();
  }
  return String();
}

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

if(var == "TEMPERATURE"){
  return readDHTTemperature();
}

If the placeholder is %HUMIDITY%, we return the humidity value.

else if(var == "HUMIDITY"){
  return readDHTHumidity();
}

setup()

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

Serial.begin(115200);

Initialize the DHT sensor.

dht.begin();

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

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

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("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDHTHumidity().c_str());
});

When we make a request on the root URL, we send the HTML text that is stored on the index_html variable. We also need to pass the processorfunction, 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 and humidity readings. When we receive a request on the /temperature 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("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDHTTemperature().c_str());
});

The same process is repeated for the humidity.

server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDHTHumidity().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.

Upload the Code

Now, upload the code to your ESP32. Make sure you have the right board and COM port selected.

After uploading, open the Serial Monitor at a baud rate of 115200. Press the ESP32 reset button. The ESP32 IP address should be printed in the serial monitor.

Upload the DHT11 DHT22 ESP32 Sketch Code Example

Web Server Demonstration

Open a browser and type the ESP32 IP address. Your web server should display the latest sensor readings.

Notice that the temperature and humidity readings are updated automatically without the need to refresh the web page.

ESP32 DHT11/DHT22 Web Server - Temperature and Humidity using Arduino IDE Demonstration

Troubleshooting

If your DHT sensor fails to get the readings, read our DHT Troubleshooting Guide to help you fix the issue.

Wrapping Up

In this tutorial we’ve shown you how to build an asynchronous web server with the ESP32 to display sensor readings from a DHT11 or DHT22 sensor and how to update the readings automatically.

If you liked this project, you may also like:

This tutorial is a preview of the “Learn ESP32 with Arduino IDE” course. If you like this project, make sure you take a look at the ESP32 course page where we cover this and a lot more topics with the ESP32.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

203 thoughts on “ESP32 DHT11/DHT22 Web Server – Temperature and Humidity using Arduino IDE”

  1. Hello. I keep getting this error when I compile.

    Board nodemcuv2 (platform esp8266, package esp8266) is unknown
    Error compiling for board NodeMCU 1.0 (ESP-12E Module).

    It compiles OK when I select Arduino Nano, but not the ESP8266. Can you give me any suggestions on how to solve this problem?
    Thanks,
    Steve Tripoli

    Reply
    • I changed these lines and it now compiles and uploads.
      This is the orignial
      // Replace with your network credentials
      const char* ssid = “YOUR_SSID”;
      const char* password = “YOUR_PASSWORD”;

      All I did was to remove the const in both lines.

      Reply
  2. Will this work using an ESP8266? I am trying, but this all I get from the serial monitor.

    ets Jan 8 2013,rst cause:4, boot mode:(3,6)

    wdt reset
    load 0x4010f000, len 1384, room 16
    tail 8
    chksum 0x2d
    csum 0x2d
    v4ceabea9
    ~ld

    Connecting to MyHome36

    Reply
  3. Hi,
    This work perfectly, thank you.
    I just wants to connect more sensors with the esp32 , for example the DHT11 for temperature and humidity and the PIR motion sensor. It is possible to do it ? and witch pins use to collect data ?

    Reply
    • Hi.
      Yes, you can do that.
      You can use the PIR motion sensor with any GPIO of the ESP32 (except GPIOs 6, 7, 8, 9, 10, and 11).
      I hope this helps.
      Regards
      sara 🙂

      Reply
      • Found it, got it to compile. However, on runtime, upon going to browser, it displays the page, but it always goes to “FAILED” on ALL readings. I’m trying to find out why it can’t read the DHT11 🙁

        Reply
        • It may be a power issue. If you’re supplying 3.3V to the DTH11, try to supply 5V instead, and see if that fixes your issue.
          Also, make sure you have everything wired correctly with the 4.7K Ohm pull-up resistor.
          Also test powering up the sensor using an external power suppky.
          I hope this helps debugging your problem.
          Regards,
          Sara 🙂

          Reply
  4. Hi, Suppose I have my sensors outside the house, how to supply power to the ESP8266 module without the USB port? Can batteries do this job?

    Reply
  5. hello

    I loaded this on a esp32, and it works… for a while, then the browser can`t access the web server until I restart the ESP32 again. Any thoughts ?

    Reply
    • Hi Martin.
      Sometimes the DHT sensor fails to read the temperature, but I have no idea why that happens?
      But do you get good results without failures with that new library?
      We need to try that library as see what we get.
      Regards,
      Sara 🙂

      Reply
  6. It looks like you now also need the Adafruit_Sensor-master repo to get the DHT repo to work right. It can be found here: https://github.com/adafruit/Adafruit_Sensor.

    Without it I was getting a “multiple libraries were found for “wifi.h”” error that wouldn’t allow for a compile.

    Or did I miss a step when following the instructions?

    Reply
    • Hi Michael.
      You are right. You also need to install the adafruit sensor library.
      I’ve updated the post to include that.
      Thanks for telling us.
      Regards,
      Sara 🙂

      Reply
  7. Hi, just wondering how can I save the reading data from the website to a text file for every 30 seconds? I added a line of client.println(“Content-Disposition: attachment; filename=\”test.txt\””); under the line of client.println(“Content-Type: text/html”); , but the webpage stop refreshing after the first text file has been downloaded. Please advise.

    Reply
  8. Will this work on an ESP8266? I am trying to find what to change to make this work on an 8266 and I cant find anything in the code. I tried just setting the board (under tools->board) to my model ESP8266 (adafruit feather Huzzah esp8266) but it wont take the code.

    Reply
  9. Hi,

    I adapted this code to send a key status to the browser, but the 30 seconds of auto refresh is to long… Is there a way to send (and show on browser) the data right after the key is pressed or not?

    Reply
  10. Sara, it is always the dht11 or dht22 sensors which are limited to low temperatures. Why not do a project that uses the MAX31865 RTD and MAX31855 Thermocouple amplifier boards with the ESP8266. These devices offer outstanding accuracy over an extremely long range of temperatures.

    Reply
    • Hi Carl.
      Thank you for the suggestion.
      We have to try those in the future and maybe come up with a tutorial.
      Regards,
      Sara

      Reply
  11. Hi all, good post, but i’ve suggestion.
    this app contains 2 async separated calls, for temperature and humidity: why not a single xhr call to read these values then returning an object (ie {“T”:”25,32″, “H”:”76.54″})?
    regards

    Reply
  12. Finally a new project that isn’t MicroPython, thanks, very cool.
    Question: is it possible to insert the icons local, that is on my local network that doesn’t have internet access? (Where I live way out in the country internet is VERY expensive so have to go into town and use library internet about once a week)
    Can they be downloaded elsewhere and stored on the esp32?
    Thanks for all the great tutorials.
    dp

    Reply
  13. Bonjour. impossible de compiler le programme. il m’indique:’tcp’p_api_call_data’ incomplete .exit status 1.Ă  vous lire salutations; toutes les librairies sont bien instalĂ©s le “SSID” et le “Passeword ” sont OK ,alors?

    Reply
  14. Hi. when compiling I get this error:

    int begin(char* ssid, const char *passphrase);
    ^
    exit status 1
    invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]

    Do you know what may be happening?
    Thank you

    Reply
    • Hi.
      This project only works with the ESP32.
      But you can change the code to include the right libraries to make it compatible with the ESP8266. However, we don’t have that documented at the moment.
      You need to use the ESP8266WiFi library instead of the WiFi library, and the ESPAsyncTCP instead of the Async TCP.
      Regards,
      Sara

      Reply
  15. Hii
    I keep getting this error when I compile.
    “invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]”
    Can you give me any suggestions on how to solve this problem?
    Thanks,
    Udayana

    Reply
  16. Hi, Sara and Rui,
    I have realized this project with the ESP32 and everything was perfect.
    I’wanted to try with an ESP8266-01 (1Mb) and I changed the library WiFi.h with the ESP8266WiFi.h
    I have also in my library folder the ESPAsyncTCP.h, but is not used directly in the sketch.
    But can’t read the sensor (DFH11 or DHT22) with the error “Failed to read from DHT sensor!”.
    I have insert the display of the Temp and Humidity at the beginning of the Setup, and run perfectly.
    I have also changed the interval time in the Javascript from 10.000 to 20.000.
    The sensor is powered with 5v with a pullup resistor of 4.7k.
    Also a display after the “dht.readTemperature()” shows “nan” (Not a Number) and a “delay(200)” or more added after the “dht.readTemperature()d” can’t run better.

    It’s not so important, but I’d like to understand why.
    One time out of twenty I have a correct display of the Temp and Humidity at the beginnig after a “reset”.
    I have put a counter instead the Temp value and run correctly also on the Smartphone.

    Thanks for any suggestion. I start also to try yours intersting projects with MicroPython.
    This project is the best project with ESP and C++ I ever found. Really!!
    Roberto
    Graz
    Austria

    Reply
    • Hi Roberto.
      Thank you so much for your nice words.
      When you get “Failed to read from DHT sensor!” it usually means that the sensor is not wired properly, or it is not being powered properly. If you’re powering your ESP32 using an USB cable directly through your computer USB port, that can be the problem, and that’s why you sometimes get readings and others don’t.
      Try power it from a USB hub powered by an external source. Also helps to replace the USB cable with a stronger and/or shorter one.
      If you get a “nan” error, it usually means that the sensor didn’t have enough time to get the readings. If you’re using a DHT22, you can only request readings every 2 seconds.

      I hope this helps.
      Regards,
      Sara

      Reply
  17. I have installed the AsyncTCP-master library but I get the error:

    C:\Users\marti\Documents\Arduino\sketchbook\libraries\ESPAsyncWebServer-master\src/ESPAsyncWebServer.h:36:25: fatal error: ESPAsyncTCP.h: No such file or directory

    #include

    ^

    I see the file AsyncTCP.h in the library but not ESPAsyncTCP.h Is there another library I need that wasn’t in the article?

    Reply
  18. Hi Sara,
    following the detailed (thank you!) instructions in “installing ESP32 board …” second part “deleting the espressif folder ..” to get the latest version of it I successful could test the WiFiscan example.
    Great!
    However:
    I failed to compile the “ESP32 DHT11/DHT21 webserver temp & hum …” example from your Web site. Got a whole bunch of error messages, first read as:
    … AsyncTCP-952b7eb6ba62f7071f7da2a274d36e06b97de572\src\AsyncTCP.cpp:259:27: error: field ‘call’ has incomplete type ‘tcpip_api_call’
    etc. etc.
    Searching the WEB I found a lot of comments concerning this issue totaly unintelligble to me :-((
    Please give advice how to fix the problen or public a new – compatible – version of the Web-server sketch.
    Thank you

    Reply
      • Sara, thank you for the very fast response!
        As I’m using the latest arduino IDE and the latest espressive file may I ask you for a very short cross check before I have to dig deeper into installation details?

        I’m using IDE 1.8.9 and have – according to the instruction – deleted the espressive file in my sketchbook folder to compile the sourcecode from your Web-side.

        Thank you so much for your support

        Reply
        • Unfortunately, I don’t know what to do from here as I’ve never experienced that problem.
          You can also check if you have more than one Arduino IDE installed in your computer that may be conflicting…

          Reply
      • Thank you Sara for your hint. I gone thru all the steps in https://github.com/me-no-dev/AsyncTCP/issues/21 as adviced. Afterwards I could sucessfull compile and run the ESP32 examples WiFiScan, getChipID, LEDCSoftwarefade etc. but still not the async. Webserver sketch.
        Did you suceed in compiling the code?
        Maybe there is someone out here who can try to compile – no hardware neede for the test just compile.
        Thank you for support!

        Reply
          • Sara
            it looks like an incompabilty of older an newer async tcpip libs:
            field ‘call’ has incomplete type ‘tcpip_api_call’ struct tcpip_api_call call;

            If you ever update arduino IDE et all pls try to compil again and report the result here. It’s allways a mess with incompatible updates I know.

            Thank you for your support!

  19. Thanks so much for this tutorial, it’s fantastic and just what I was looking for.
    Do you know if there a way to display a graph of the data on the website so you can view the changes in temp & humidity over the course of a day, instead of just at a point in time??

    Reply
  20. There is a compilation error that seems to be linked to one of the libraries:
    C:\Users\ik\Documents\Arduino\libraries\ESPAsyncWebServer\src\WebAuthentication.cpp:23:17: fatal error: md5.h: No such file or directory

    I have the ESPAsyncWebserver installed and there is a WebAuthentication.cpp file.
    What could be wrong here

    Reply
  21. Hey thanks for the awesome guide!

    I know this is a bit old but there were a few issues.

    The link to the AsyncTCP might be incorrect or outdated, I googled and found the files from a different source.

    There was a problem with multiple wifi.h locations, but this seems like a general esp32 issue.

    Also the credentials for wifi showed errors, I removed the ‘const’ and it worked.

    I have one question, the website randomly gets assigned to an local ip address.
    Is there any way to keep the ip static so it will be the same?

    Thank you for the guide

    Reply
  22. hi there I’m getting this error how do I fix it

    Serial port /dev/cu.Bluetooth-Incoming-Port
    Connecting…….._____….._____….._____….._____….._____….._____…..____An error occurred while uploading the sketch
    _

    A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header

    Reply
  23. Hi there,
    thanks for the fine tutorial.
    It’s working, but I’ve little issues:
    I set the interval to 12000, both t and h.
    Now the h updates every 8 seconds, the t only when I reload the page.
    Not so comfortable and I don’t understand – both parts have similar code.

    So I thought, it would be nice to display the date and time of the readings too. Unfortunately I don’t know how to integrate this function.

    Another question for ESP32: If I interrupt the voltage and connect again, starts it working by itself or must I press the boot- and/or the en-button?

    Thanks for your applied time
    Siegfried

    Reply
  24. Update:
    After changing interval time and uploading, it doesn’t connect to wifi anymore.
    Everything else is the same.
    Help!!!

    Reply
  25. Maybe I should have added this:
    18:47:16.866 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    18:47:16.866 -> configsip: 0, SPIWP:0xee
    18:47:16.866 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    18:47:16.912 -> mode:DIO, clock div:1
    18:47:16.912 -> load:0x3fff0018,len:4
    18:47:16.912 -> load:0x3fff001c,len:928
    18:47:16.912 -> ho 0 tail 12 room 4
    18:47:16.912 -> load:0x40078000,len:8424
    18:47:16.912 -> ho 0 tail 12 room 4
    18:47:16.912 -> load:0x40080400,len:5868
    18:47:16.912 -> entry 0x4008069c
    18:47:18.316 -> Connecting to WiFi..
    18:47:19.299 -> Connecting to WiFi..
    18:47:20.282 -> Connecting to WiFi..
    18:47:21.313 -> Connecting to WiFi..
    18:47:22.295 -> Connecting to WiFi.. and so on
    I tried again and again.

    Reply
    • Hi.
      Did you introduced your network credentials?
      It is common to get that error when we upload the code without the credentials. It continuously tries to connect to wifi.
      Regards,
      Sara

      Reply
  26. Hi Sara,
    I did! It worked before. The code is the same, I only changed interval time. The problem is still after I undid the change.
    I tried the ‘const char* ssid = “W…’ lines without ‘const’, wich hint I found somewhere – no other result.
    Regards,
    Siegfried

    Reply
  27. I’m sorry to be flashy but I can’t solve the problem.
    I made a new sketch, copying your code, only changing the network credentials, did the upload. It started the same way as before: continuously tries to connect to wifi.
    I can’t understand because it worked about ten days ago for about one weak. It’s the same computer and other hardware (Win7, DOIT ESP32 Devkit V1, Router WLAN adjustment).
    Would you have any suggestions?
    Regards,
    Siegfried

    Reply
    • Hi.
      I’m sorry, but I don’t know what can be wrong.
      If you are inserting your network credentials properly, it is very difficult to figure out what is wrong.
      Can you try any other wi-fi sketch example and see if the ESP32 connects to wi-fi?
      In the Arduino IDE, you can select a file from the examples folder.
      Regards,
      Sara

      Reply
  28. Hi,
    as the ESP32 to google sheets project works fine since may, 19. on the same wifi, I finally
    changed the DHT22 to another one – no better result
    put it to 5V as I read somewhere – no better result
    put it back to 3.3V – miraculously it w o r k s !!!
    I don’t understand but obviously sometimes you have to try some crazy things with the computer stuff.

    How could I display date and time on the web page too?

    Is there any workshop for learning how to get access to my WiFi.localIP from www? After reading the whole google (nearly), all I tried till now failed.

    Thanks so much for helping,
    Siegfried

    Reply
  29. I’m going to connect two ultrasonic sensors with ESP module is there anything to change or can I just replacer the coding part which is related to the ultrasonic sensor part?
    help me

    Reply
    • Hi Igor.
      After uploading the code, open the Serial Monitor and make sure you have the right baud rate selected. In this case 115200.
      Then, press the ESP32 on-board RESET button. It should display the IP address.
      I hope this helps.
      Regards,
      Sara

      Reply
  30. hi..i am facing an error after uploading the code.i open the serial monitor and there was an error message…BROWNOUT DETECTOR WAS TRIGGERED.pls help me to solve this

    Reply
  31. hi
    this is the first time i play arround with something other than a rasperry pi,
    i have a problem with the ESPAsyncWebServer library.
    when i try to upload the code i get a error at compiliation. it can not find the ESPAsyncTCP.h file.

    Screenshot https://imgur.com/a/IpT7UUs

    i think i copy and rename the librarys right..?

    also i just uploaded a onboard LED blink sketch that works…?

    hope you can help me noob

    Reply
  32. hi,

    I’ve a Question. How to can I combine the DHT values on webpage with an Input-Output module?
    Is there any possibility?

    Kind regards
    Jan

    Reply
  33. Can I make it work as an access point and send the sensor data through it? so as not to have the need to be connected to a local network.

    Reply
  34. Hello everybody,
    as I never knew if my server displayed actual data,
    I worked out how to display the date and time of sensor readings in european format,
    – in case of someone is interested, I did it that way:

    First the libraries:
    #include
    #include

    then:
    // Define NTP Client to get time
    WiFiUDP ntpUDP;
    NTPClient timeClient(ntpUDP);
    // Variables to save date and time
    String formattedDate;
    String dayStamp;
    String timeStamp;
    String newdate;
    String zeit;
    int splitT;

    then added the readZeit function (Zeit=time):
    String readZeit() {
    while(!timeClient.update()) {
    timeClient.forceUpdate();
    }
    formattedDate = timeClient.getFormattedDate();
    splitT = formattedDate.indexOf(“T”);
    timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
    dayStamp = formattedDate.substring(0, splitT);
    String year = dayStamp.substring(0,4);
    String month = dayStamp.substring(5,7);
    String day = dayStamp.substring(8);
    // format for european standard
    zeit = day + “.” + month + “.” +year+” “+timeStamp;
    Serial.println(“Variable zeit”);
    Serial.println(zeit);
    return String(zeit);
    }

    changed the styles a little:

    html {
    font-family: Arial;
    display: inline-block;
    margin: 0px auto;
    text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 2.5rem;
    .units { font-size: 1.5rem; }
    .dht-labels{
    font-size: 1.5rem;
    vertical-align:middle;
    }

    A new icon for the time:


    Zeit
    %zeit%

    Setinterval for time (I choosed 5 sec for all intervals):

    setInterval(function ( ) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
    document.getElementById(“zeit”).innerHTML = this.responseText;
    }
    };
    xhttp.open(“GET”, “/zeit”, true);
    xhttp.send();
    }, 5000 ) ;

    behind WiFiConnected I added:
    // Initialize a NTPClient to get time, offset 3600 for +1 hour
    timeClient.begin();
    timeClient.setTimeOffset(3600);
    while(!timeClient.update()) {
    timeClient.forceUpdate();
    }

    and at last:
    server.on(“/zeit”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, “text/plain”, readZeit().c_str());
    });

    Concerning my posts from May, everything works much better since I have a windows10 laptop!
    Kind regards,
    Siegfried

    Reply
  35. I got an Compiler error:
    Arduino: 1.8.10 (Windows 10), Board: “DOIT ESP32 DEVKIT V1, 80MHz, 921600, None”

    Multiple libraries were found for “WiFi.h”
    In file included from C:\Users\santr\Documents\ESP32\DHT11_Web_server\DHT11_Web_server.ino:8:0:

    Used: C:\Users\santr\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi
    C:\Users\santr\Documents\Arduino\libraries\ESPAsyncWebServer\src/ESPAsyncWebServer.h:33:22: fatal error: AsyncTCP.h: No such file or directory

    Not used: C:\Program
    compilation terminated.

    Multiple libraries were found for “ESPAsyncWebServer.h”
    Used: C:\Users\santr\Documents\Arduino\libraries\ESPAsyncWebServer
    Multiple libraries were found for “FS.h”
    Used: C:\Users\santr\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\FS
    exit status 1
    Error compiling for board DOIT ESP32 DEVKIT V1.

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    Reply
  36. Hi, I bought some courses you sell. I want to make a query … how do I add a button to activate an output to this server program … thank you very much ..

    Reply
  37. Hello Sara Santos Madam. Can you please tell me how to send sensor data connected to ESP32 into the laptop by using built in bluetooth/wifi of laptop.

    Reply
  38. Hello Sara, I tried to add an OLED SSD1306 to display temperature but it didn’t work…The web server just stopped working ! Does anybody try to do that?
    JCB

    Reply
    • Hi Luca.
      Yes, you can modify the code to use that sensor.
      You need a different library to read that sensor: the Adafruit_HTU21DF library
      After installing the library you should get some examples on how to get temperature and humidity.
      Then, you just need to assign the temperature and humidity to the same values we use in our code.
      Unfortunately, we don’t have any tutorial about that sensor at the moment.
      Regards,
      Sara

      Reply
  39. C:\Users\19477\Desktop\eg1\DHT11_ESP32_Web\DHT11_ESP32_Web.ino:8:28: fatal error: AsyncWebServer.h: No such file or directory

    compilation terminated.

    Hello, Sarah, this problem has been bothering me for 2 days, can you help me to see what the problem is? Thank you 

    Reply
  40. Hey, i want to display a message on the webpage itself when the temperature or the humidity crosses a threshold.
    Also i want to connect a relay and the relay should be activated that is it should send high signal when the temperature or the humidity crosses a threshold.
    If anyone knows either of the two, please it would of great help as im not sure on how to exactly do it. Its a little important.

    Reply
  41. Hi Sara & Rui,

    Thanks again for a great tutorial !!

    However, I’m getting the following compile error with Arduino IDE:

    ‘index_html’ was not declared in this scope

    The declaration of index_html is:

    const char index_html[] PROGMEM = R”rawliteral(

    .
    .
    .

    If I comment out the following it compiles OK.

    // Route for root / web page
    server.on(“/”, HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, “text/html”, index_html, processor);
    });

    Any ideas what’s happening ?

    Regards,

    George

    Reply
    • Hi,

      Just an update. I solved the problem by moving the declaration of index_html to before the setup. It must be related to the scope of the variable ?

      However, it now works :-))

      George

      Reply
  42. What’s the problem? It’s been bothering me for a long time

    ResolveLibrary(functional)In file included from C:\Users\Administrator\Documents\Arduino\DHT-11_web\DHT-11_web.ino:8:0:

    -> candidates: []
    C:\Users\Administrator\Documents\Arduino\libraries\ESPAsyncWebServer\src/ESPAsyncWebServer.h:26:10: fatal error: functional: No such file or directory

    #include

    ^~~~~~~~~~~~

    compilation terminated.

    äœżç”š 1.2.7 ç‰ˆæœŹçš„ćș“ WiFi ćœšæ–‡ä»¶ć€č E:\arduino-1.8.12\libraries\WiFi
    äœżç”š 1.2.3 ç‰ˆæœŹçš„ćș“ ESPAsyncWebServer ćœšæ–‡ä»¶ć€č C:\Users\Administrator\Documents\Arduino\libraries\ESPAsyncWebServer
    exit status 1
    äžșćŒ€ć‘æż Arduino Uno çŒ–èŻ‘æ—¶ć‡ș错。

    Reply
  43. I’m having very inconsistent successful vs failed reads when I put the sensor in a -0C environment. Is there a workaround for this?

    Thanks,
    Andy

    Reply
  44. Hi,
    Using the DHT 22 I am getting a TON of failed reads below freezing (below 0 Degrees Celsius). The specs for the sensor rate it at -40, I’m looking for the -20 range (a standard freezer ).
    Am I doing something wrong?

    Thanks
    Andy

    Reply
  45. This is pretty great, but the webserver crashes after about 30-60 minutes. It doesn’t seem to matter if you are connected to the webpage or not. Others mentioned this in earlier comments. I’d like to use this for my little seedling box, but it has to work all the time or most. Anyone know why the webserver crashes? Nothing shows in the console (chrome console and serial monitor), it just stops updating and the page is unavailable if updated.

    Reply
  46. In this Version the ‘%’ after the humidity value until the end of the html page will be replaced with an empty string. Is there a way to escape the percent? So that it won’t act as a variable?

    Reply
  47. I’ve tried the tutorial that you shared, but after I uploaded it to Esp32 why is it so slow to connect to the Esp32 webserver it doesn’t even respond, is there a way out, thank you

    Reply
  48. This was a GREAT project! I’ve put my DHT11 through its paces, from the Arduino Uno temperature reader via 2 line LCD screen, then a TFT screen, then a small OLED screen. Using the ESP32 to get it wirelessly is really neat. I’m getting a couple other (more precise) sensors soon. Would like to integrate a data-logging feature perhaps. But first, I need to understand all that I put into that sketch!

    Reply
    • Hello Donald. I totally agree that this is one GREAT project and one of my favourites. Many thanks go to Rui and Sara for making it and all the other projects available to us. In fact, I’ve used this project as the basis for my own project which monitors temperature, pressure and carbon monoxide all controlled by WiFi through the webserver running on an ESP32. Readings are updated on a TFT and graphically displayed for each of the sensors while at the same time readings are sent over WiFi to an external WiFi enabled device. If the carbon monoxide levels reach the defined limits set in the program then a buzzer sounds and LED’s flash green, blue or red depending on the levels detected. I have PCB’s professionally made and have a few available if you or anyone else is interested in building my project. I could also supply all the electronic parts for the build including an ESP32 pre-programmed – sorry but the source code cannot be made available. For those into 3D printing I can also provide STL files for a case to house everything.

      Reply
  49. Hello Folks

    I am trying to setup an async web server on an ESP32 Thing (sparkfun). My basic problem is multiple timeouts as viewed in the web browser console and the server stops responding after a longer period of time.
    Example of timeout errors
    (index):47 GET http://192.168.0.180/temperature net::ERR_CONNECTION_TIMED_OUT

    Since my program was based on a few different Random Nerd Tutorials I decide to go back to the exacted code that was used in this example to display temp and humidity.

    The esp32 is within 7′ of the router.

    I am getting the same errors……Please help.

    Reply
    • Hello Rob,

      This is an issue I’m trying to solve with my project. The webserver stops responding after a period of time. I’ve tried starting in AP mode only, STA mode only, AP-STA mode – connecting via local AP and then changing the url on a webpage to access via the router. Every time the webserver stops responding but the program doesn’t crash as the readings are continually updated on the screen.

      I’ve even checked the WiFi status aka WiFi.status() but not knowing the codes returned it’s difficult to know what’s going on. Have searched the web for what the status values mean but either they cannot be found or not well documented.

      It would also be good to know what is the best way, if any, to switch between AP and STA modes. Does the webserver need to be disconnected, stopped before restarting or whatever ?

      Hopefully someone can shed some light and help out with this problem ? (Rui, Sara ?)

      Regards

      Reply
  50. maybe you can use this.
    I switch between ap mode and station mode or vice versa, this way.
    you have to call apmode and stamode from main loop as shown.

    #include <WiFi.h>
    #include <AsyncTCP.h>
    #include <ESPAsyncWebServer.h>

    bool modeap = 0;
    bool modesta = 0;

    const char* ssid = “REPLACE_WITH_YOUR_SSID”;
    const char* password = “REPLACE_WITH_YOUR_PASSWORD”;

    const char* apssid = “REPLACE_WITH_YOUR”;
    const char* appassword = “REPLACE_WITH_YOUR”;

    AsyncWebServer server(80);

    void apmode(){
    WiFi.disconnect();
    WiFi.mode(WIFI_AP);
    WiFi.softAP(apssid, appassword);
    delay(100);
    IPAddress Ip(192, 168, 7, 1);
    IPAddress NMask(255, 255, 255, 0);
    WiFi.softAPConfig(Ip, Ip, NMask);

    IPAddress myIP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(myIP);

    }

    void stamode(){
    // Connect to Wi-Fi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println(“Connecting to WiFi..”);
    }
    IPAddress ip = WiFi.localIP();
    Serial.print(“IP Address: “);
    Serial.println(ip);
    }

    void setup() {
    // Serial port for debugging purposes
    Serial.begin(115200);

    stamode();

    server.on(“/apmode”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send (200, “text/html”, “ok_apmode”);
    modeap = 1;
    });
    server.on(“/station”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send (200, “text/html”, “ok_station”);
    modesta = 1;
    });

    // Start server
    server.begin();
    }

    void loop() {
    // put your main code here, to run repeatedly:
    if(modesta == 1){
    modesta = 0;
    delay(500);
    stamode();
    }
    if(modeap == 1){
    modeap = 0;
    delay(500);
    apmode();
    }
    }

    Reply
  51. Hi George

    Thanks for the reply. I used a Firefox browser yesterday, I did not get any timeouts and the webserver continue to works for 30 hours. Success I though. As a final test I closed the webpage and tried to reconnect with no success. The serial monitor tells me the ESP32 is still running, since I added a counter in the main page and printed it out every second.

    Reply
  52. The status codes for WiFi.status() are not well documents, but I did fine this in a forum….. Serial.println(WiFi.status());
    // WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
    // WL_IDLE_STATUS = 0,
    // WL_NO_SSID_AVAIL = 1,
    // WL_SCAN_COMPLETED = 2,
    // WL_CONNECTED = 3,
    // WL_CONNECT_FAILED = 4,
    // WL_CONNECTION_LOST = 5,
    // WL_DISCONNECTED = 6

    Reply
  53. Hello J.Bredahl and Rob,

    Thanks very much for your advice and information.

    I’ll give it a try and see what happens. Will report back with the outcome.

    Thanks again.

    Regards.

    Reply
  54. Boa tarde,

    Tenho este código a trabalhar mas preciso que a uma determinada temperatura seja acionado um LED. Como faço isso?
    Penso que seja fĂĄcil, mas nĂŁo estou a conseguir.

    Obrigado!

    Reply
  55. Worked a treat.

    Thanks for a terse pragmatic and effective tutorial.

    Only snag now is the DHT 22 shows 99.9 percent humidity for a bit too long. It has been bashing about in my parts box for a year or so and I do live in Darwin and it has been pelting with tropical rain.

    Will order a new sensor and in the mean time try giving the old one the Methelated Spirits treatment.

    Otherwise Does exactly what it says on the tin…

    Very Happy …

    Reply
  56. Hi Folks,

    As promised in my previous post, I’m back to give you an update on my issue with ESPAsyncWebserver. In short, after hair pulling and nail biting for over a week and ploughing through numerous searches on the internet, I didn’t find a solution as to why the webserver stops responding. So, I’ve ditched using ESPAsyncWebserver altogether. My solution, I moved over to the IOT platform Blynk. I can now do everything that I had originally planned to do plus more !! And, the best part is that Blynk just works seamlessly and the program space used has now been reduced from 83% when using ESPAsyncWebserver to 57% running Blynk !! :)) No need for email client libraries either as Blynk does it all. Of course there are times when we need a webserver, but for my project I’m pleased I made the change. Perhaps Rui or Sara would like to do a tutorial with the ESP32 and Blynk ?

    Reply
    • Hi Rob, hopefully a solution will be found for ESPAsyncWebserver :). Post back with an update if you decide to use Blynk.

      Reply
  57. Big thanks to Rui and Sara! VERY well put together tutorials. Especially for someone new to the “hobby”. One issue: When my DHT22 gets below freezing, the reading to maximum? negative integer. For Farenheit- 5866. Same issue with Celcius. Am using the code and libraries copied from your tutorial and everything else works and displays great. Any ideas>

    Thanks,
    Mark

    Reply
  58. Hi Mark,

    “When my DHT22 gets below freezing, the reading to maximum? negative integer.”

    Negative integer?? Have you changed the variable type from float to an unsigned integer type in the function String readDHTTemperature() ? If so this is probably your problem .

    dht.readTemperature() returns a float and NOT an integer. However, if you want to return just the integer value you could change the code “return String(t);” to “return String(t, 0);” where the “0” states the number of decimals i.e. none in this case. You could also cast the output of dht.readTemperature() to a signed integer type and return the string value as normal aka int16_t t = (int16_t) dht.readTemperature();

    Hope this solves your problem.

    Regards.

    Reply
  59. Hello!

    I’m not getting any result
    could you please help with this?
    thank you so much for your support.
    and how can i connect more DHT11 maximum how many i can connect it.
    the Error is

    rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1216
    ho 0 tail 12 room 4
    load:0x40078000,len:10944
    load:0x40080400,len:6388
    entry 0x400806b4
    Connecting to WiFi..
    Connecting to WiFi..
    Connecting to WiFi..
    Connecting to WiFi

    Reply
      • I don’t know if I had the same problem. But the ESP32 would not connect to my network. I ran the example program supplied by AsyncWebServer, the simple_server. That worked. Then I retried your code and it worked! I think the fix was a call to WiFi.mode(WIFI_STA);

        Excellent tutorials on your site. Thank you!

        Reply
  60. Hi Trhere, this is a great tutorial! it tought me a lot. I do have a question if you dont mind.
    Lets say that I log all my reading to an SD card and then would like to read the file on demand and send the whole data array back to the website for plotting, how could I acheive this please? I tried a string but it has limited length. I cannot seem to get an array of say 1000 chars to pass back up in the server response to the plotting tool.

    Eg, something like this

    for(int i = 0; i < 1000; i++)
    request->send_P(200, “text/plain”, Data[i].c_str());
    next i;

    thanks in advance
    Nigel

    Reply
    • Hi.
      Here’s what I’ve done in a similar project.
      – Save the readings in JSON format in a file (for example data.txt).
      – Create a JAvaScript function that makes a request for the file when the page loads, for example /getReadings
      – Add something like this to send the file to the server when requested:
      server.on(“/getReadings”, HTTP_GET, [](AsyncWebServerRequest *request){
      request->send(SD, “/data.txt”, “text/txt”);
      });

      Handle the response using JavaScript (read the file content and place the readings on the chart). As the file gets bigger, it will take more time to load the readings. So, it is a good idea to limit the number of readings.

      I hope this helps.
      Regards,
      Sara

      Reply
      • Wow! I’m stunned at the fast reply! many many thanks.

        Ill get working on this right away.

        You replay got me looking at the source for ESPAsyncWebServer.h on github, specifically at the send overloads and not only is there the File overload but theres also a send Stream method! This opens up a world of possibilities in that we could read the file into the stream prior to sending it back in the response. That might speed larger file tranfer up a little.

        I’ll do some experimenting and thanks again Sara for the fast and great reply!

        Much Appreciated
        Br
        Nigel

        Reply
      • Sare, I just updated my code using your suggestion and it worked like a charm.

        Im using CSV file with date sample reading. I’ll post my JS code below if it helps anybody else. The service backend handler is exactly as you describe.

        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
        st = this.responseText;

        var obj;
        var t = [];

        obj = st.split(",");

        for (i = 0; i < obj.length-1; i++) {
        var tr = obj[i].split("|");
        var x = Date.parse(tr[0]);
        var y = parseFloat(tr[1]);

        t.push([x,y]);
        }

        chartHistory.series[0].setData(t);
        chartHistory.refresh();
        }

        };

        Br
        Nigel

        Reply
  61. Hello Sara
    just to say that mine runs perfectly !
    I spend couple of hours to test, to understand, to read, to try to change 1 part and retest…
    to take note for futur…
    2 next step : add second dht22 in project and saving data on a sql data base
    thank you again for sharing and keep our mind warm !
    br, Christophe

    Reply
  62. absolutely fantastic, great tutorial! very well described, and so easy to follow, I am certainly a fan of yours from now on, worked a treat
    Of all the web server projects I have tried, this is the first one to work from the IP address on my computer and Mobile, I don’t know why! but I will certainly be picking through the code to try and find out why it has not worked before!.
    Newby to micro electronics.

    Reply
    • Hi David.
      We have many other web server tutorials you can try.
      Just search for “web server” in our website search bar.
      Regards,
      Sara

      Reply
  63. Good morning Sara. I am getting the following error:
    unterminated raw string
    The highlighted area of code reads
    const char index_html[] PROGMEM = R”rawliteral(

    I’ve probably missed something but any help would be great!

    Reply
  64. Hello Sara!
    Is there possible to link the Arduino Code with an actual index.html page without writing it down (along with CSS and JavaScript) into che code that you flash on the ESP32?:/
    I’m quite new to these things so sorry for the dumb question! But I thought that maybe is there is a string of code which tells the ESP to take the HTML data from an actual file instead of having all of it together maybe it could work nicely. 😀

    Thank you very much!

    Reply
  65. Hi Guys.

    First of all i am not a HTML or CSS guy.

    I am wondering how to add switches and sliders below the Temperature and Pressure? I am doing a project which i need to monitor and manipulate in ex : Reading temperature and have a switch to enable a motor.

    I tried added like below:

    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; }
    .dht-labels{
    font-size: 1.5rem;
    vertical-align:middle;
    padding-bottom: 15px;
    }

    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px}
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border radius: 34px}
    .slider:before {position: absolute; content: “”; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}

    But it didn’t work. Or can you refer to a good site for further learning on this part

    Thanks guys!

    Reply
  66. Many thanks to Sara/Rui for this project, my second one with the ESP32 (WMOS-LOLIN).
    Using NTP getting local date/time. DHT22 sensors.

    I noticed something while testing with multiple clients connected, Sara made a remark about this some time (years) ago.
    Each time a (new) client connects, the number of requests for temp and humidity (and in my case time and date also) increases on the server, which presents timing problems as the sensors are too slow.
    So I solved this by letting the server decide when the sensors and date/time are read/determined – every 5 seconds -, save all 4 values in local server buffers/vars, and rewrite the html refreshing to read the local buffers instead of accessing the sensors – every 10 seconds as it was.
    The result is that the website refresh is very fast and the sensors are read not more than once every 5 seconds, never returning errors anymore.
    This “paradigma-shift” is possible because all values displayed on the website do not have to be accurate on the second, or even 10 seconds, including time(hh:mm) and date.

    I would like to share my code but see no option to do so.
    Kind regards
    Johan

    Reply
    • Hi.
      That’s a good alternative to our code.
      To share your code, you can share a link to pastebin or GitHub, for example.
      Regards,
      Sara

      Reply
  67. Hello,
    It doesn’t seem to work on my esp 32 i have downloaded all libraries needed and I still get this error message:

    Arduino: 1.8.15 Hourly Build 2021/08/23 12:34 (Mac OS X), Board: “DOIT ESP32 DEVKIT V1, 80MHz, 115200, None”

    DHT22_server:10:31: fatal error: ESPAsyncWebServer.h: No such file or directory
    Multiple libraries were found for “Adafruit_Sensor.h”
    compilation terminated.
    Used: /Users/michalciura/Documents/Arduino/libraries/Adafruit_sensor
    Not used: /Users/michalciura/Documents/Arduino/libraries/Adafruit_Unified_Sensor
    Not used: /Users/michalciura/Documents/Arduino/libraries/Adafruit_Sensor-master
    Multiple libraries were found for “WiFi.h”
    Used: /Users/michalciura/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6/libraries/WiFi
    Not used: /private/var/folders/wd/zr4tby711xbfw4kld_x4qg9r0000gn/T/AppTranslocation/BFBDE4CF-FF9A-4665-B79C-1292046DE926/d/Arduino.app/Contents/Java/libraries/WiFi
    exit status 1
    ESPAsyncWebServer.h: No such file or directory

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    this is the copied error message.

    Reply
  68. I have my temperature up & running.
    Can I put the ESP32 to save battery power?
    Can I retain the last upload on the website until it gets refreshed again?

    Please advise

    Reply
    • Hi.
      Make sure the credentials are correct, and that your board is relatively close to your router.
      Additionally, make sure it has proper power supply.
      Regards,
      Sara

      Reply
  69. DHT webserver problem. I’m trying to do this with VS Code and PlatformIO. I can’t find the exact libraries you specify for Arduino IDE and I’m not sure how to get them into PlatformIO.

    In platformio.ini I have the following:
    lib_deps =
    beegee-tokyo/DHT sensor library for ESPx@^1.18
    me-no-dev/ESP Async WebServer@^1.2.3
    adafruit/Adafruit DHT Unified@^1.0.0
    me-no-dev/AsyncTCP@^1.1.1
    robtillaart/DHTlib@^0.1.34
    in main.ccp I include:
    // Import required libraries
    #include <Arduino.h>
    #include <WiFi.h>
    #include <AsyncTCP.h>
    #include <ESPAsyncWebServer.h>
    //#include <Adafruit_Sensor.h>
    #include <DHT.h>

    I’m getting a error on instantiating DHT
    DHT dht(DHTPIN, DHTTYPE);

    The error message is:
    ‘DHT’ does not name a type

    I’m thinking ‘DHT’ is defined in a library and I don’t have that library.

    How can I fix this?

    Reply
  70. Hello Sarah. Can you help me understand the line of code: %TEMPERATURE% I am doing a project similar to yours and I am guided by your lines of code but it does not work. You are declaring ”t” as the variable for dht.readTemperature(); but when you declare it in line in HTML you use %TEMPERATURE%. . I don’t understand why you are doing this. I know I have to put between %_% but why not %t%. The word TEMPERATURE comes from where. Thank you

    Reply
  71. Hi Denis,
    Maybe I can help you to understand a bit more on what is going on in the code.
    The %TEMPERATURE% in the HTML page is a place holder which will be replaced by the actual value of the temperature which is in a “String” format when the web page loads. The web page requests the temperature and also the humidity in the XMLHttpRequest – look at the setInterval functions in the code. In fact %TEMPERATURE% and %HUMIDITY% could be almost anything that you choose e.g. %MYTEMP% or %MYHUMIDITY% or %CAT% or %DOG% but the most important thing is that whatever names you give them they must match with the variables in the program:-
    // Replaces placeholder with DHT values
    String processor(const String& var){
    //Serial.println(var);
    if(var == “TEMPERATURE”){
    return readDHTTemperature();
    }
    else if(var == “HUMIDITY”){
    return readDHTHumidity();
    }
    return String();
    }
    Now, you should note that this is a “String” processor and the value that is returned is a String, either the temperature or the humidity depending on what the HTML page is requesting. The functions readDHTTemperature() and readDHTHumidity() both return the temperature and humidity as strings. That is, the local variables “f” and “h” hold the temperature and humidity values as floats but they then need to be converted to strings to be returned to the HTML page – see the code lines “return String(t);” and “return String(h);”.
    As Sarah suggests, reading the tutorials fully will give you a better understanding.
    Hope this helps in the meantime.
    Regards,
    George

    Reply
  72. Hello . I sincerely thank you for answering me and for doing it so quickly. You cannot know how much I appreciate it. I will read this tutorial with great interest. And yes, George, you helped me a lot with your explanations, it’s clearer and it will surely help me understand the tutorial even more. I discovered microcontrollers about 2 years ago and programming is a hobby for me and it’s quite a challenge for me. What complicates things is I don’t speak much English so it takes longer…but that’s okay. A thousand times thank you

    Reply
    • Hi Denis. I’m pleased my explanation was of help for you to better understand how the code works. And yes, RANDOM NERD TUTORIALS is one of the best, if not THE BEST, domain for tutorials on the web. Many thanks to Sara and Rui !! I wish you all the best in your programming. Regards, George :))

      Reply
  73. Hello Rui, and Sara,
    This is a great tutorial on how to create a ESP web server that can display values on a web page. I have learn a lot for your videos and examples.
    I used your guidance to have the web page display a value from the analog input and a temperature from a DS18B20 sensor. In works great except the values do not automatically update.
    My implementation is on an ESP 8266.
    Does the auto update work on the ESP8266?
    I used the ESPAsyncTCP.h and ESPAsyncWebServer.h libraries.

    Any help or suggestions you have to offer would be appreciated.

    Reply
  74. Hellow, I’m new programming ESPC3-32, so when i’m compiling to upload the program it shows a error:
    “exit status 1
    Error compiling for board ESP32C3 Dev Module.”
    Can you helpme with this issue?

    Reply
    • maybe this can help you?
      Have you installed espessif system version 2.0.3 in board manager.
      In the tools menu select board, Boards Manager.
      type esp32 in the board manager menu.
      after installing espessif systems version 2.0.3

      In the tools menu select board, esp32 arduino and then select
      ESP32C3 Dev Module.

      Reply
  75. hi Sara, I have a problem with the display value of h, t
    sometimes h=1.00,t=1.00, sometimes t=32.70,h=72.10, sometimes fail
    how to fix

    Reply
  76. Is this code specific to the ESP32 Can I install this code on a ‘nano 33 iot’ using the WiFiNINA library?

    ( I am using different sensors but I can handle the code changes for that)

    Reply
    • Hi.
      I’m not sure… I’m not familiar with that board.
      But, it seems an Arduino board. They use different Wi-Fi libraries, and I’m not sure if the AsyncWebServer library is compatible with arduino boards.
      Regards,
      Sara

      Reply
  77. Hi there!

    I get the following output, even with another sensor.

    ESP32 Weather Report

    Temperature: 2147483647°C

    Humidity: 2147483647%

    the output numbert is not random, but 2^32 -1

    does anyone have an idea about this. Thanks a lo

    Reply
  78. Hey, first of all thanks for this tutorial.
    everything works, but i have one major problem, if the DHT is not connected to the ESP, then the ESP is connecting to the given Network. However why (checked energy and right SSID + password) when the DHT is connected to the ESP serial monitor shows:
    connecting to WiFi…
    connecting to WiFi…
    connecting to WiFi…
    if i remove the DHT its connect to WiFi, the only problem is that together it wont work
    Thanks for helping!

    Reply
  79. Hello. I am a complete novice, so it is possible that I am asking very stupid questions. But I have a Fibaro hc3 smarthome controller, and am trying to get communication with ESP32 via websocket. I get it working on the website. Fibaro hc3 can work as a websocket client. But I don’t know what to write in the code it will send out to get communication with server (ESP32)? I assume that it is the same as the PC sends from the website, but that communication is hidden from me.

    Reply
    • Hi.
      I’m not familiar with that device.
      But, if you can control in which URLs it can make requests, you just need to set the ESP32 as a server that responds to requests on certain routes.
      On the other device, you should make the requests on the ESP32 web server IP address on the routes you defined on the code.
      Both devices need to be on the same network.
      I’m sorry if this is confusing, but this is very difficult to explain when I don’t know how that device works exactly.
      Either way, I hope this helps.
      Regards,
      Sara

      Reply
      • Hi. I am impressed with how quickly you respond. I understand that it can be difficult to answer when you do not know the device. But I don’t think it’s that important. What I think I need is the exact url(?) that my PC sends when it communicates with the ESP32. If I have understood it correctly, I write the same (with the necessary adaptation) in the code for Fibaro hc3. What may be confusing is that the question ended up on the wrong subject. (I had several websites up at the same time) The question should actually be on the page https://randomnerdtutorials.com/esp32-websocket-server-arduino/. I have managed to send a one-way command from the Fibaro hc3 to an esp32 webserver. https://randomnerdtutorials.com/esp32-web-server-arduino-ide/ because there is the code I need in the url field on the web browser. But that code is, as I said, hidden on the websocket (If you think my English is weird, blame it on Google translate)

        Reply
        • Hi.
          That web server project is different from the one with WebSockets.
          Basically the first communicates via HTTP requests.
          The websocket project first establishes a connection via an HTTP request, and then all the information is exchanged via WebSocket communication (so there isn’t a URL with the parameters you want to send).
          If you want to pass parameters in the URL, you can take a look at some of other projects, for example:
          https://randomnerdtutorials.com/esp32-esp8266-input-data-html-form/ (all data is passed on the URLs) – you’ll need to adjust the code for your specific scenario.
          Regards
          Sara

          Reply
  80. Hello,

    I just built this:
    ESP32 DHT11/DHT22 Web Server – Temperature and Humidity using Arduino IDE.
    It worked first time and does so very well. Thank you for the excellent tutorial.

    Now I would to make a combination with this tutorial:
    ESP32/ESP8266: DHT Temperature and Humidity Readings in OLED Display.
    So a local display and a webserver both using the DHT values.

    Of course, I’ll make sure the same DHT22 pin is used for webserver and for the OLED version on the same ESP8266.

    Is this possible? I suppose I can just ‘merge’ both codes in IDE?
    Henry

    Reply
  81. Hi Sara/Rui
    Great tutorial for a learner like me. one quick question how do you change the colours of the icons based upon the temperature/humidity?. I have looked around online and had my noodle fried with this, any tips or links to assit me as it may simple for some but alas not me!

    Reply
  82. For the DHT11 webserver, I managed to get it all to compile and upload to my board no problem. I am getting an IP address reported and successful connection to my wifi.
    I can ping this device no problem.
    However when I put http://theipaddress into my browser I get refused connection in Chrome and invalid address in Safari.

    Any suggestions?

    David

    Reply
  83. I have always been a great enthusiast for your site and projects.

    I have to confess that when it comes to the webserver side of things I am at a bit of a loss and could really do with a bit of help to progress and get my project off the ground.

    I have successfully run both the ESP32 Control outputs and ESP32 DHT11/22 Webserver projects independently. For my project I need to be able to combine these and have sensor readings displayed and also the ability control outputs. So combining the two. I also want to add some additional sensors to the web page. Do you have any examples of how to do this?

    I have tried merging elements of the codes and adding new sensor data but have failed dismally 🙁 mainly because I don’t really understand what I am doing. I am fine with non html stuff and have created many projects previously, but never with html etc.

    Can you help me out?

    David

    Reply

Leave a Comment

Download Our Free eBooks and Resources

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