NodeMCU Data Logger to Upload Data on Webserver

ESP8266 Web Server Data Logger using DHT11 Sensor

You mostly have seen Data logging web server with real-time graphs and tables on ThingSpeak and other IoT platforms. But we can also create our own webserver and can update the data in real-time, we previously created many webservers using different boards. Here we will also create ESP8266 Web Server Data Logger using DHT11 Sensor. Here the temperature and humidity data will be updated on the webpage using AJAX.

 

AJAX (Asynchronous JavaScript and XML) allows for automatic updating of websites by sharing tiny volumes of data with the server in the background without refreshing the complete webpage. This ensures that portions of a web page will be changed without reloading the whole website. So let’s get started!

 

Components Required

  • NodeMCU ESP8266
  • DHT11 Sensor
  • Jumper Wires

 

DHT11 sensor is used to measure temperature and humidity and generally used to create weather stations.

 

Circuit Diagram

Circuit Diagram for ESP8266 data logger is given below:

NodeMCU Data Logger Circuit Diagram

 

Wiring the DHT11 to the NodeMCU is easy. VCC and GND pins of DHT11 is connected to 3.3V and GND NodeMCU while the Data pin of DHT is connected to D5 (GPIO 14) pin of NodeMCU.

ESP8266 Data Logger

 

Programming NodeMCU ESP8266 for Data logging

Complete code for NodeMCU Temperature Logger can be found at the end of the page. Here we are explaining the complete code line by line:

 

Before moving directly on coding, install required libraries, the ESP8266 libraries are pre-installed on IDE; you only need to install the DHT11 library that you can download from here.

 

After installing the library, including all the required libraries.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "DHT.h"

 

Now in the next lines, enter your Wi-Fi name and Password.

const char* ssid = "Wi-Fi Name";
const char* password = "Password";

 

Then define the type of DHT sensor and the pin where the sensor is connected. If you are using DHT22, then change the DHT type to DHT22. In my case, the DHT sensor is connected to the GPIO14 (D5) of NodeMCU.

#define LED 2 //Onboard LED
#define DHTTYPE DHT11 // DHT 11
uint8_t DHTPin = 14; 
DHT dht(DHTPin, DHTTYPE);

 

The handleRoot function is executed when we open the Webpage inbrowser using the NodeMCU IP address.

void handleRoot()
{
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}

 

The next function that is readData() is used to read the data from the DHT11 sensor and send it to the Webpage. In this loop, NodeMCU stores the DHT11 values into two float variables: temperature & humidity, after this it converts the float variables into the string and store their data into another string variable ‘Data’ and send this to Webpage whenever requested.

void readData()
{
String data = "{\"Temperature\":\""+ String(temperature) +"\", \"Humidity\":\""+ String(humidity) +"\"}";
digitalWrite(LED,!digitalRead(LED)); 
server.send(200, "text/plane", data); 
delay(2000);
temperature = dht.readTemperature(); 
humidity = dht.readHumidity(); 
 Serial.print(humidity, 1);
 Serial.print(temperature, 1);
}

 

Inside the void setup() function, we initialized the baud rate, DHT sensor using .begin() function, Webpage using server.begin() function and then connect the module with the Wi-Fi using the Wi-Fi name and password.

Serial.begin(115200);
pinMode(DHTPin, INPUT);
dht.begin();
 WiFi.begin(ssid, password);
server.begin();

 

The first function is used to call the 'handleRoot' function when a client requests URI (Uniform Resource Identifier) "/" while the second function is used to call the 'readData' function when a POST request is made to URI "/readData"

server.on("/", handleRoot);     
server.on("/readData", readData); 

 

The void loop() function continuously listen for HTTP requests from clients

void loop(void)
{
  server.handleClient();          
}

 

HTML Code for Webpage

The <!DOCTYPE html > tag is used to tell the web browser that which version of html we are using to write the html code. This tag is written at the top. Everything, that in this code is written after that.

<!doctype html>

 

The code written between the <html> </html> tags will be read by the browser. The <head> </head> tag is used to define the title, header line, and style of the web page. The data written in the <title></title> is the name of the tab in the browser. The <style></style> tag is used to style the table and the header lines.

