IoT Based Weather Monitoring System Using Arduino

In this post we are going to construct an IoT based weather monitor system using Arduino which can report us weather status like atmospheric pressure, temperature, humidity, air quality, light intensity etc. of your locality in real time and the data from the sensors are logged to an IoT cloud service called Thingspeak for monitoring and analysis.

We will see:

  • What is IoT based weather monitoring system?
  • Why we need an IoT based weather monitoring system.
  • Types of sensors involved in weather monitoring.
  • Block diagram of IoT based weather monitoring system.
  • Circuit diagram and description.
  • How to setup your Thingspeak account?
  • Program code for Arduino and ESP8266.
  • How to upload data to generic ESP8266?
  • Prototype images.
  • How to operate the circuit?

What is an IoT based weather monitoring system?

It is a system that involves in acquiring weather and environment data using advanced electronic sensors and sending them to a web server via internet for real time weather monitoring and storage of data for future analysis and study.  

Why we need an IoT based weather monitoring system?

  1. Ease of monitoring your local weather conditions in real time from anywhere in the world.
  2. For storing weather and environment data for short and long term for studying weather pattern changes and to understand how human induced climate change affected your local weather.
  3. Easy deployment of the setup for monitoring local atmospheric conditions and microclimates for weather forecasting and prediction.

Types of sensors involved in weather monitoring:

We can find wide spectrum of electronic sensors involved in weather monitoring system depending on the kind of application.

For example:

Farmers need to know the temperature, relative humidity, soil moisture, rain fall etc. to enhance their crop production and the following type of sensors are utilized to obtain the data:

  • Temperature sensor.
  • Humidity / hygrometer sensor.
  • Soil moisture sensor.
  • Rain sensor etc.

For an airplane pilot he/she needs to know wind speed, wind direction, atmospheric pressure, precipitation, visibility etc. before they takeoff and they use the following sensors:

  • Barometric sensor – for measuring atmospheric pressure.
  • Anemometer – for measuring wind speed.
  • Rain sensor.
  • Visibility sensor – for measuring visibility during snow, rain, storm etc.

In conclusion, the sensors used for monitoring weather depends on the type application we going to deploy for.

Block diagram of IoT based weather monitoring system:

Block diagram - IoT based weather monitoring system
Block diagram – IoT based weather monitoring system

We are going to develop the weather monitoring system using the above illustrated blocks. The brain of the project is an Arduino board and the surrounding blocks are digital and analog sensors for acquiring local weather and environment data.

A generic ESP8266 is used for interfacing the circuit setup with internet via 2.4 GHz Wi-Fi band. The ESP8266 sends the sensor data to a cloud server where the data gets updated in real time and also gets stored for future analysis. We are utilizing a 16 x 2 LCD display to showcase the sensor data, so that we can observe real-time data locally.

Full circuit diagram for IoT based weather monitoring system:

IoT basIoT based weather monitoring system using Arduinod weather moniotring system using Arduino
IoT based weather monitoring system using Arduino

The above circuit consists of the following modules:

  • 5V / 3.3V Power supply regulator.
  • Arduino Uno.
  • 16 x 2 display with I2C adapter module.
  • DHT11 temperature & humidity sensor.
  • MQ-135 sensor air quality sensor.
  • BMP180 – Barometric sensor.
  • Light depend resistor (LDR).
  • Generic ESP8266 Wi-Fi module.

Now, let’s explore what each of the module does and how it is interfaced with other modules.

Power supply 5V and 3.3V:

Power supply 5V/3.3V
Power supply 5V/3.3V

The above illustrated module takes 9V to 12V DC supply from a wall adapter and converts to 5V and 3.3V for providing power to Arduino board and sensors.

There are multiple 5V and 3.3V supply outputs in this module and you need to connect 5V supply to 5V sensor modules and 3.3V supply to 3.3V sensor modules. Mismatching will lead to malfunction of the respective modules / sensors.   

A button is provided on the module to turn ON/OFF the 5V / 3.3V output. A green LED indicates that the module is powered ON. There is also a USB power output but we won’t be using it for this project.

16 x 2 LCD display:

I2C LCD display
I2C LCD display

We are utilizing a 16 x 2 LCD display to showcase sensor data locally and it can display 16 alphanumeric characters in 2 rows.

An I2C display module is used in this project to reduce the number of wires that connect from microcontroller to LCD display to four; otherwise we need to connect 16 wires.

I2C display module operates on I2C bus and has the following four pins:

  • SDA – Serial data.
  • SCL – Serial clock.
  • Vcc – 5V.
  • GND – ground.

The Vcc pin connects to 5V of the power supply module and GND connects to GND of the supply, the SDA connects to A4 of Arduino and SCL connects to A5.

The I2C module has backlight control, by removing the jumper we can turn off the backlight and vice-versa. You can adjust the display contrast by rotating the potentiometer (blue color on the module) using a small screw driver.

