Humidity, Temperature and Pressure are three basic parameters to build any Weather Station and to measure environmental conditions. We have previously built a Digital Thermometer web server using NodeMCU and this time we are extending it to Weather Station using ESP12E NodeMCU. In this project, we will measure Humidity, Temperature and Pressure parameters and display them on the web server, which makes it a IoT based Weather Station where the weather conditions can be monitored from anywhere using the Internet.


In this NodeMCU Weather Station we will use our NodeMCU in Station mode and will make a web server for weather monitoring. A similar kind of IoT Weather Station using Raspberry Pi is built previously.

Components Required

  1. NodeMCU
  2. DHT11 sensor
  3. BMP180 sensor
  4. Breadboard
  5. Jumper Wires

DHT11 Temperature and Humidity Sensor

DHT11 module features a humidity and temperature complex with a calibrated digital signal output means DHT11 sensor module is a combined module for sensing humidity and temperature which gives a calibrated digital output signal. DHT11 gives us very precise value of humidity and temperature and ensures high reliability and long term stability. This sensor has a resistive type humidity measurement component and NTC type temperature measurement component with an 8-bit microcontroller inbuilt which has a fast response and cost effective and available in 4-pin single row package.
DHT11 Sensor

DHT11 module works on serial communication i.e. single wire communication. This module sends data in form of pulse train of specific time period. Before sending data to arduino it needs some initialize command with a time delay. And the whole process time is about 4ms.
Check various other projects using DHT11 Sesnor:

BMP180 Pressure Sensor

It is a barometric pressure sensor and it works with an I2C interface. This sensor measures the absolute pressure of the air around it. The pressure value depends on both the weather and altitude. It depends on how you interpret the data, and can easily monitor changes in the weather, measure the altitude, or any other tasks that require an accurate pressure reading.
BMP180 Pressure Sensor

It has 5 pins: I2C pins, Vcc, Gnd and IO. Only 4 pins are used normally. Fifth pin labeled as IO allows us to alter the I/O voltage for very low voltage microcontrollers. It is disabled by default, you can leave this pin disconnected.

Circuit Diagram

Circuit diagram for NodeMCU Weather Station is given below:
 Circuit Diagram for IoT Weather Station using NodeMCU



Following are the connections
SCL of BMP180 -> SCL of Nodemcu (pin D1)
SDA of BPM180 -> SDA of Nodemcu (pin D2)
Data pin of DHT11 -> D3 of Nodemcu (GPIO 0)
Vcc of BMP180 and DHT11 -> 3.3v of Nodemcu
GND of BPM180 and DHT11 -> GND of Nodemcu
Circuit Hardware for IoT Weather Station using NodeMCU

Code and Explanation

Here We will use Arduino IDE to program ESP12. So, make sure you have downloaded ESP8266 board files. If there is no ESP8266 boards in the tool menu then follow the previous tutorials on NodeMCU.
Complete code with a demonstration Video for this Weather Station Project using NodeMCU is given at the end of the project.

For the coding part, we need Four libraries ESP8266WiFi, DHT (for DHT sensor), SFE_BMP180 (for BMP180) and Wire(for I2C).
Download these libraries from these links: , and install them from Include library in sketch menu.
#include <ESP8266WiFi.h>
#include "DHT.h"
#include <SFE_BMP180.h>
#include <Wire.h>

Then, we initialize variables and make instances for DHT, BMP180, Wi-Fi name, Wi-Fi password and some other variables used in the code. Define Pin for DHT sensor, we are using GPIO 0 (D3) here. Value of altitude variable depends on your location.
You can Google your location’s altitude. Alternatively, you can find your location altitude by knowing pressure in your area. The code for getting altitude is given in the examples of BMP180 library.
#define ALTITUDE 431.0
#define DHTPIN 0    
#define DHTTYPE DHT11  
SFE_BMP180 pressure;
DHT dht(DHTPIN, DHTTYPE);
const char* ssid     = "***"; // Your ssid
const char* password = "******2"; // Your Password

..

Next, we declare an object of WifiServer library, so we can access its functions. The argument for the instance formed will be port number where the server is listening. Since 80 is the default port for HTTP, we will use this value.
WiFiServer server(80);

In Void setup() function, we will initialize the baud rate , dht sensor and BMP180 using .begin() function then connect the module with the Wi-Fi using WiFi.begin(ssid, password); function.
void setup() {
 Serial.begin(115200);
 delay(100);
  dht.begin();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);

..

