Live Weather Station using NodeMCU ESP8266 with dashboard IOT

Have you ever been curious to know whats the live weather status exactly where you live, many people use weather application by choosing the city name  to get the data from weather stations but that’s not mostly accurate to your live location. So here we brought an interesting project to make a live weather station at home with ESP8266 – 12E based nodeMCU and monitor temperature, humidity, Barometric pressure and rainfall status  over local web server. Follow the below instructions to learn about the sensors used and interfacing them to build the awesome final device.

Lets see what are the items required to build this.

Hardware Requirements:

  • NodeMCU ESP8266
  • DHT11 temperature and humidity sensor or latest DHT22 with high accuracy.
  • BMP180 or BMP280 Barometric pressure sensor
  • Rain sensor module FC-37
  • 2 X Resistors 4.7 K ohm
  • USB cable for code upload
  • Few connection wires

Software Requirements:

  • Arduino IDE

Sensor details:

DHT11 temperature and humidity sensor

This sensor is an easy to use temperature and humidity sensor with attractive cheap price. It allows us to get both temperature and humidity data from single board instead of using two.

It comes in two types one is only the sensor with 4 pins on it and the other one is sensor fitted on a PCB which includes an 5 kΩ pull up resistance and a on board LED which indicates the data usage. Both has same functionality only new difference is the price and connection pins.

  • It works in the voltages between 3 volts and 5 volts
  • with the temperature measurement range from 0 to 50 degree centigrade.
  • Accuracy ± 2 ° C
  • Resolution Temperature: 0.1 ° C
  • Humidity measurement range: 20% to 90% RH.
  • Humidity measurement accuracy: 5% RH.
  • Humidity Resolution: 1% RH
  • Sensing time: 1 sec.

Rain Sensor:

This type of sensor detects the presence of rain due to the variation in the conductivity of the sensor when it comes into contact with water. There are several similar sensor models, such as the FC-37 and the YL-83.

Constructively they are simple sensors. There are two contacts, connected to conductive tracks interlocked with each other at a small distance, without contact between them. When water is deposited on the surface, both conductors are placed in electrical contact, which can be detected by a sensor.

Both models are shipped with a standard measurement plate with the LM393 comparator, which allows the reading to be obtained both as an analog value and digitally when a certain threshold is exceeded, which is regulated through a potentiometer located on the plate itself.

Analog values ​​measured range from 0 for a fully soaked plate to 1023 for a completely dry plate .

BMP180 Barometric Pressure Sensor:

bmp180 sensor is a printed circuit board, which includes a high-precision absolute barometric / atmospheric pressure sensor (atmospheric pressure is the force per unit area that air exerts on Earth’s surface), it has a measurement range between 300 and 1100 hPa (Hecto Pascal) and an error margin of 0.03 hPa, it also has a temperature sensor and by means of software it allows calculating the altitude with respect to the sea.

The pressure sensor is based on piezo-resistive technology with high efficiency, linearity and long duration, it has a power range of between 1.8 volts and 3.6 volts dc (direct current), so if we are going to use it With a micro controller running at 5 volts, we will need level adapters on the SDA (data line) and SCL (clock line) pins of the I2C bus.

I currently have the model on the left and the central one, both are the same, except that the central module has an integrated 3.3 volt source, it can be powered at 5 volts on the pin marked Vcc, but it can also be powered with 3.3 volts on the pin marked 3.3 volts.

Interfacing DHT11, BMP180 and rain sensor with NodeMCU to built Weather station

Here we are interfacing the sensors with nodemcu both dht11 and BMP 180 are connected directly without using any external resistance but for rain sensor we are using 2 4.7K ohm resistors. For detailed connections refer the below image for a schematic diagram.

Live Weather Station using NodeMCU ESP8266 circuit diagram

Source code:

In this project we have two codes 1) Main arduino code 2) front view dashboard code which in html format.

As we cannot upload the html code directly we need to convert it into a compatible format so we converted into index.h file format.

Libraries needed:

index.h source code

Copy the code into note pad and save it with name as index.h and save it in the same directory where the main .ino file is located and don’t forget to choose all files instead of .txt.