DHT11 temperature and humidity module:

DHT11 Sensor
DHT11 Sensor

DHT11 is a digital sensor responsible for collecting temperature and humidity data from your surroundings. It has three terminals namely:

  • Vcc
  • GND
  • Data

Vcc connects to 5V supply, GND connects to GND and data pin connects to A0 of Arduino.

Note: The pin diagram for DHT11 module could differ from manufacture to manufacture and it is recommended to take a good look at your module to see which pins are Vcc, GND and Data before you apply power to the circuit.

BMP180 barometric sensor:

BMP180 barometric sensor
BMP180 barometric sensor

The above illustrated module is a barometric sensor which is capable of measuring atmospheric data; it can give out data like, atmospheric pressure at ground level, atmospheric pressure at sea level and altitude.

We will be only extracting atmospheric pressure data at ground and sea level to display it on the LCD, but we will be sending only the atmospheric pressure data at ground level to Thingspeak server, which is the relevant data for your locality.

It has the following pins:

  • SDA – Serial data.
  • SCL – Serial clock.
  • Vcc – 3.3V.
  • GND – ground.

Care must be taken while connecting the supply to this module as it operates on 3.3V DC and 5V will kill the module. It operates on I2C bus, same as I2C display adapter module.

MQ-135 air quality sensor module:

MQ-135 is an analog air quality sensor which takes air samples from your surroundings and gives out an analog voltage at its output terminal. MQ-135 can detect the following gases:

  • NH3
  • NOx
  • Alcohol
  • Benzene
  • Smoke, CO2 etc.

The operating voltage of MQ-135 is 5V and consumes around 160mA, the sensor has built-in heater for heating the sensor for its normal operation and if the sensor is exposed to strong wind we may get incorrect readings. The sensor takes typically around 3 to 5 minutes to reach optimum temperature depending on surrounding air flow.

The sensor has good sensitivity to detect the above mentioned gases, but the disadvantage is it cannot differentiate which gas or gases have been detected.

Generic ESP8266 module:

Genric ESP8266
Generic ESP8266

The above illustrated module is called generic ESP8266 which is responsible for connecting the weather monitoring system to internet. This module is inserted on a breakout board adapter so that ESP8266 can be interfaced on a breadboard.

Pin diagram of ESP8266:

Pin Diagram of ESP8266
Pin Diagram of ESP8266

ESP8266 is not a just another ordinary module, it has a full-fledged 32-bit microcontroller which requires a program code to function. We will be using a programmer to upload the code to this ESP8266 module which we will see in the later part of this article. It operates on 3.3V and communicates on serial interface with Arduino.

Light depend resistor – LDR:

Photoresistor
Photoresistor

LDR is responsible for collecting data about the intensity of light at your surroundings and it is a passive analog sensor.

The LDR is essentially a resistor that is sensitive to the light, when higher intensity light falls on the photosensitive surface its resistance drops and when less light is received its resistance increases.

In other words, the resistance is inversely proportional to the intensity of the light on the photosensitive surface of LDR. 

This concludes all the modules and sensors used in the circuit setup.

Program code for Arduino:              

I2C LCD library: Click here

DHT library: Click here

BMP180 library: Click here

/******************** Copyright of Electronics-project-hub.com *****************************/
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <dht.h>
#include <Wire.h>
#include <BMP180.h>
dht DHT;
LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial mySerial(10, 11);
BMP180 myBMP(BMP180_ULTRAHIGHRES);
#define DHT11_PIN A0
#define mq135_pin A2
#define LDR A1
void ReadDHT(void);
void ReadBMP(void);
void ReadAir(void);
void send_data(void);
bool BMP_flag = 0;
bool DHT_flag = 0;


void setup()
{
  mySerial.begin(115200);
  pinMode(mq135_pin, INPUT);
  pinMode(LDR, INPUT);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("  IoT  Weather  ");
  lcd.setCursor(0, 1);
  lcd.print("Monitor System");
  delay(1500);
}

void loop()
{
  ReadDHT();
  ReadBMP();
  ReadAir();
  Readlight();
  send_data();
}

void  ReadDHT(void)
{
  lcd.clear();
  int chk = DHT.read11(DHT11_PIN);
  switch (chk)
  {
    case DHTLIB_OK:
      DHT_flag = 1;
      lcd.setCursor(0, 0);
      lcd.print("Temp: ");
      lcd.print(DHT.temperature, 1);
      lcd.print(" *C");
      lcd.setCursor(0, 1);
      lcd.print("Humi: ");
      lcd.print(DHT.humidity, 1);
      lcd.print(" %");
      break;
    case DHTLIB_ERROR_CONNECT:
      lcd.setCursor(0, 0);
      lcd.print("NO DHT11 SENSOR");
      lcd.setCursor(0, 1);
      lcd.print("     FOUND!     ");
      break;
    case DHTLIB_ERROR_CHECKSUM:
    case DHTLIB_ERROR_TIMEOUT:
    case DHTLIB_ERROR_ACK_L:
    case DHTLIB_ERROR_ACK_H:
    default:
      DHT_flag = 0;
      lcd.setCursor(0, 0);
      lcd.print("  DHT11 SENSOR  ");
      lcd.setCursor(0, 1);
      lcd.print("     ERROR      ");
      break;
  }
  delay(2000);
}