<html>
<head>
  <title>Data Logger</title>
  <h1 style="text-align:center; color:red;">Iot Design Pro</h1>
    <style>
  canvas{
    -moz-user-select: none;
……………………..
……………………..
……………………..
</style>
</head>

 

The <script></script> tag is used to include the jQuery. The jQuery is the JavaScript library. The getData() function inside the <script> tag is used to get the data from NodeMCU and update the data table.

function getData() 
{
…………..
…………..

 

The XMLHttpRequest object is used to request data from the web server. All browsers have a built-in XMLHttpRequest object to request data from a server. Using the XMLHttpRequest, we can update a web page without reloading the page, request data from the server, receive data from a server, and can send data to a server. Here we are using this object to get the temperature and humidity data from the NodeMCU and update the data table without refreshing the web page.

var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     //Push the data in array
  var time = new Date().toLocaleTimeString();
  var txt = this.responseText;
  var obj = JSON.parse(txt); 
      Tvalues.push(obj.Temperature);
      Hvalues.push(obj.Humidity);
      timeStamp.push(time);
……………………….
…………….................
……………………….

 

The open() and send() methods of the XMLHttpRequest object are used to send a request to a server. The syntax for xhttp.open() is given below:

xhttp.open(method, url, async)
Where:
method is the type of request (GET or POST) 
url is the server location
async is used to define asynchronous or synchronous, where true is asynchronous and false is synchronous
xhttp.open("GET", "readData", true); 
xhttp.send();

 

Testing the NodeMCU Data Logger

Finally, connect the DHT11 sensor with NodeMCU and upload the code. After uploading the program in NodeMCU, open serial monitor with 115200 baud rate and get the IP address of NodeMCU. Open it in the web browser, and your Webpage will look like this:

NodeMCU Data Logger Working

A working video and complete code are given below.

Code

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "DHT.h"
//SSID and Password of your WiFi router
const char* ssid = "Galaxy-M20";
const char* password = "ac312124";
#define LED 2       //On board LED
#define DHTTYPE DHT11 // DHT 11
uint8_t DHTPin = 14; 
DHT dht(DHTPin, DHTTYPE); 
float humidity, temperature;
ESP8266WebServer server(80); //Server on port 80
const char MAIN_page[] PROGMEM = R"=====(
<!doctype html>
<html>
<head>
  <title>Data Logger</title>
  <h1 style="text-align:center; color:red;">Iot Design Pro</h1>
  <h3 style="text-align:center;">NodeMCU Data Logger</h3>
  <style>
  canvas{
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
  }
  /* Data Table Styling*/ 
  #dataTable {
    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    width: 100%;
    text-align: center;
  }
  #dataTable td, #dataTable th {
    border: 1px solid #ddd;
    padding: 8px;
  }
  #dataTable tr:nth-child(even){background-color: #f2f2f2;}
  #dataTable tr:hover {background-color: #ddd;}
  #dataTable th {
    padding-top: 12px;
    padding-bottom: 12px;
    text-align: center;
    background-color: #050505;
    color: white;
  }
  </style>
</head>
<body>
<div>
  <table id="dataTable">
    <tr><th>Time</th><th>Temperaure (&deg;C)</th><th>Humidity (%)</th></tr>
  </table>
</div>
<br>
<br>  
<script>
var Tvalues = [];
var Hvalues = [];
var timeStamp = [];
setInterval(function() {
  // Call a function repetatively with 5 Second interval
  getData();
}, 5000); //5000mSeconds update rate
 function getData() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     //Push the data in array
  var time = new Date().toLocaleTimeString();
  var txt = this.responseText;
  var obj = JSON.parse(txt); 
      Tvalues.push(obj.Temperature);
      Hvalues.push(obj.Humidity);
      timeStamp.push(time);
  //Update Data Table
    var table = document.getElementById("dataTable");
    var row = table.insertRow(1); //Add after headings
    var cell1 = row.insertCell(0);
    var cell2 = row.insertCell(1);
    var cell3 = row.insertCell(2);
    cell1.innerHTML = time;
    cell2.innerHTML = obj.Temperature;
    cell3.innerHTML = obj.Humidity;
    }
  };
  xhttp.open("GET", "readData", true); //Handle readData server on ESP8266
  xhttp.send();
}
</script>
</body>
</html>

)=====";
 

void handleRoot() {
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}

void readData() {

 String data = "{\"Temperature\":\""+ String(temperature) +"\", \"Humidity\":\""+ String(humidity) +"\"}";
 digitalWrite(LED,!digitalRead(LED)); //Toggle LED on data request ajax
 server.send(200, "text/plane", data); //Send ADC value, temperature and humidity JSON to client ajax request
 delay(2000);
 temperature = dht.readTemperature(); 
 humidity = dht.readHumidity(); 
 Serial.print(humidity, 1);
 Serial.print(temperature, 1);
}

void setup ()
{
  Serial.begin(115200);
  Serial.println();
  pinMode(DHTPin, INPUT);
  dht.begin();
 
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");
  //Onboard LED port Direction output
  pinMode(LED,OUTPUT); 
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
 
  server.on("/", handleRoot);      //Which routine to handle at root location. This is display page
  server.on("/readData", readData); //This page is called by java Script AJAX
 
  server.begin();                  //Start server
  Serial.println("HTTP server started");
}

void loop(void){
  server.handleClient();          //Handle client requests
}
 

Video

16 Comments

The "complete Code" is missing everything from the handleroot function to the HTML Code. Also, there is no line by line description about the following in the "complete code":
float humidity, temperature;
ESP8266WebServer server(80); //Server on port 80
const char MAIN_page[] PROGMEM = R"=====(

