IoT Weather Station project using NodeMCU

Updated: May 2

A weather station is a place where meteorological observations can be made. The basic parameters like temperature, humidity, and pressure can be monitored using an #IoT Weather station. #NodeMCU is a combination of node and MCU. MCU stands for Microcontroller Unit. NodeMCU is an open-source firmware and development board specially used for IoT-based applications. It is the firmware for which open-source prototyping board designs are available.

To monitor the climatic conditions we can use this project IOT based weather monitoring system using NodeMCU.

Hardware Requirements:

The hardware equipment required to design an #IoTWeatherStation using NodeMCU is as follows.


1.NodeMCU:

6. Node mcu(esp 8266).
Node mcu(esp 8266)


NodeMCU is a firmware and development board. It is used in IoT-based applications. It is one of the important components of this project.


2. 20x4 LCD Display Module:

20x4 LCD Module
20x4 LCD Module



Liquid Crystal Display (#LCD) is a visual display that uses the light-modulating properties of crystals. 20X4 LCD can display 20 characters in each of four rows i.e., a total of 80 characters.



3. Jumper wires:


Jumper wires
Jumper wires

Jumper wires are used to establish connections between different components in the circuit.

4. USB cable:




USB cable
USB cable

Universal Serial Bus(USB) used to connect peripheral devices like printers, keyboards to the computer.


5.I2C board:


I2C board
I2C board

Inter-Integrated Circuit(#I2C) boards are used to attach lower-speed peripheral IC's to processors and microcontrollers over short distances.


Circuit Connection:


The below diagram shows the circuit connections.

Weather station
Weather station

Vin pin is connected to Vcc pin of LCD module, GND to the GND pin of the LCD module, D1 pin of NodeMCU is connected to Serial Clock pin of LCD module. D2 pin of NodeMCU is connected to Serial Data pin of LCD module.


Working of Iot weather reporting system using NodeMCU:


The below program is written in Arduino IDE and uploaded. After uploading the code serial monitor is opened by NodeMCU an IP address is assigned to the device and the weather information is displayed. The information related to weather can be acessed using an application called openweathermap and create nodemcu weather station openweathermap project.


Code:


#include <ESP8266WiFi.h>

The above line of code includes a basic library for the NodeMCU board.


#include <WiFiClientSecure.h>

The above line of code includes a library that provides a secure connection between a client and a server.


#include <ArduinoJson.h>

The above line of code includes a library that is used to parse the Json formatted document which will be received from the server.

#include <LiquidCrystal_I2C.h>

The above line of code includes a library that allows control LCDs.


#include <Wire.h>              // for transferring serial data 

The above line of code includes a library that is used to send a serial data and a serial clock from NodeMCU to I2C board.



const char* ssid = "vivo 1801";
const char* password = "harshit123";

The above lines of code uses two pointer type variables "ssid and password". These two variables are used to hold credentials.



const char* host = "api.openweathermap.org";
 

The variable host is used in the above line of code. This is the host from where the real time weather information is fetched for a particular location.


const int httpsPort = 443;

The variable httpsport in the above line is a communication protocol. 443 is the code for the secured version.

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "eeaa586d4f1f42f4185b7fb0f20a4cdd97477d99";

The variable pointer fingerprint which is a type of public key of a server. This is used for web request on a server.

const int Time = 600000;                               // 10 minutes in milli second
unsigned long CurrentTime , PreviousTime = 0;


String weather_Location, weather_country, weather_description;
String country;

int flag = 1;
float clouds, wind, Temperature, humidity, pressure;

The above lines of code uses some global variables like Time, CurrentTime, PreviousTime, weather_Location, weather_country, weather_description, country are defined to use in the program.

LiquidCrystal_I2C lcd(0x27, 20, 4);

An object LiquidCrystal_I2C is defined. The name of the object is lcd. The arguments 0x27, 20 and 4 represents the I2C address, columns and rows respectively.

void setup() {
  Serial.begin(115200);
  lcd.begin();
  Wire.begin(D2, D1);
  

void setup starts from above lines of code. The serial communication, the LCD, transmission of data begins in the above lines of code. D2 is the serial data and D1 is the serial clock pin.

  Serial.println();
  Serial.print("connecting to "); 

The above lines of code prints a blink line, connecting to on the serial monitor.


  lcd.clear();
  lcd.setCursor(3,1);

The above lines of code clears the LCD and the sets the cursor.

lcd.print("connecting....");
Serial.println(ssid);

The above lines of code prints "connecting...." and ssid on serial monitor.


WiFi.begin(ssid, password);

The above line of code connects NodeMCU with the internet.


 while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

If the NodeMCU is not connected then it prints "." for every 0.5 seconds.


  lcd.clear();
  lcd.setCursor(5,1);
  lcd.print("connected");

The above lines of code clears the LCD screen and sets the cursor and prints "connected".


  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);

The above lines of code prints the output that is specified.



  lcd.clear();
  lcd.setCursor(5, 1);
  lcd.print("Real Time");
  lcd.setCursor(3, 2);
  lcd.print("Weather Station");

The above lines of code clears the LCD and sets the cursor and prints the given data.

  OpenWeatherData();
  }

The above line of code calls the function OpenWeatherData().


void loop()
{
  CurrentTime = millis();
  if (CurrentTime - PreviousTime >= Time)
  {
    Serial.println(CurrentTime);
    OpenWeatherData();
    PreviousTime = CurrentTime;
  }

The above lines prints the statements as per the condition in the if statement.


  else
  {
    lcd.clear();
    lcd.setCursor(2, 1);
    lcd.print(weather_Location + ",");
    lcd.print(weather_country);
    lcd.setCursor(2, 2);
    lcd.print(weather_description);
    delay(3000);
    
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Temp  : ");
    lcd.print(Temperature-273,1);
    lcd.print((char)223);
    lcd.print("C");
    
    lcd.setCursor(0,1);
    lcd.print(" Pres  : ");
    lcd.print(pressure,1);
    lcd.print(" hPa");
    
    lcd.setCursor(0,2);
    lcd.print(" Humi  : ");
    lcd.print(humidity,1);
    lcd.print("%");
    
    lcd.setCursor(0,3);
    lcd.print(" Wind  : ");
    lcd.print(wind);
    lcd.print(" m/s");
    delay(10000);
    
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Clouds  : ");
    lcd.print(clouds,1);
    lcd.print("%");
    delay(4000);
    
  }
}

The above lines prints the statements as per the condition in the else body.


void OpenWeatherData()
{
  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);

  Serial.printf("Using fingerprint :'%s'\n", fingerprint);
  client.setFingerprint(fingerprint);

  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

This is the function OpenWeatherData() inside which "WiFiClientSecure" object is defined and the object is "client". fingerprint of a server is printed and is verified.


String url = "/data/2.5/weather?q=your_city&APPID=xxxxxxxxx YOUR APT KEY xxxxxxxxxxx";

The above line of code defines a string variable "url" that is the API key.


  Serial.print("requesting URL: ");
  Serial.println(url);

The above two lines of code prints the given string.



  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

The above lines of code explains about web request. The host here is openweathermap, User-Agent is ESP.



  Serial.println("request sent");

The above line prints "request sent" on the serial monitor.


  while (client.connected()) 
  {
    if (flag == 1)
    {
      lcd.clear();
      lcd.setCursor(4, 1);
      lcd.print("Fetching.....");
      lcd.setCursor(0, 2);
      lcd.print("Current Weather Data");
      delay(3000);
      lcd.clear();
      lcd.setCursor(7, 1);
      lcd.print("From:");
      lcd.setCursor(3, 2);
      lcd.print("openWeatherMap");
      flag = 0;
    }

The above lines of code prints the given statements if flag is 1 and after printing the details flag is set to 0.


    String line = client.readStringUntil('\n');
    if (line == "\r") 
    {
      Serial.println("headers received");
      flag = 1;
      break;
    }
  }

The above lines of code prints "headers received" if line is equal to "carriage return" and sets the flag to 1.



  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"coord\"")) {
    Serial.println("esp8266 CI successfull!");
  } else {
    Serial.println("esp8266 CI has failed");
  }

