DHT22 sensor web server on ESP8266

 Author:   Posted on:   Updated on:  2019-12-29T14:34:34Z

Display DHT11/DHT22 readings on web page of ESP8266 server. It's easy to build a temperature controller with configurable actions.

There are plenty of projects using digital temperature and humidity sensors such as DHT11 or DHT22 and various development boards. I'll try to make this one a bit different. A common thing that I didn't like about projects using sensors and web servers is the way most users choose to update sensor data. The easiest way is to use a refresh meta tag in the HTML of the web page.

I don't like this. Asking the browser to refresh the document means to request it again from the server and render it on the client's device. I'll use in this article Javascript code which will request a new sensor reading from the server running on the development board and update the specific HTML element. As additional features, I'll add some user-selectable actions when readings reach a threshold.

DHT22 sensor web server on ESP8266

You need for this project a WiFi development board. I will use ESP8266 NodeMcu, but since I will do the programming with Arduino IDE, you can use a different ESP8266 board and even ESP32. A sensor is needed. I will use DHT11/DHT22, but you can utilize whatever you want (not limited to temperature sensors). To make this project, you need to know a little C and Javascript programming. You also need basic HTML and CSS knowledge.

Hardware

Digital temperature and humidity sensors type DHT11/DHT22/AM2302 make use of a custom protocol implemented in software with the help of a library. All they require is a single communication line to the development board. I chose to wire the data pin of my sensor breakout board to D3 of the NodeMcu.

DHT22 wired to ESP8266 NodeMcu on the breadboard

DHT22 wired to ESP8266 NodeMcu on the breadboard

Server page

I started this project with the design of the HTML page served to the clients. Avoid using external resources available on the internet (CSS frameworks, web fonts or images) unless you are sure clients have access to the internet. If the ESP8266 is going to be in a closed network or WiFi AP mode, external resources will not be available. The start of HTML and the head section look like this:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>ESP8266 Sensor Server</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA/4QAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAiIgEQAiAQASAAEAEgAhABAgAQASACARAAIBEQIiAQASACAQACABABIAIAEAAgARACIAABAAIAAAAAAAAAAAAAAAAAAAAAEREAERAAEAAQAAAAAQAQABAAAAABABAAERAAARAAERAQAAAQAAAQARAAABAAABABEREAAREAERCQmQAAZ2YAAGtmAACdEQAAZrsAAGbdAACZ7gAA//8AAP//AAAMdwAAf7cAAH+3AAAecQAAffYAAH32AAAOMQAA" />
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="script.js"></script>
</head>

This is a standard HTML 5 file, with references to local external Javascript and CSS. These files will be stored on the SPI flash of the board. Next, the body contains heading and an element which will hold sensor readings. The inner HTML of that element will be set by Javascript code.

<body>
    <div class="main">
        <h1>Sensor Server</h1>
        <h2>Parameters</h2>
        <div id="readings">Loading...</div>

I could have ended the file now, by closing body and html tags. Yet, I want to add two configurable actions depending on sensor readings. So, I created a form with a pair of checkboxes, combo box and numeric input. Those will be used to trigger an action (which can be the state of a pin) when the condition is true.

<form action="/set" method="get">
            <p class="rd">
                <label class="switch">
                    <input type="checkbox" name="tc" value="1"><span class="slider round"></span></label> Temperature
                <br/>Condition:
                <select name="to">
                    <option value="0">smaller</option>
                    <option value="1">greater</option>
                </select> than
                <br/>Threshold:
                <input type="number" name="tt" min="-25.0" max="50.0" value="24"> °C</p>

            <p class="rd">
                <label class="switch">
                    <input type="checkbox" name="hc" value="1"><span class="slider round"></span></label> Humidity
                <br/>Condition:
                <select name="ho">
                    <option value="0">smaller</option>
                    <option value="1">greater</option>
                </select> than
                <br/>Threshold:
                <input type="number" name="ht" min="0" max="100" value="60"> %</p>

            <div class="btn">
                <input type="submit" value="Save">
            </div>
        </form>

With some styling, the checkboxes are turned into sliding buttons. There are two actions, one for the temperature and the other for humidity.

External files

The external files are the CSS style for the webpage and the Javascript which requests temperature and humidity at every 2.5 seconds. I won't go into CSS details. Here are the contents of the script file.

setInterval(readSensor, 2500);

function readSensor() {
 var req = new XMLHttpRequest();

 req.onreadystatechange = function () {
  if (this.readyState == 4 && this.status == 200) {
   document.getElementById("readings").innerHTML = req.responseText;
  }
 };

 req.open("GET", "read", true);
 req.send();
}

It contains a single function that triggers a server request. This function is automatically called every 2.5 s by setInterval(readSensor, 2500);. I made a folder named data in the Arduino sketch folder and used the method described in this post to upload the CSS and JS to flash.

Arduino code

The sketch contains a function mainPage() which creates a string containing the plain HTML and sends it to clients upon request. It checks and adjusts the actual state of the elements in the form. The function that reads sensor data sends the readings as HTML.

void readSensor() {
  currt = dht.readTemperature();
  currh = dht.readHumidity();

  String response = "<p>Current temperature</p><p class=\"reading\">";
  response += String(currt, 1);
  response += "&nbsp;&#176;C</p><p>Relative humidity</p><p class=\"reading\">";
  response += String(currh, 0);
  response += "&nbsp;%</p>";

  //server.sendHeader("Access-Control-Allow-Origin", String("*"), true);
  server.send(200, "text/html", response);

There is also a function which processes data sent from the HTML form using GET method. After it parses arguments, it redirects clients to main server page.

void setParams() {
  if (server.hasArg("tc")) {
    if (server.arg("tc") == "1") actt = 1;

    if (server.hasArg("to")) {
      if (server.arg("to") == "1") cont = 1;
      else cont = 0;
    }

    if (server.hasArg("tt")) {
      thrt = server.arg("tt").toInt();
    }
  }
  else actt = 0;

  if (server.hasArg("hc")) {
    if (server.arg("hc") == "1") acth = 1;

    if (server.hasArg("ho")) {
      if (server.arg("ho") == "1") conh = 1;
      else conh = 0;
    }

    if (server.hasArg("ht")) {
      thrh = server.arg("ht").toInt();
    }
  }
  else acth = 0;

  server.sendHeader("Location", String("/"), true);
  server.send(301, "text/plain", "");
}

For the external resources, server.streamFile() is used to send the content of those files after being read from SPIFFS. The entire sketch has about 200 lines of code and can be found on GitHub, along with the external CSS and JS files.

Overview

This little program is intended as a starting point for sensor projects. It handles WiFi connection, basic server setup, streaming files from SPIFFS and parsing client's arguments on the server. You have to modify the following functions to suit your needs.

void temperatureAction(bool conditionMet) {
  if (conditionMet) Serial.println("Temperature threshold reached");
}

void humidityAction(bool conditionMet) {
  if (conditionMet) Serial.println("Humidity threshold reached");
}
Server page displayed on Android smartphone

Server page displayed on Android smartphone

You may use different sensors and add additional functions for data logging etc. The server is completely standalone and it does not depend on internet connection to display and function properly. The URL of the development board is set to http://sensor.local using MDNS. Unfortunately, MDNS is not available on Android platform and you'll have to know the IP of the board in order to connect to the server. The web page is designed for mobile clients.

1 comment :

Please read the comments policy before publishing your comment.