const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>Live Weather Station Dashboard</title>
</head>
<style>
@import url(https://fonts.googleapis.com/css?family=Montserrat);
@import url(https://fonts.googleapis.com/css?family=Advent+Pro:400,200);
*{margin: 0;padding: 0;}
 
body{
  background:#544947;
  font-family:Montserrat,Arial,sans-serif;
}
h2{
  font-size:14px;
}
.widget{
  box-shadow:0 40px 10px 5px rgba(0,0,0,0.4);
  margin:100px auto;
  height: 330px;
  position: relative;
  width: 500px;
}
 
.upper{
  border-radius:5px 5px 0 0;
  background:#f5f5f5;
  height:200px;
  padding:20px;
}
 
.date{
  font-size:40px;
}
.year{
  font-size:30px;
  color:#c1c1c1;
}
.place{
  color:#222;
  font-size:40px;
}
.lower{
  background:#00A8A9;
  border-radius:0 0 5px 5px;
  font-family:'Advent Pro';
  font-weight:200;
  height:130px;
  width:100%;
}
.clock{
  background:#00A8A9;
  border-radius:100%;
  box-shadow:0 0 0 15px #f5f5f5,0 10px 10px 5px rgba(0,0,0,0.3);
  height:150px;
  position:absolute;
  right:25px;
  top:-35px;
  width:150px;
}
 
.hour{
  background:#f5f5f5;
  height:50px;
  left:50%;  
  position: absolute;
  top:25px;
  width:4px;
}
 
.min{
  background:#f5f5f5;
  height:65px;
  left:50%;  
  position: absolute;
  top:10px;
  transform:rotate(100deg);
  width:4px;
}
 
.min,.hour{
  border-radius:5px;
  transform-origin:bottom center;
  transition:all .5s linear;
}
 
.infos{
  list-style:none;
}
.info{
  color:#fff;
  float:left;
  height:100%;
  padding-top:10px;
  text-align:center;
  width:25%;
}
.info span{
  display: inline-block;
  font-size:40px;
  margin-top:20px;
}
.weather p {
  font-size:20px;padding:10px 0;
}
.anim{animation:fade .8s linear;}
 
@keyframes fade{
  0%{opacity:0;}
  100%{opacity:1;}
}
 
a{
 text-align: center;
 text-decoration: none;
 color: white;
 font-size: 15px;
 font-weight: 500;
}
</style>
<body>
 
 
<div class="widget"> 
  <div class="clock">
    <div class="min" id="min"></div>
    <div class="hour" id="hour"></div>
  </div>
  <div class="upper">
    <div class="date" id="date">21 March</div>
    <div class="year">Temperature</div>
    <div class="place update" id="temperature">23 &deg;C</div>
  </div>
  <div style="text-align: center;"><a href="https://www.circuitschools.com" style="align:center">www.circuitschools.com</a></div>
  <div class="lower">    
    <ul class="infos">
      <li class="info temp">
        <h2 class="title">TEMPERATURE</h2>
        <span class='update' id="temp">21 &deg;C</span>
      </li>
      <li class="info weather">
        <h2 class="title">PRESSURE</h2>
        <span class="update" id="pressure">0 mb</span>
      </li>
      <li class="info wind">
        <h2 class="title">RAIN</h2>
        <span class='update' id="rain">0%</span>
      </li>
      <li class="info humidity">
        <h2 class="title">HUMIDITY</h2>
        <span class='update' id="humidity">23%</span>
      </li>
    </ul>
  </div>
</div>
 
<script>
setInterval(drawClock, 2000);
    
function drawClock(){
    var now = new Date();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();
    
    //Date
    var options = {year: 'numeric', month: 'long', day: 'numeric' };
    var today  = new Date();
    document.getElementById("date").innerHTML = today.toLocaleDateString("en-US", options);
    
    //hour
    var hourAngle = (360*(hour/12))+((360/12)*(minute/60));
    var minAngle = 360*(minute/60);
    document.getElementById("hour").style.transform = "rotate("+(hourAngle)+"deg)";
    //minute
    document.getElementById("min").style.transform = "rotate("+(minAngle)+"deg)";
 
    //Get Humidity Temperature and Rain Data
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
      var txt = this.responseText;
      var obj = JSON.parse(txt); //Ref: https://www.w3schools.com/js/js_json_parse.asp
        document.getElementById("rain").innerHTML = obj.Rain + "%";
        document.getElementById("temperature").innerHTML = Math.round(obj.Temperature) + "&deg;C";
        document.getElementById("temp").innerHTML = Math.round(obj.Temperature) + "&deg;C";
        document.getElementById("humidity").innerHTML = Math.round(obj.Humidity) + "%";
        document.getElementById("pressure").innerHTML = Math.round(obj.Pressuremb) + " mb";
      }  
    };
   xhttp.open("GET", "readADC", true); //Handle readADC server on ESP8266
   xhttp.send();
}
</script>
</body>
</html>
)=====";