The above lines of code prints the statements as per the conditions given in if and else.


  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");

The above lines of code prints the given statements.


  line.replace('[', ' ');
  line.replace(']', ' ');

The above lines of code replaces " [ ] " with spaces to neglect errors that occur while parsing teh Json document.


  Serial.println(line);

The above line prints the data of Json formatted document.



  const int BUFFER_SIZE = 1024;

  StaticJsonDocument<BUFFER_SIZE> doc;

In the above lines of code buffer size is defined and assigned to Json document.


  char json[line.length() + 1];
  line.toCharArray(json, sizeof(json));
  json[line.length() + 1] = '\0';


  DeserializationError error = deserializeJson(doc, json);



  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }

If any error occurs the statements are printed as given in the body of if condition.



  String Location = doc["name"];
  String country = doc["sys"]["country"];
  String description = doc["weather"]["description"];
  Temperature = doc["main"]["temp"];
  humidity = doc["main"]["humidity"];
  pressure = doc["main"]["pressure"];
  wind = doc["wind"]["speed"];
  clouds = doc["clouds"]["all"];

The above lines of code prints the weather details if parsing is successful. The required information is extracted from Json document.



  weather_Location = Location;
  weather_country = country;
  weather_description = description;

The variables which are local variables are made as global variables using above lines of code.


 Serial.println(Location);
  Serial.println(country);
  Serial.println(description);
  Serial.println(Temperature);
  Serial.println(humidity);
  Serial.println(pressure);
  Serial.println(wind);
  Serial.println(clouds);
}

The above line prints the required information.


Complete code:


