Project tutorial
GSM-Based Weather Monitoring and Prediction Device

GSM-Based Weather Monitoring and Prediction Device © CC BY

Smart weather prediction device which send data to wunderground and receives the predicted 10 day forecast.

  • 1,600 views
  • 2 comments
  • 10 respects

Components and supplies

About this project

This project About predicting weather by creating a PWS (Personal Weather Station) and send data to Wunderground. From Wunderground the predicted data is received by API. Everything done here is wireless by using GSM SIM800A module.

Step1:

Making the connections ready.

# Mega to TFT: just fix the tft screen to Mega as shown below. (Using Adapter is optional)

# Mega to BMP280: To SDA and SCA of the Mega.

# Mega to DHT11: Pin 2 of Mega.

# GSM Module: RX and TX to RX1 and TX1 of Mega.

Step2:

Create an account in Weather underground and add a PWS by registering. Then subscribe for API for receiving data.

Step3:

After uploading the code you will find the results like listed below.

Thanks guys.

If you have any doubts or clarifications feel free to post it. The is too big and a little hard to understand it. Needs more time to work. Have a nice day.

Code

CodeArduino
#define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h>
const char apn[]  = "bsnlnet";
const char user[] = "";
const char pass[] = "";
#define SerialAT Serial1
TinyGsm modem(SerialAT);



#include <UTFT.h>
#include <tinyFAT.h>
#include <UTFT_tinyFAT.h>
UTFT myGLCD(CTE32HR,38,39,40,41);
UTFT_tinyFAT myFiles(&myGLCD);
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern uint8_t Grotesk16x32[];
extern uint8_t GroteskBold32x64[];
extern unsigned int logo[0x3F60];


#include <Wire.h>
#include <Adafruit_BMP085.h> 
#include "DHT.h"
#define DHTPIN 2 // SO CONNECT THE DHT11/22 SENSOR TO PIN D4 OF THE NODEMCU
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP085 bmp;                    // BMP Pressure Sensor


//wunderground UPLOAD
char SERVER[] = "rtupdate.wunderground.com";           // Realtime update server - RapidFire
//char SERVER [] = "weatherstation.wunderground.com";  //standard server
char WEBPAGE [] = "GET /weatherstation/updateweatherstation.php?";
char ID [] = "ICOIMBAT6";
char PASSWORD [] = "e2us54xz";
const int port = 80;
int DEBUG = 0;      // DEBUG counter; if set to 1, will write values back via serial




//wunderground download
#include <ArduinoJson.h>
const char server[] = "api.wunderground.com";    // name address for Weather Underground (using DNS)
const String myKey = "4e450941e7eee1eb";  //See: http://www.wunderground.com/weather/api/d/docs (change here with your KEY)
const String myFeatures = "forecast";   //See: http://www.wunderground.com/weather/api/d/docs?d=data/index&MR=1
const String myCountry = "IN";        //See: http://www.wunderground.com/weather/api/d/docs?d=resources/country-to-iso-matching
const String myCity = "Coimbatore";      //See: http://www.wunderground.com/weather/api/d/docs?d=data/index&MR=1
const int buffer_size = 300;  
const int buffer=400;
char* conds[]={"\"local_epoch\":","\"weather\":","\"temp_c\":","\"relative_humidity\":","\"wind_dir\":","\"wind_kph\":","\"pressure_mb\":","\"feelslike_c\":"};
int num_elements = 8;  // number of conditions you are retrieving, count of elements in conds
int num_elements_fr = 16; // number of forecast you are retrieving, count of elements in forecast