void ReadBMP(void)
{
  lcd.clear();
  if (myBMP.begin() != true)
  {
    lcd.setCursor(0, 0);
    lcd.print(" BMP180  SENSOR ");
    lcd.setCursor(0, 1);
    lcd.print("    NOT FOUND   ");
    BMP_flag = 0;
    delay(2000);
  }
  else
  {
    BMP_flag = 1;
    lcd.setCursor(0, 0);
    lcd.print("Pa(Grnd):");
    lcd.print(myBMP.getPressure());
    lcd.setCursor(0, 1);
    lcd.print("Pa(sea) :");
    lcd.print(myBMP.getSeaLevelPressure(115));
  }
  delay(2000);
}

void ReadAir(void)
{
  int airqlty = 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("AIR QUALITY:");
  airqlty = analogRead(mq135_pin);
  lcd.print(map(analogRead(mq135_pin), 0, 1024, 99, 0));
  lcd.print("%");
  lcd.setCursor(0, 1);
  if (airqlty <= 180)
    lcd.print("GOOD!");
  else if (airqlty > 180 && airqlty <= 225)
    lcd.print("POOR");
  else if (airqlty > 225 && airqlty <= 300)
    lcd.print("VERY BAD");
  else
    lcd.print("TOXIC");
  delay(2000);
}

void Readlight(void)
{
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("LIGHT :");
  lcd.print(map(analogRead(LDR), 0, 1024, 0, 99));
  lcd.print("%");
  lcd.setCursor(0, 1);
  lcd.print("****************");
  delay(2000);
}

void send_data()
{
  mySerial.print('*'); // Starting char
  if (DHT_flag == 1)
  {
    mySerial.print(DHT.temperature, 0); //2 digit data
    mySerial.print(DHT.humidity, 0); //2 digit data    
  }
  else
  {    
    mySerial.print("0000"); // Send dummy data
  }
  if (BMP_flag == 1)
  {
    mySerial.print(myBMP.getPressure()); //5 digit data
  }
  else
  {
    mySerial.print("00000");// Send dummy data
  }
  mySerial.print(map(analogRead(LDR), 0, 1024, 0, 99)); //2 digit data
  mySerial.print(map(analogRead(mq135_pin), 0, 1024, 99, 0)); //2 digit data
  mySerial.println('#'); // Ending char
}
/******************* Copyright of Electronics-project-hub.com ****************************/

Program code for Generic ESP8266

Download Thingspeak Library: Click here

// ----------(c) Electronics-project-hub-------- //
#include "ThingSpeak.h"
#include <ESP8266WiFi.h>

//------- WI-FI details ----------//
char ssid[] = "SSID"; //SSID here
char pass[] = "PASSWORD"; // Password here
//--------------------------------//

//----------- Channel details ----------------//
unsigned long Channel_ID = 123456; // Your Channel ID
const char * myWriteAPIKey = "ABC123CDE456"; //Your write API key
//-------------------------------------------//

const int Field_Number_1 = 1;
const int Field_Number_2 = 2;
const int Field_Number_3 = 3;
const int Field_Number_4 = 4;
const int Field_Number_5 = 5;
String value = "";
int value_1 = 0, value_2 = 0, value_3 = 0, value_4 = 0, value_5 = 0;
WiFiClient  client;

void setup()
{
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);
  internet();
}

void loop()
{
  internet();
  if (Serial.available() > 0)
  {
    delay(100);
    while (Serial.available() > 0)
    {
      value = Serial.readString();
      if (value[0] == '*')
      {
        if (value[14] == '#')
        {
          value_1 = ((value[1] - 0x30) * 10 + (value[2] - 0x30));
          value_2 = ((value[3] - 0x30) * 10 + (value[4] - 0x30));
          value_3 = ((value[5] - 0x30) * 10000 + (value[6] - 0x30) * 1000 + (value[7] - 0x30) * 100 + (value[8] - 0x30) * 10 + (value[9] - 0x30));
          value_4 = ((value[10] - 0x30) * 10 + (value[11] - 0x30));
          value_5 = ((value[12] - 0x30) * 10 + (value[13] - 0x30));
        }
      }
    }
  }
  upload();
}

void internet()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    while (WiFi.status() != WL_CONNECTED)
    {
      WiFi.begin(ssid, pass);
      delay(5000);
    }
  }
}