/*
    HTTP over TLS (HTTPS) example sketch

    This code demonstrates how to use
    WiFiClientSecure, ArduinoJson to access and parse HTTPS API.
    We fetch and display the status of real time weather
    of a particular location in India.
    Using esp8266/NodeMCU board.

    Created by HARSHIT GUPTA Electronics Hobbyist & Electronics Engineer, 2020.
    This example is in public domain.
*/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>              // for transferring serial data 

const char* ssid = "vivo 1801";
const char* password = "harshit123";

const char* host = "api.openweathermap.org";
const int httpsPort = 443;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "eeaa586d4f1f42f4185b7fb0f20a4cdd97477d99";

const int Time = 600000;                               // 10 minutes in milli second
unsigned long CurrentTime , PreviousTime = 0;

String weather_Location, weather_country, weather_description;
String country;

int flag = 1;
float clouds, wind, Temperature, humidity, pressure;

LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {
  Serial.begin(115200);
  lcd.begin();
  Wire.begin(D2, D1);
  
  Serial.println();
  Serial.print("connecting to ");
  lcd.clear();
  lcd.setCursor(3,1);
  lcd.print("connecting....");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  lcd.clear();
  lcd.setCursor(5,1);
  lcd.print("connected");

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);

  lcd.clear();
  lcd.setCursor(5, 1);
  lcd.print("Real Time");
  lcd.setCursor(3, 2);
  lcd.print("Weather Station");

  OpenWeatherData();
}


void loop()
{
  CurrentTime = millis();
  if (CurrentTime - PreviousTime >= Time)
  {
    Serial.println(CurrentTime);
    OpenWeatherData();
    PreviousTime = CurrentTime;
  }
  else
  {
    lcd.clear();
    lcd.setCursor(2, 1);
    lcd.print(weather_Location + ",");
    lcd.print(weather_country);
    lcd.setCursor(2, 2);
    lcd.print(weather_description);
    delay(3000);
    
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Temp  : ");
    lcd.print(Temperature-273,1);
    lcd.print((char)223);
    lcd.print("C");
    
    lcd.setCursor(0,1);
    lcd.print(" Pres  : ");
    lcd.print(pressure,1);
    lcd.print(" hPa");
    
    lcd.setCursor(0,2);
    lcd.print(" Humi  : ");
    lcd.print(humidity,1);
    lcd.print("%");
    
    lcd.setCursor(0,3);
    lcd.print(" Wind  : ");
    lcd.print(wind);
    lcd.print(" m/s");
    delay(10000);
    
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Clouds  : ");
    lcd.print(clouds,1);
    lcd.print("%");
    delay(4000);
    
  }
}

void OpenWeatherData()
{
  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);

  Serial.printf("Using fingerprint :'%s'\n", fingerprint);
  client.setFingerprint(fingerprint);

  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

  String url = "/data/2.5/weather?q=your_city&APPID=xxxxxxxxx YOUR APT KEY xxxxxxxxxxx";

  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent");

  while (client.connected()) 
  {
    if (flag == 1)
    {
      lcd.clear();
      lcd.setCursor(4, 1);
      lcd.print("Fetching.....");
      lcd.setCursor(0, 2);
      lcd.print("Current Weather Data");
      delay(3000);
      lcd.clear();
      lcd.setCursor(7, 1);
      lcd.print("From:");
      lcd.setCursor(3, 2);
      lcd.print("openWeatherMap");
      flag = 0;
    }
    String line = client.readStringUntil('\n');
    if (line == "\r") 
    {
      Serial.println("headers received");
      flag = 1;
      break;
    }
  }

  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"coord\"")) {
    Serial.println("esp8266 CI successfull!");
  } else {
    Serial.println("esp8266 CI has failed");
  }
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");

  line.replace('[', ' ');
  line.replace(']', ' ');

  Serial.println(line);

  const int BUFFER_SIZE = 1024;

  StaticJsonDocument<BUFFER_SIZE> doc;

  char json[line.length() + 1];
  line.toCharArray(json, sizeof(json));
  json[line.length() + 1] = '\0';

  DeserializationError error = deserializeJson(doc, json);

  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }

  String Location = doc["name"];
  String country = doc["sys"]["country"];
  String description = doc["weather"]["description"];
  Temperature = doc["main"]["temp"];
  humidity = doc["main"]["humidity"];
  pressure = doc["main"]["pressure"];
  wind = doc["wind"]["speed"];
  clouds = doc["clouds"]["all"];


  weather_Location = Location;
  weather_country = country;
  weather_description = description;

  Serial.println(Location);
  Serial.println(country);
  Serial.println(description);
  Serial.println(Temperature);
  Serial.println(humidity);
  Serial.println(pressure);
  Serial.println(wind);
  Serial.println(clouds);
}



Video By: Harshit Gupta




See Also:


Home automation using TV Remote

Interfacing Keypad with Arduino using TinkerCAD

IoT Smart Bulb using NodeMCu and Blynk App


Follow us:


Please do follow us i.e., #learnelectronicsindia to get daily updates about new blogs, videos, courses, quizzes and contests.


Facebook | LinkedIn | Instagram | Youtube | Website | Gmail