char* forecast[]={"\"celsius\":","\"celsius\":","\"icon\":","\"pop\":","\"celsius\":","\"celsius\":","\"icon\":","\"pop\":","\"celsius\":","\"celsius\":","\"icon\":","\"pop\":","\"celsius\":","\"celsius\":","\"icon\":","\"pop\":"};
char* forecast_rename[]={"\"celsius_h_0\":","\"celsius_l_0\":","\"icon_0\":","\"pop_0\":","\"celsius_h_1\":","\"celsius_l_1\":","\"icon_1\":","\"pop_1\":","\"celsius_h_2\":","\"celsius_l_2\":","\"icon_2\":","\"pop_2\":","\"celsius_h_3\":","\"celsius_l_3\":","\"icon_3\":","\"pop_3\":"}; //rename for same data name.
char* weekdayNames[]={"Sunday   ", "Monday   ", "Tuesday  ", "Wednesday", "Thursday ", "Friday   ", "Saturday "};
char close_brace ='}';
char comma = ',';
char* iconArray[]={"chancerain", "chancesleet", "chancetstorms", "clear", "cloudy", "partlycloudy", "flurries", "fog", "hazy", "mostlycloudy", "mostlysunny", "partlysunny", "rain", "sleet", "snow", "sunny", "tstorms"};
String sdFileName;
String sdFileName2;
String sdFileName3;
const char* iconName
;
const char* iconName2;
const char* iconName3;

unsigned long WMillis = 0;



void setup() {
  // Set console baud rate
  Serial.begin(115200);
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(115200);
  delay(300);


 myGLCD.InitLCD(0);

  file.initFAT();

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
     myGLCD.clrScr();
    myGLCD.fillScr(VGA_WHITE);
    myFiles.loadBitmap(10, 120, 300, 200, "w11.raw");
    delay(5000);
    myGLCD.clrScr();
    myGLCD.fillScr(VGA_WHITE);
    myGLCD.setBackColor(VGA_WHITE);
    myGLCD.setFont(Grotesk16x32);
    myGLCD.setColor(VGA_LIME);
    myGLCD.print("Smart", CENTER, 160);
    myGLCD.print("Weather Predictor", CENTER, 210);
    delay(5000);
    
  
  
  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  Serial.println(F("Initializing Modem..."));
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
     myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Initializing ", CENTER, 190);
   myGLCD.print("Modem...", CENTER, 230);
   delay(1000);
  modem.restart();

  String modemInfo = modem.getModemInfo();
  Serial.print("Modem: ");
  Serial.println(modemInfo);

   Serial.print(F("Waiting for network..."));
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Initializing ", CENTER, 190);
   myGLCD.print("Network...", CENTER, 230);
   delay(1000);
   
  if (!modem.waitForNetwork()) {
    Serial.println(" fail");
    delay(10000);
    return;
  }
  Serial.println(" OK");
myGLCD.print("CONNECTED!!!...", CENTER, 270);

 
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Connecting to ", CENTER, 190);
   myGLCD.print(apn, CENTER, 230);
   delay(1000);
  Serial.print(F("Connecting to "));
  Serial.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    Serial.println(" fail");
    delay(10000);
    return;
  }
 
  Serial.println("   Apn connected");
  myGLCD.print("CONNECTED!!!...", CENTER, 270);

   
   
   
   wunderground();
  
    //bmp 
  bmp.begin(); 

   //dht
  dht.begin();

 }