void upload()
{
  ThingSpeak.writeField(Channel_ID, Field_Number_1, value_1, myWriteAPIKey);
  delay(15000);
  ThingSpeak.writeField(Channel_ID, Field_Number_2, value_2, myWriteAPIKey);
  delay(15000);
  ThingSpeak.writeField(Channel_ID, Field_Number_3, value_3, myWriteAPIKey);
  delay(15000);
  ThingSpeak.writeField(Channel_ID, Field_Number_4, value_4, myWriteAPIKey);
  delay(15000);
  ThingSpeak.writeField(Channel_ID, Field_Number_5, value_5, myWriteAPIKey);
  delay(15000);
  value = "";
}
// ----------(c) Electronics-project-hub-------- //

Insert your Wi-Fi credentials here the code:

//------- WI-FI details ----------//
char ssid[] = "SSID"; //SSID here
char pass[] = "PASSWORD"; // Passowrd here
//--------------------------------//

Insert your Thingspeak credentials here:

//----------- Channel details ----------------//
unsigned long Channel_ID = 123456; // Your Channel ID
const char * myWriteAPIKey = "ABC123CDE456"; //Your write API key
//-------------------------------------------//

How to upload code to generic ESP8266 module:

  1. You need to download ESP8266 board package.
  2. You need an ESP8266 programmer board.

1) How to download ESP8266 board package?

Preferences
Preferences
  • Paste the URL on the box and click “OK”.
  • Now go to Tools > Board > Boards Manager.

 A window will popup:

boards manager
boards manager
  • Type “ESP8266” on the box as shown and you will get installation option, select the latest version and click install.
  • Now the IDE will download the necessary packages and this could take more than 5 minute to complete.
  • Now go to Tools > Board > ESP8266 boards > select “Generic ESP8266”.
  • Now, copy the given ESP8266 program code and paste it on to Arduino IDE software.
  • Now press compile button (Green tick button). The compilation of code may take more than couple of minutes so be patient. If the compilation failed please check whether have you selected the “Generic ESP8266 Module” in the board option or not.
  • After successful compilation of code, now it’s time to upload the code to ESP8266.

2) USB ESP8266 Programmer:

ESP8266 Programmer
ESP8266 Programmer

The above illustrated USB device is used for programming the generic ESP8266 module.

Please note that two pins on the programmer must be shorted before you upload the code, otherwise you will get errors while uploading.

Now insert the ESP8266 on the programmer and plug it to your PC’s USB port, like this and click upload:

ESP8266 Programmer
ESP8266 Programmer

Once you successfully uploaded the code, you will the below info on your IDE:

Now, you may insert the ESP8266 on your main circuit setup.

How to setup your Thingspeak account for receiving data?

  • To send sensor data to Thingspeak, you need a Thingspeak account and you can sign-up here.
  • Create a new channel and do the following to your Thingspeak channel:
Thingspeak channel settings
Thingspeak channel settings
  • Scroll down and press save.
  • Please take note of your channel ID and you need to copy and insert the ID to the ESP8266 code.
  • Now go to API key tab and you will see “write API” and “read API” keys. Write API key is a secret code for writing data to your Thingspeak channel.
  • You need copy and paste the write API key to the ESP8266 code.

Prototype images of IoT based weather monitoring system:

IoT based weather monitoring system
IoT based weather monitoring system
IoT based weather monitoring system
IoT based weather monitoring system
IoT based weather monitoring system
IoT based weather monitoring system

How to operate the IoT based weather monitoring system:

  • Make sure that you have connected all the wirings properly and all the modules are connected.
  • Plug a 9V to 12V DC adapter to the power supply module’s DC socket and press the ON switch.
  • You will see sensor data on the LCD cycling between sensors as shown below:

DHT11 temperature and humidity:

BMP180 atmospheric pressure at ground and sea level (unit is Pa):

MQ-135 Air quality sensor:

LDR sensor – intensity of the light:

Lower percentage indicates low light intensity and higher the percentage indicates higher light intensity.

Please note that air quality and light intensity values are between 0 and 100% and no unit. Also please note that MQ-135 sensor needs to heat up for its proper functioning, so initially while the sensor is heating up it will throw incorrect values and incorrect quality status like toxic or poor.

Data on Thingspeak:

  • DHT11 sensor:

BMP180 and LDR:

MQ-135 sensor:

Note: Initially zero value will get updated on all the 5 fields on Thingspeak and after that real time data starts updating. 

If you have any questions regarding this project, feel free to ask us in the comment, you will get a guaranteed reply from us.

My nick name is blogthor, I am a professional electronics engineer specialized in Embedded System. I am a experienced programmer and electronics hardware developer. I am the founder of this website, I am also a hobbyist, DIYer and a constant learner. I love to solve your technical queries via comment section.