In void loop() function, we will get the temperature in Celsius and Fahrenheit and store this data in different variables using dht.read() function. Then we will get the pressure using pressure.sealevel(); function, it has two arguments namely sea level pressure and altitude. Pressure will be in millibar. Then, print this data on serial monitor.
void loop() {
   status = pressure.getPressure(P,T);
        if (status != 0)
        {
   p0 = pressure.sealevel(P,ALTITUDE);
          Serial.print("relative (sea-level) pressure: ");
          Serial.print(p0,2);
          Serial.print(" mb, ");
}
float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
..
.

Next, we will design our web page using html and send each line using client.println() function. 
WiFiClient client = server.available();
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");  // the connection will be closed after completion of the response
client.println("Refresh: 10");  // update the page after 10 sec

To decorate your page you can use CSS to style the text and background. You can change the properties in the below lines.
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<style>html { font-family: Cairo; display: block; margin: 0px auto; text-align: center;color: #333333; background-color: #ccffb3;}");

We will make division using <div> tag for each parameter i.e. Pressure, Temp and Humidity and will define different properties for these parameters.
..
..
client.println("<div class=\"side_adjust text1\">Humidity:</div>");
client.println("<div class=\"side_adjust data1\">");
client.print(h);
client.println("<div class=\"side_adjust text1\">%</div>");
client.println("</div>");

Similarly, make the division class for temperature and pressure. Finally close the html and body tag.
client.println("</body>");
client.println("</html>");
client.println();

Full code is given in the end of this tutorial.

Testing the NodeMCU Weather Station

Now Connect the NodeMCU ESP12E with the laptop and choose the board and port correctly and then hit the Upload button.
Make sure your laptop or Smartphone share same Wi-Fi network as the NodeMCU. After uploading the code, open the serial monitor. Make the baud rate of serial monitor as 115200. You will see the IP address in the monitor, just copy this IP and paste it in the browser.
Testing NodeMCU Weather Station

You will see a webpage in your browser as shown below. This page will be refresh automatically after every 10 seconds. You can change this time in code.
IoT based Weather Webserver using NodeMCU

This is how you can build your own weather Station and can monitor the Temperature, Humidity and Pressure of your home or office from anywhere in the world using your computer or SmartPhone.
Code
#include <ESP8266WiFi.h>
#include "DHT.h"
#include <SFE_BMP180.h>
#include <Wire.h>
 
#define ALTITUDE 431.0
#define DHTPIN 0     // what digital pin we're connected to
#define DHTTYPE DHT11   // DHT 11
 
SFE_BMP180 pressure;
DHT dht(DHTPIN, DHTTYPE);
const char* ssid     = "awesome"; // Your ssid
const char* password = "awesome12"; // Your Password
 
char status;
double T,P,p0,a;
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(100);
dht.begin();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
 
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
 
Serial.println("");
Serial.println("WiFi is connected");
server.begin();
Serial.println("Server started");
 
 
Serial.println(WiFi.localIP());
  if (pressure.begin())
    Serial.println("BMP180 init success");
  else
  {
    Serial.println("BMP180 init fail\n\n");
    while(1); // Pause forever.
  }
  delay(1000);
}
 
void loop() {
    status = pressure.getPressure(P,T);
    if (status != 0)
    {
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, ");
}
 
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
  
WiFiClient client = server.available();
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");  // the connection will be closed after completion of the response
client.println("Refresh: 10");  // update the page after 10 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<style>html { font-family: Cairo; display: block; margin: 0px auto; text-align: center;color: #333333; background-color: #ccffb3;}");
client.println("body{margin-top: 50px;}");
client.println("h1 {margin: 50px auto 30px; font-size: 50px; text-align: center;}");
client.println(".side_adjust{display: inline-block;vertical-align: middle;position: relative;}");
client.println(".text1{font-weight: 180; padding-left: 15px; font-size: 50px; width: 170px; text-align: left; color: #3498db;}");
client.println(".data1{font-weight: 180; padding-left: 80px; font-size: 50px;color: #3498db;}");
client.println(".text2{font-weight: 180; font-size: 50px; width: 170px; text-align: left; color: #ff6600;}");
client.println(".data2{font-weight: 180; padding-left: 150px; font-size: 50px;color: #ff6600;}");
client.println(".text3{font-weight: 180; padding-left: 15px; font-size: 50px; width: 170px; text-align: left; color: #0066ff;}");
client.println(".data3{font-weight: 180; padding-left: 80px; font-size: 50px;color: #0066ff;}");
client.println(".data{padding: 10px;}");
client.println("</style>");
client.println("</head>");
client.println("<body>");
client.println("<div id=\"webpage\">");   
client.println("<h1>ESP Weather Station server</h1>");
client.println("<div class=\"data\">");
client.println("<div class=\"side_adjust text1\">Humidity:</div>");
client.println("<div class=\"side_adjust data1\">");
client.print(h);
client.println("<div class=\"side_adjust text1\">%</div>");
client.println("</div>");
client.println("<div class=\"data\">");
client.println("<div class=\"side_adjust text2\">Temperature:</div>");
client.println("<div class=\"side_adjust data2\">");
client.print(t);
client.println("<div class=\"side_adjust text2\">*C</div>");
client.print(f);
client.println("<div class=\"side_adjust text2\">F</div>");
client.println("</div>");
client.println("<div class=\"data\">");
client.println("<div class=\"side_adjust text3\">Pressure:</div>");
client.println("<div class=\"side_adjust data3\">");
client.print(p0,2);
client.println("<div class=\"side_adjust text3\">mb</div>");
client.println("</div>");
client.println("</div>");
client.println("</body>");
client.println("</html>");
 delay(4000);
}