Live Weather Station Main Code 

Copy the below code and paste it in the Arduino IDE and save it in the same directory where index.h was saved previously.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <SFE_BMP180.h>
#include <Wire.h>
 
#include "index.h" //Our HTML dashboard page
#include "DHTesp.h" //DHT11 Library for ESP
 
#define LED 2 //On board LED
#define DHTpin 5 //D1 of NodeMCU is GPIO5
 
SFE_BMP180 pressure;
 
#define ALTITUDE 542.0 // Your Altitude in meters search in google
 
DHTesp dht;
 
//SSID and Password of your WiFi router
const char* ssid = "Your_WiFi_SSID";
const char* password = "Your_WiFi_password";
 
ESP8266WebServer server(80); //Server on port 80
 
void handleRoot() {
String s = MAIN_page; //Read HTML contents
server.send(200, "text/html", s); //Send web page
}
 
float humidity, temperature;
 
void handleADC() {
char status;
double T,P,p0,a;
double Tdeg, Tfar, phg, pmb;
 
status = pressure.startTemperature();
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
status = pressure.getTemperature(T);
if (status != 0)
{
// Print out the measurement:
Serial.print("temperature: ");
Serial.print(T,2);
Tdeg = T;
Serial.print(" deg C, ");
Tfar = (9.0/5.0)*T+32.0;
Serial.print((9.0/5.0)*T+32.0,2);
Serial.println(" deg F");
 
status = pressure.startPressure(3);
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
status = pressure.getPressure(P,T);
if (status != 0)
{
// Print out the measurement:
Serial.print("absolute pressure: ");
Serial.print(P,2);
pmb = P;
Serial.print(" mb, ");
phg = P*0.0295333727;
Serial.print(P*0.0295333727,2);
Serial.println(" inHg");
 
p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)
Serial.print("relative (sea-level) pressure: ");
Serial.print(p0,2);
Serial.print(" mb, ");
Serial.print(p0*0.0295333727,2);
Serial.println(" inHg");
 
a = pressure.altitude(P,p0);
Serial.print("computed altitude: ");
Serial.print(a,0);
Serial.print(" meters, ");
Serial.print(a*3.28084,0);
Serial.println(" feet");
}
else Serial.println("error retrieving pressure measurement\n");
}
else Serial.println("error starting pressure measurement\n");
}
else Serial.println("error retrieving temperature measurement\n");
}
else Serial.println("error starting temperature measurement\n");
 
 
int rain = analogRead(A0);
 
//Create JSON data
String data = "{\"Rain\":\""+String(rain)+"\",\"Pressuremb\":\""+String(pmb)+"\",\"Pressurehg\":\""+String(phg)+"\", \"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(dht.getMinimumSamplingPeriod());
 
humidity = dht.getHumidity();
temperature = dht.getTemperature();
 
Serial.print("H:");
Serial.println(humidity);
Serial.print("T:");
Serial.println(temperature); //dht.toFahrenheit(temperature));
Serial.print("R:");
Serial.println(rain);
}
 
void setup()
{
Serial.begin(115200);
Serial.println();
 
// dht11 Sensor
 
dht.setup(DHTpin, DHTesp::DHT11); //for DHT11 Connect DHT sensor to GPIO 17
pinMode(LED,OUTPUT);
 
//BMP180 Sensor
if (pressure.begin())
Serial.println("BMP180 init success");
else
{
Serial.println("BMP180 init fail\n\n");
while(1); // Pause forever.
}
 
WiFi.begin(ssid, password); //Connect to your WiFi network
Serial.println("");
 
// 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("/readADC", handleADC); //This page is called by java Script AJAX
 
server.begin(); //Start server
Serial.println("HTTP server started");
}
 
void loop()
{
server.handleClient(); //Handle client requests
}

Working of Live Weather station using ESP8266

After connecting and uploading the code to the nodeMCU open serial monitor to find the IP address assigned to the device just copy the address and paste in any web browser connected in the same network to display the Live weather monitoring dashboard.

You can also view the weather data in the serial monitor.

Live Weather Station using NodeMCU ESP8266 dashboard output