Mini Weather Station (Rain Gauge, Wind Speed, Wind Direction) using Blynk and SIM800C

Overview

Weather Forecasting are important for planning our day-to-day activities. Farmers need information to help them plan for the planting and harvesting of their crops. Airlines need to know about local weather  conditions in order to schedule flights. Weather forecasting helps us to make more informed daily decisions, and may even help keep us out of danger.

In this tutorial, we will make a mini weather station that will send or display its data on the Blynk application using SIM800C.

Hardware Components

  • Robotdyn Uno R3

  • SIM800C
  • 
    
  • 10k ohms Resistor
  • 
    
  • Rain Gauge Sensor
  • 
    
  • Wind Speed Sensor
  • 
    
  • Wind Direction Sensor
  • 
    
  • Jumper wires (Male to Male)
  • Jumper wires (Male to Female)
  • 
    

    You can buy it all here at createlabz.

    Software Components

    Application Discussion

    Rain Gauge Sensor

    This is simply a small balance “tipping bucket” detector where the rain runs in one side of the balance  which make it heavier causing the balance to topple over. In so doing a small magnet makes the reed switch change from OFF to ON and then back to off sending a pulse to the control unit.

    Wind Speed Sensor

    The cup-type anemometer measures wind speed by closing a contact as a magnet moves past a switch. The anemometer switch is connected to the inner two conductors of the RJ11 cable.

    Wind Direction Sensor

    The wind direction sensor has eight switches, each connected to a different resistor. The vane’s magnet may close two switches at once, allowing up to 16 different positions to be indicated. An external resistor can be used to form a voltage divider, producing a voltage output that can be measured with an analog to digital converter.

    SIM800C

    The SIM800 is a cellular communication module that can make calls, send email and SMS texts, and even connect to the internet. The module is intended to operate like a mobile phone, but it needs external peripherals to function properly.

    Software Setup

    First install the Blynk app from Playstore or App Store in your phone.

    Open the app and select New Project.

    Enter the Project Name, press the CHOOSE DEVICE and select Arduino UNO and press the CONNECTION TYPE and select GSM. Then click Create Project.

    Just press ok, now your auth token was sent to your email but you can also find it in the Project Settings

    Go to the widgets menu and select the Gauge widget.

    Enter the name of the gauge. And assign the pin input and the label.

    Go to the widgets menu again and select LCD. Assign the input pin 1 to Virtual 1 and Enter the WIND DIRECTION: message to pin 0 in the Message section.

    Go back to widgets menu and select LCD again. Assign input pin 1 to virtual 3 and enter the RAINFALL: message in pin 0 and Inch in pin 1.

    If you are able to connect to the blynk app. Just click the play button on the top left corner.

    NOTE: you can make your own design and format in your Blynk app.

    Hardware Setup

    Wind Speed Sensor

    Connect the wind speed sensor to the RJ11 Adapter. And then connect the green wire of RJ11 to the pin 2 of Arduino Uno and the red wire to the 5V pin.

    Wind Direction Sensor

    Connect the wind direction sensor to the RJ11 Adpater. Now connect the yellow wire to the ground of Arduino Uno and connect the black wire to the Analog pin 0 with a pull up 10k resistor.

    Rain Gauge Sensor

    Connect the rain gauge sensor to the RJ11 Adapter. Then connect the red wire of RJ11 to the 5V pin of Arduino Uno and the green wire to the pin 3 with a pull down 10k resistor.

    SIM800C

    The VCC and GND of SIM800C is connected to a different Arduino Uno to function properly and the TXD pin is connected to the pin 9 of the main Arduino Uno and the RXD pin is connected to the pin 10.

    Code

    Libraries Included

    Arduino Code

    #define TINY_GSM_MODEM_SIM800
    #include <TinyGsmClient.h>
    #include <BlynkSimpleSIM800.h>
    #include <millisDelay.h>
    
    #define windSensorPin 2
    #define RainPin 3
    #define windDirectionPin A0
    millisDelay timerDelay;
    
    
    int windCounter = 0;
    float windSpeed = 0;
    int windPulse = 0;
    int pulses = 0;
    int windTest1 = 1;
    int windTest2 = 0;
    int windTimer = 1;
    int result = 1;
    int startTest = 1;
    
    
    int Rain = 0;
    const double amountperpulse = 0.011;
    double RainPulse = 0;
    int rainTest1 = 1;
    int rainTest2 = 0;
    int rainTimer = 1;
    
    double RainSensor = 0.0;                
    int lastcount = 0;
    
    int timerStart = 1;
    
    int windDirValue = 0;
    int windDir;
    
    
    char auth[] = "3b01650ac0484ec58fc322e5c5561f03";
    
    char apn[]  = "http.globe.com.ph"; 
    char user[] = "";
    char pass[] = "";
    
    #include <SoftwareSerial.h>
    SoftwareSerial SerialAT(9, 10); // RX, TX
    
    TinyGsm modem(SerialAT);
    
    void setup()
    {
      // Set console baud rate
      Serial.begin(19200);
      pinMode(windSensorPin, OUTPUT);
      pinMode(RainPin, OUTPUT);
      pinMode(windDirectionPin, INPUT); 
      delay(10);
    
      // Set GSM module baud rate
      SerialAT.begin(19200);
      
      delay(1000);
      SerialAT.println("AT");
    
      Blynk.begin(auth, modem, apn, user, pass);
    }
    
    void loop()
    {
      Blynk.run();
      if (digitalRead(windSensorPin) < 1 && startTest == 1 )
      {
        windDirValue = analogRead(windDirectionPin);
        windDir = map(windDirValue, 1, 1024, 1, 5000);
        windTest1 = 1;
        windTest2 = 1;
        windTimer = 1;
        result = 1;
        startTest = 0;
        
      }
      WindSpeed();
      if (digitalRead(RainPin) == 1 && rainTest1 == 1)
      {
        Rain++;
        rainTest2 = 1;
        rainTest1 = 0;
        
      }
      RainGauge();
      if ((digitalRead(windSensorPin) < 1 || digitalRead(RainPin) == 1) && timerStart == 1)
      {
        timerDelay.start(3000);
        result = 1;
        timerStart = 0;
      }
      if (timerDelay.isFinished() && result == 1)
      {
    
        windSpeed = 1.25 * (pulses/3);
        Serial.print("WindSpeed: ");
        Serial.print(windSpeed);
        Serial.print(" mph\t\t");
        Blynk.virtualWrite(V2,windSpeed);
        pulses = 0;
        windSpeed = 0;
      
    
        startTest = 1;
    
        RainSensor = RainPulse;
        Serial.print("Rainfall = ");
        Serial.print(RainSensor);
        Serial.print(" inch\t\t");
        Blynk.virtualWrite(V3,RainSensor);
        
        WindDirection();
    
        lastcount = RainPulse;
        rainTimer = 1;
        RainPulse = 0;
        result = 0;
        timerStart = 1;
      }
    }
    
    void WindSpeed()
    {
      if (digitalRead(windSensorPin) < 1)
      {
        windCounter++;
      }
      if (windCounter > 0 && digitalRead(windSensorPin) == 1 && windTest1 == 1)
      {
        windPulse += 1;
        windCounter = 0;
    
      }
    
      if (windPulse == 3 && windTest2 == 1)
      {
        pulses += 2;
        //Serial.println(pulses);
        windPulse = 0;
      }
    
      
    }
    
    void RainGauge()
    {
      
      if (Rain > 0 && digitalRead(RainPin) == 0 && rainTest2 == 1)
      {
        delay(200);
        Rain = 0;
        RainPulse += amountperpulse;
        rainTest2 = 0;
        rainTest1 = 1;
        
      }
    }
    void WindDirection()
    {
       
      
      if(windDir >= 3600 && windDir <= 3900)
      {
        Serial.print("Wind Direction: ");
        Serial.println("North");
        Blynk.virtualWrite(V1,"North");
      }
      else if(windDir >= 2050 && windDir <= 2300)
      {
        Serial.print("Wind Direction: ");
        Serial.println("NorthEast");
        Blynk.virtualWrite(V1,"NorthEast");
      }
      else if(windDir >= 350 && windDir <= 500)
      {
        Serial.print("Wind Direction: ");
        Serial.println("East");
        Blynk.virtualWrite(V1,"East");
      }
      else if(windDir >= 800 && windDir <= 900)
      {
        Serial.print("Wind Direction: ");
        Serial.println("SouthEast");
        Blynk.virtualWrite(V1,"SouthEast");
      }
      else if(windDir >= 1250 && windDir <= 1450)
      {
        Serial.print("Wind Direction: ");
        Serial.println("South");
        Blynk.virtualWrite(V1,"South");
      }
      else if(windDir >= 2850 && windDir <= 3100)
      {
        Serial.print("Wind Direction: ");
        Serial.println("SouthWest");
        Blynk.virtualWrite(V1,"SouthWest");
      }
      else if(windDir >= 4400 && windDir <= 4650)
      {
        Serial.print("Wind Direction: ");
        Serial.println("West");
        Blynk.virtualWrite(V1,"West");
      }
      else if(windDir >= 4150 && windDir <= 4350)
      {
        Serial.print("Wind Direction: ");
        Serial.println("NorthWest");
        Blynk.virtualWrite(V1,"NorthWest");
      }
    }

     

    Code Breakdown

    char auth[] = "Auth Token";
    
    char apn[]  = "http.globe.com.ph"; 
    char user[] = "";
    char pass[] = "";

    Enter your Auth Token from the Blynk app in the project settings and your APN service provide. If the APN service provider doesn’t have username and password, just leave it blank.

    void setup()
    {
      // Set console baud rate
      Serial.begin(19200);
      pinMode(windSensorPin, OUTPUT);
      pinMode(RainPin, OUTPUT);
      pinMode(windDirectionPin, INPUT); 
      delay(10);
    
      // Set GSM module baud rate
      SerialAT.begin(19200);
      
      delay(1000);
    
      Blynk.begin(auth, modem, apn, user, pass);
    }

    This is the setup part of the code. In this code we set the serial communication baud rate and the GSM module baud rate. This also starts to establish network connection, sets up Blynk connection details, and tries to connect to Blynk server.

    Blynk.run();

    This code is the main Blynk routine, responsible for keeping connection alive, sending data, receiving data, etc.

    if (digitalRead(windSensorPin) < 1 && startTest == 1 )
      {
        windDirValue = analogRead(windDirectionPin);
        windDir = map(windDirValue, 1, 1024, 1, 5000);
        windCounter++;
        windTest1 = 1;
        windTest2 = 1;
        startTest = 0;
        
      }
      WindSpeed();

    In this code, if the windSensorPin is equal to zero or less than 1 and startTest variable is equal to 1, it will start reading the value of the windDirectionPin and map it to 1 – 5000 range. Next is it will increment the windCounter variable and sets the windTest1 and windTest2 variables to 1 and startTest variable to 0 stop this code from running. After this it will call the WindSpeed() function.

    if (digitalRead(RainPin) == 1 && rainTest1 == 1)
      {
        Rain++;
        rainTest2 = 1;
        rainTest1 = 0;
        
      }
      RainGauge();

    This code will now run if the RainPin is equal to and rainTest variable is equal to 1. It will increment the Rain variable and set the rainTest2 variable to 1 and rainTest to 0 to stop this code from running. And after this it will call the RainGauge() function.

    if ((digitalRead(windSensorPin) < 1 || digitalRead(RainPin) == 1) && timerStart == 1)
      {
        timerDelay.start(3000);
        result = 1;
        timerStart = 0;
      }

    This is the code starts a 3 seconds timer if the windSensorPin, RainPin and timerStart is equal to 1. And set the result variable to 1 and timerStart to 0 to prevent the code from running again.

    if (timerDelay.isFinished() && result == 1)
      {
    
        windSpeed = 1.25 * (pulses/3);
        Serial.print("WindSpeed: ");
        Serial.print(windSpeed);
        Serial.print(" mph\t\t");
        Blynk.virtualWrite(V2,windSpeed);
        pulses = 0;
        windSpeed = 0;
      
    
        startTest = 1;
    
        RainSensor = RainPulse;
        Serial.print("Rainfall = ");
        Serial.print(RainSensor,8);
        Serial.print(" inch\t\t");
        Blynk.virtualWrite(V3,RainSensor);
        
        WindDirection();
    
        lastcount = RainPulse;
        rainTimer = 1;
        RainPulse = 0;
        result = 0;
        timerStart = 1;
      }

    After the 3 seconds timer and if the result variable is equal to 1, this code will now run. It will now calculate the wind speed and store it in the windSpeed variable and it will also calculate the rainfall and store it in the RainSensor variable. And sends the windSpeed and RainSensor data to the Blynk app and it will also call the WindDirection() function.

    void WindSpeed()
    {
      if (windCounter > 0 && digitalRead(windSensorPin) == 1 && windTest1 == 1)
      {
        windPulse += 1;
        windCounter = 0;
    
      }
    
      if (windPulse == 3 && windTest2 == 1)
      {
        pulses += 2;
        windPulse = 0;
      }
    
      
    }

    This is the WindSpeed() function. This is the code for counting the pulse of the wind speed sensor. If the windCounter is greater than 0 and windSensorPin and windTest is equal to 1, windPulse variable will now increase by 1 and sets the windCounter back to 0. And if the windPulse is equal to 3 and windTest is equal to 1, the variable pulses will now increase by 2 and sets the windPulse variable to 0.

    void RainGauge()
    {
      
      if (Rain > 0 && digitalRead(RainPin) == 0 && rainTest2 == 1)
      {
        delay(200);
        Rain = 0;
        RainPulse += amountperpulse;
        rainTest2 = 0;
        rainTest1 = 1;
        
      }
    }

    This is the RainGauge() function. If the Rain variable is greater than 0 and RainPin is equal to 0 and rainTest is equal to 1, RainPulse will now increment by 0.011 (amountperpulse =
    0.011 ) and sets the Rain variable back to 0.

    void WindDirection()
    {
       
      
      if(windDir >= 3600 && windDir <= 3900)
      {
        Serial.print("Wind Direction: ");
        Serial.println("North");
        Blynk.virtualWrite(V1,"North");
      }
      else if(windDir >= 2050 && windDir <= 2300)
      {
        Serial.print("Wind Direction: ");
        Serial.println("NorthEast");
        Blynk.virtualWrite(V1,"NorthEast");
      }
      else if(windDir >= 350 && windDir <= 500)
      {
        Serial.print("Wind Direction: ");
        Serial.println("East");
        Blynk.virtualWrite(V1,"East");
      }
      else if(windDir >= 800 && windDir <= 900)
      {
        Serial.print("Wind Direction: ");
        Serial.println("SouthEast");
        Blynk.virtualWrite(V1,"SouthEast");
      }
      else if(windDir >= 1250 && windDir <= 1450)
      {
        Serial.print("Wind Direction: ");
        Serial.println("South");
        Blynk.virtualWrite(V1,"South");
      }
      else if(windDir >= 2850 && windDir <= 3100)
      {
        Serial.print("Wind Direction: ");
        Serial.println("SouthWest");
        Blynk.virtualWrite(V1,"SouthWest");
      }
      else if(windDir >= 4400 && windDir <= 4650)
      {
        Serial.print("Wind Direction: ");
        Serial.println("West");
        Blynk.virtualWrite(V1,"West");
      }
      else if(windDir >= 4150 && windDir <= 4350)
      {
        Serial.print("Wind Direction: ");
        Serial.println("NorthWest");
        Blynk.virtualWrite(V1,"NorthWest");
      }
    }

    This is the WindDirection() function. This is the code to determine the direction of the wind depending on the value we got from the wind direction sensor.

    Conclusion

    Weather affects a wide range of man’s activities, including agriculture, transportation, and time. But with the different kinds of sensors that can detect weather parameters we can now monitor it and thus help us make better decisions.

    References

    [1] http://www.philpot.me/weatherinsider.html

    [2] https://www.rmets.org/resource/beaufort-scale

    The post Mini Weather Station (Rain Gauge, Wind Speed, Wind Direction) using Blynk and SIM800C appeared first on CreateLabz.

    ArduinoBlynkCellularGprsGsmIotKnowledgebaseRain gaugeSim800Sim800cWeatherWeather stationWind directionWind speed

    Leave a comment

    All comments are moderated before being published