void loop()
{
  //upload
  float tempc = bmp.readTemperature(); //Can read temp from bmp or dht sensors
  float tempf = (tempc * 9.0)/ 5.0 + 32.0; //was dht.readTemperature, need to convert native C to F
  float humidity = dht.readHumidity(); 
  float baromin = bmp.readPressure()* 0.0002953;// Calc for converting Pa to inHg (wunderground)
  float dewptf = (dewPoint(tempf, dht.readHumidity())); //Dew point calc(wunderground) //replaced dht.readtemp with converted temp
   float f = dht.readTemperature(true);
  float t = dht.readTemperature();


  
  
  Serial.print("temp= ");
  Serial.print(tempf);
  Serial.println(" *F");
  Serial.print("baro= ");
  Serial.print(baromin);
  Serial.println(" inHg");
  Serial.print("dew point= ");
  Serial.println(dewptf);
 
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_GREEN);
   myGLCD.print("STATION", CENTER, 190);
   myGLCD.print("DATA", CENTER, 230);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setColor(VGA_AQUA);
   myGLCD.print("WEATHER PREDICTOR", CENTER, 430);
   delay(2000);


   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("STATION DATA", CENTER, 20);
  
   
   myGLCD.print("Temperature:", LEFT, 70);
   myGLCD.setColor(VGA_RED);
   myGLCD.printNumI(tempf, LEFT, 120);
   myGLCD.print("*F ", CENTER, 120); 
     
      
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Humidity:", LEFT, 170);
   myGLCD.setColor(VGA_GREEN);
   myGLCD.printNumI(humidity, LEFT, 230);
   myGLCD.print("% ", CENTER, 230);
   
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Pressure:", LEFT, 280);
   myGLCD.setColor(VGA_FUCHSIA);
   myGLCD.printNumI(baromin, LEFT, 320);
   myGLCD.print("Hg ", CENTER, 320);
   
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Dew Point:", LEFT, 370);
   myGLCD.setColor(VGA_BLUE);
   myGLCD.printNumI(dewptf, LEFT, 420);
   myGLCD.print("*F ", CENTER, 420);
    
delay(5000);
    



   
  
  TinyGsmClient client(modem);
 if (client.connect(SERVER, 80)) { 
    if (DEBUG) {    
      Serial.println("Sending DATA ");
      }
    // Ship it!
     Serial.println("Sending DATA ");
     client.print(WEBPAGE); 
    client.print("ID=");
    client.print(ID);
    client.print("&PASSWORD=");
    client.print(PASSWORD);
    client.print("&dateutc=");
    client.print("now");    //can use instead of RTC if sending in real time
    client.print("&tempf=");
    client.print(tempf);
    client.print("&baromin=");
    client.print(baromin);
    client.print("&dewptf=");
    client.print(dewptf);
    client.print("&humidity=");
    client.print(humidity);
    //client.print("&action=updateraw");//Standard update
    client.print("&softwaretype=Arduino%20UNO%20version1&action=updateraw&realtime=1&rtfreq=2.5");//Rapid Fire
    client.print(" HTTP/1.0\r\n");
    client.print("Accept: text/html\r\n");
    client.print("Host: ");
    client.print(SERVER);
    client.print("\r\n\r\n");
    client.println();
    client.stop();
     myGLCD.clrScr();
   myFiles.loadBitmap(0, 0, 320, 480, "w14.raw");
   delay(3000);
     if (DEBUG) {   
      Serial.println("Upload complete");
      }
      }//End send loop 
    else {
      if (DEBUG) { Serial.println(F("Connection failed")); }
      return;
      
      }
      
      wunderground();                                    
}




double dewPoint(double tempf, double humidity)
{
  double A0= 373.15/(273.15 + tempf);
  double SUM = -7.90298 * (A0-1);
  SUM += 5.02808 * log10(A0);
  SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
  SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
  SUM += log10(1013.246);
  double VP = pow(10, SUM-3) * humidity;
  double T = log(VP/0.61078);   
  return (241.88 * T) / (17.558-T);
}





