Prasannaa Kumar
Published © CC BY

GSM-Based Weather Monitoring and Prediction Device

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

AdvancedFull instructions provided6,067
GSM-Based Weather Monitoring and Prediction Device

Things used in this project

Hardware components

Arduino Mega 2560
Arduino Mega 2560
×1
3.2 Inch TFT display
×1
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
MyOctopus i2c Barometric Air Pressure Sensor BMP280
MyOctopus i2c Barometric Air Pressure Sensor BMP280
×1
GSM SIM800a module
×1

Story

Read more

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).

Code

Code

Arduino
#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;}
    
  }
  
  
}

  
  

Credits

Prasannaa Kumar

Prasannaa Kumar

12 projects • 30 followers
Researcher, Maker & Tinkerer!

Comments