Any way possible you could fix this or explain what's going on here?

Hi Asheesh,
I am looking at producing a controller for a UV light which works on timer, motion sensor or manual on? Product is for a disinfection unit which I am developing but I am not a control engineer. Would you be able to contact me and may be we can work out something together?
Thanks and regards,
ashveen

when I upload the code and get the IP address of the nodemcu and past into the web browser the browser says can't reach the page but the serial monitor display "HTTP server started" what is the fault please tell me it is urgent

Hello have I use Arduino IDE 1.8.13 for run code .
I got the porblem error as below . what should i do ??

Exception (3):
epc1=0x4000bf64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x40243295 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffd00 end: 3fffffc0 offset: 0190
3ffffe90: 00000001 3ffee40c 40243295 4020aedb
3ffffea0: 3ffef700 00000001 3ffef6bc 40203222
3ffffeb0: 3fffff00 3fffff10 80fffef0 402012c4
3ffffec0: 00000001 4020d940 3ffffef0 4020d90e
3ffffed0: 3fffff10 3ffee428 3ffef6bc 401000e1
3ffffee0: 3ffef6bc 3ffee428 3ffef6bc 402012fc
3ffffef0: 3ffe0000 3fff0000 801003e8 800016d3
3fffff00: 3ffef6bc 3ffee428 3ffee3e8 4020338a
3fffff10: 001a002f 80000000 81feff00 0000008f
3fffff20: 80005054 f5a67c23 40100300 3ffee62c
3fffff30: 3ffee428 3ffee504 3ffee544 00000001
3fffff40: 00000001 3ffef6bc 00000003 402065e5
3fffff50: 00000001 3ffee40c 3ffee3e8 3ffee62c
3fffff60: 00000001 3ffee40c 3ffee3e8 40203633
3fffff70: 00000000 00000000 3ffee504 40207179
3fffff80: 00000000 00000000 00000001 4010033c
3fffff90: 3fffdad0 00000000 3ffee5ec 402036d4
3fffffa0: 3fffdad0 00000000 3ffee5ec 4020be58
3fffffb0: feefeffe feefeffe 3ffe84f0 40100e11
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

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

load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld

Hi,
Im trying to use your code in this article but im running into a issue that i cant seem to find a solution for.
compiling and uploading the code is just fine.
the esp starts and in the serial i see my ip and that the server is running.
but when i connect to the ip adress i get a exeption.

this is the exeption i get.
i found many other people on the internet that had simmilar issues but sofar the solutions provided on other sides are not working for me.

I hope you guys can help me get this problem resolved

Exception (3):
epc1=0x4000bf64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x4023dd91 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffd00 end: 3fffffc0 offset: 0190
3ffffe90: 00000001 3ffee3cc 4023dd91 40205d5b
3ffffea0: 3ffef628 00000001 3ffef78c 402031f6
3ffffeb0: 3fffff00 3fffff10 80fffef0 40201b9c
3ffffec0: 00000001 40208aa8 3ffffef0 40208a76
3ffffed0: 3fffff10 3ffee3e8 3ffef78c 401000e1
3ffffee0: 3ffef78c 3ffee3e8 3ffef78c 40201bd4
3ffffef0: 3ffe0000 3fff0000 80fee55c 80000030
3fffff00: 3ffef78c 3ffee3e8 3ffee3a8 4020335e
3fffff10: 0000002f 80000000 81ff0000 0000008f
3fffff20: 80005054 3c378920 40100200 00002de2
3fffff30: 3ffee3e8 00000000 00000001 00000001
3fffff40: 00000001 3ffef78c 3ffee3a8 3ffee55c
3fffff50: 00000001 3ffee3cc 3ffee3a8 3ffee55c
3fffff60: 00000001 3ffee3cc 3ffee3a8 40203607
3fffff70: 00000000 00000000 00001388 80ef0061
3fffff80: 00000000 00000000 00000001 40100170
3fffff90: 3fffdad0 00000000 3ffee51c 402036a8
3fffffa0: 3fffdad0 00000000 3ffee51c 40206ce0
3fffffb0: feefeffe feefeffe 3ffe84f0 40100c45
<<<stack<<<

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

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

load 0x4010f000, len 3584, room 16
tail 0
chksum 0xb0
csum 0xb0
v2843a5ac
~ld

Best regards,

ShermyBoss

Ah I found the solution to this problem
I decoded the MSG above my post.

It says delete the PROGMEM right after MAIN_page[] and that did the trick for me.
I now can reach the website from the esp12f.

thanks for the solution guys

Dude, this is not a data logger. It is rather a data viewer. Once you close the page, everything is gone. And btw, you could use a websocket , because you don;t have to do the damn polling. It is much more elegant. Data logging would require persisting the data somewhere (a.k.a creating a log entry)