void wunderground() 
{
 TinyGsmClient client(modem);

   myGLCD.clrScr();
     myFiles.loadBitmap(10, 120, 300, 179, "w12.raw");
     myGLCD.setColor(0, 255, 0);
     myGLCD.setBackColor(0, 0, 0);
     delay(2000);
  
  Serial.print("connecting to ");
  Serial.println(server);
  
  // Use WiFiClient class to create TCP connections
  
  const int httpPort = 80;
  
  if (!client.connect(server, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  String html_cmd1 = "GET /api/" + myKey + "/" + myFeatures + "/q/" + myCountry + "/" + myCity + ".json HTTP/1.1";
  String html_cmd2 = "Host: " + (String)server;
  String html_cmd3 = "Connection: close";

   Serial.println(" " + html_cmd1);
   Serial.println(" " + html_cmd2);
   Serial.println(" " + html_cmd3);
   
   client.println(html_cmd1);
   client.println(html_cmd2);
   client.println(html_cmd3);
   client.println();
  
  
  delay(500);
 unsigned int i = 0; //timeout counter
 char json[buffer]="{"; // array for Json parsing
    int n = 1;          // character counter for json
    
        while (!client.find("\"simpleforecast\": {")) {}
       
    for (int j=0;j<num_elements_fr;j++){
      while (!client.find(forecast[j])){} // find the part we are interested in.
      
      String Str1 = forecast_rename[j];
      
      for (int l=0; l<(Str1.length());l++)
      {json[n] = Str1[l];
      n++;}
      while (i<60000) {
        if(client.available()) {
          char c = client.read();
          if (c== ',') {break;}
          if(c== '}') {n--;n--;n--;break;}
            
          json[n]=c;
          n++;
          i=0;
        }
        i++;
      }
      if (j==num_elements_fr-1)
      {   
        
        json[n]=close_brace;
        
      
      }
      else
      {json[n]=comma;}
      n++;
    }
  //Serial.println(json);                                       // debugging json string 
  parseJSON(json);                                              // extract the conditions
  WMillis=millis();
}


void parseJSON(char json[400])
{
    Serial.println(json);
    StaticJsonBuffer<buffer> jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(json);
 if (!root.success())
{
  Serial.print("?fparseObject() failed");
  //return;
}
    const char* celsius_h_0 = root["celsius_h_0"];
    const char* celsius_l_0 = root["celsius_l_0"];
    const char* icon_0 = root["icon_0"];
    int pop_0 = root["pop_0"];
    const char* celsius_h_1 = root["celsius_h_1"];
    const char* celsius_l_1 = root["celsius_l_1"];
    const char* icon_1 = root["icon_1"];
    int pop_1 = root["pop_1"];
    const char* celsius_h_2 = root["celsius_h_2"];
    const char* celsius_l_2 = root["celsius_l_2"];
    const char* icon_2 = root["icon_2"];
    int pop_2 = root["pop_2"];
    const char* celsius_h_3 = root["celsius_h_3"];
    const char* celsius_l_3 = root["celsius_l_3"];
    const char* icon_3 = root["icon_3"];
    int pop_3 = root["pop_3"];
    
    String day1 = String(celsius_l_1) + "'/" + String(celsius_h_1) + "'";
    String day2 = String(celsius_l_2) + "'/" + String(celsius_h_2) + "'";
    String day3 = String(celsius_l_3) + "'/" + String(celsius_h_3) + "'";
    String day0 = String(celsius_l_0) + "'/" + String(celsius_h_0) + "'";
   


Serial.println(day1);

Serial.println(day2);

Serial.println(day3);

Serial.println(day0);

   
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myFiles.loadBitmap(10, 50, 300, 179, "w13.raw");
   myGLCD.setColor(VGA_RED);
   myGLCD.print("FORECAST", CENTER, 300);
   myGLCD.setColor(VGA_AQUA);
   myGLCD.print("WEATHER PREDICTOR", CENTER, 430);
   delay(1500);
    
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("WUNDERGROUND DATA", CENTER, 20);
   myGLCD.print("CITY:", LEFT, 170);
   myGLCD.print("COIMBATORE", CENTER, 230);
   myGLCD.setColor(VGA_AQUA);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.print("WEATHER PREDICTOR", CENTER, 430);
   delay(2000);
 

//day1
  myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("DAY 1", CENTER, 200);
   delay(2000);
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("FORECAST:", LEFT, 20);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("TEMPERATURE:", LEFT,370 );
   myGLCD.setColor(VGA_RED);
   myGLCD.print(day1, CENTER, 430);
  
    iconName = (icon_1);
    dayIconFix();
 
  Serial.println(icon_1);
 
  myFiles.loadBitmap(0, 70, 320, 220, (sdFileName));
  myGLCD.setColor(VGA_GREEN);
  myGLCD.print(icon_1, CENTER, 310);
  delay(5000);

     
 
   //day2
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("DAY 2", CENTER, 200);
   delay(2000);
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("FORECAST:", LEFT, 20);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("TEMPERATURE:", LEFT,370 );
   myGLCD.setColor(VGA_RED);
   myGLCD.print(day2, CENTER, 430);

 iconName = (icon_2);
    dayIconFix();
 
  Serial.println(icon_2);
 
  myFiles.loadBitmap(0, 70, 320, 220, (sdFileName));
  myGLCD.setColor(VGA_GREEN);
  myGLCD.print(icon_2, CENTER, 310);
  delay(5000);
 



 //day3
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("DAY 3", CENTER, 200);
   delay(2000);
   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("FORECAST:", LEFT, 20);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("TEMPERATURE:", LEFT,370 );
   myGLCD.setColor(VGA_RED);
   myGLCD.print(day3, CENTER, 430);

 iconName = (icon_3);
    dayIconFix();
 
  Serial.println(icon_3);
 
  myFiles.loadBitmap(0, 70, 320, 220, (sdFileName));
  myGLCD.setColor(VGA_GREEN);
  myGLCD.print(icon_3, CENTER, 310);
  delay(5000);




   myGLCD.clrScr();
   myGLCD.setColor(0, 255, 0);
   myGLCD.fillScr(VGA_WHITE);
   myGLCD.setFont(Grotesk16x32);
   myGLCD.setBackColor(VGA_WHITE);
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Forecast Summary", CENTER, 20);
  
   
   myGLCD.print("Day 1:", LEFT, 70);
   myGLCD.setColor(VGA_RED);
   myGLCD.print(icon_1, LEFT, 120);
     
      
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Day 2:", LEFT, 170);
   myGLCD.setColor(VGA_GREEN);
   myGLCD.print(icon_2, LEFT, 230);
   
   myGLCD.setColor(VGA_BLACK);
   myGLCD.print("Day 3 :", LEFT, 280);
   myGLCD.setColor(VGA_FUCHSIA);
   myGLCD.print(icon_3, LEFT, 320);
   delay(7000);
  
}








void dayIconFix()
{
  int i;
  
  for (i = 0; i < 40; i++)
  {
    
    if (strcmp (iconName, iconArray[i])==0) {i=i+1; sdFileName = "w"; sdFileName +=i; sdFileName += ".raw"; break;}
    
  }
  
  
}

  
  

Custom parts and enclosures

Weather Icons:
Just upload these icons in a 2 GB memory card and insert in the memory card slot of the TFT display (Do not Change the format).
w13_MLgz7bmfIu.raw

Comments

Similar projects you might like

Personal Weather Station (Arduino+ ESP8266 + Thingspeak)

Project tutorial by Jayraj Desai

  • 51,519 views
  • 32 comments
  • 107 respects

Arduino Environmental Monitoring

Project showcase by Prajay Basu

  • 14,550 views
  • 1 comment
  • 28 respects

Rube Goldberg Weather Station with Internet Data Storage

Project in progress by randtekk

  • 7,011 views
  • 6 comments
  • 42 respects

Monitoring Industries Using IoT

Project tutorial by vimarsh

  • 5,408 views
  • 17 comments
  • 23 respects

Portable Warehouse/Control Shed/Greenhouse Monitoring

Project tutorial by Muhammad Afzal

  • 1,303 views
  • 0 comments
  • 7 respects

WaterPi: Houseplant Remote Watering and Monitoring System

Project tutorial by Demirhan Aydin

  • 29,499 views
  • 14 comments
  • 128 respects
Add projectSign up / Login