Smartphone Controlled Atomic Weather Station Using Arduino

Atomic Weather Station

This project combines Atomic Time keeping with local weather station, and additional cool projects using Arduino and Raspberry Pi.

 Atomic Weather Station

Things used in this project

Hardware components

Arduino UNO & Genuino UNO
Arduino UNO & Genuino UNO
× 1
Raspberry Pi 2 Model B
Raspberry Pi 2 Model B
× 1
Adafruit Ultimate GPS Breakout
Adafruit Ultimate GPS Breakout
× 1
DHT22 Temperature Sensor
DHT22 Temperature Sensor
× 1
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD – 16×2
× 1
Adafruit Speaker – 3″ Diameter – 8 Ohm 1 Watt
× 1
Adafruit White LED Backlight Module – Large 45mm x 86mm
× 1
Adafruit GPS Antenna – External Active Antenna
× 1
Jumper wires (generic)
Jumper wires (generic)
× 1
× 1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
× 1
USB-A to B Cable
USB-A to B Cable
× 1

Software apps and online services

SSH Control

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)


Demo of Smartphone Controlled Atomic Weather Station


I was looking for a cool way to use the features of the Adafruit GPS module for a practical purpose, and Tony DiCola’s Arduino GPS Clock inspired me to create a GPS controlled atomic clock, with the addition of a weather station.

What we did

The first step is to wire up the Adafruit GPS Breakout Shield to the Arduino Uno. I thought initially about connecting the shield to the Arduino MKR1000 so I soldered pins onto the shield, but I realized that this small Arduino operates only on 3.3V, but the shield uses 5V. If you solder stacking headers onto the shield, it will fit right on top of the Uno.

Connect the RGB 16×2 Character LCD Display to the Uno according to the diagram below, and you can display information from the GPS, such as time, date, longitude, latitude, and altitude.

The temp/humidity sensor is soldered onto the PCB: it simply requires a couple of jumper wires for 5V and Ground, and one wire to connect to Arduino’s Digital I/O pin.

I wanted to add a wireless component to the station, so instead of physical buttons to switch modes I could use my smartphone to display different information. I first tried this using a Bluetooth module but had no success in getting Arduino to receive the commands I sent. Then I decided to connect a Raspberry Pi 2 to the Arduino and use serial communication to send a simple command from my phone to the Uno. I set up the Raspberry Pi with WiFi capability though the WiPi USB dongle. Although Bluetooth was unsuccessful, I was glad to have the Raspberry Pi. The Pi is easily controlled with a smartphone app, its WiFi capability allows me to access the Internet, and the addition of Python programs allows me to expand this project.

On the IPhone I downloaded the SSH Control App, which allows you to connect wirelessly to the Raspberry Pi and send terminal commands through buttons and switches. With just a swipe of a slider switch you can start a Python program, then tap a button to send a character through the Pi to the Arduino, which will receive the command and change the mode on the LCD display.


Breadboard Diagram

Connect all the jumper wires as shown. An RGB LCD Display has two more pins at the right end; both must be connected to Ground. The GPS Shield is not shown.
Atomic Weather Station schematics




A full list of tones with their corresponding frequencies
 * Public Constants

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
Raspberry Pi sends command from smartphone to Arduino
import serial
import time
from forecastiopy import *

ser = serial.Serial('/dev/ttyACM0', 9600)

api_key = "YOUR_API_KEY" 
lat = Your_Latitude 
lng = Your_Longitude 

while 1:
    c = input('Press button to switch mode: ')
    if len(c) == 1:
        if c == 'W':
            fio = ForecastIO.ForecastIO(api_key, latitude=lat, longitude=lng)
            current = FIOCurrently.FIOCurrently(fio)
            daily = FIODaily.FIODaily(fio)
            weather = str(int(current.temperature))
            we = list(weather)
            for day in range(0, 1):
                for item in daily.get_day(day).keys():
                    if item == 'temperatureMax':
                        highTemp = str(int(daily.get_day(day)[item]))
                    if item == 'temperatureMin':
                        lowTemp = str(int(daily.get_day(day)[item]))

            lT = list(lowTemp)
            hT = list(highTemp)

Arduino Uno code that displays information from a GPS module and a temperature sensor.
/* This Arduino code receives a single character from the Raspberry Pi
   and performs a varety of tasks: displaying time/indoor temperature,
   location, outdoor temperature, greeting, and birthday, as well as
   playing a tone.
   Some parts of this code are taken from open-source examples.

   Libraries to install:
   Adafruit_GPS-master -
   DHT-sensor-library-master -

   Created by Daniel Martin, 2016
 * */

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

#include "DHT.h"

#define DHTPIN 10     // what digital pin we're connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321


// If you're using a GPS module:
// Connect the GPS Power pin to 5V
// Connect the GPS Ground pin to ground
// If using software serial (sketch example default):
//   Connect the GPS TX (transmit) pin to Digital 3
//   Connect the GPS RX (receive) pin to Digital 2
// If using hardware serial (e.g. Arduino Mega):
//   Connect the GPS TX (transmit) pin to Arduino RX1, RX2 or RX3
//   Connect the GPS RX (receive) pin to matching TX1, TX2 or TX3

// If you're using the Adafruit GPS shield, change
// SoftwareSerial mySerial(3, 2); -> SoftwareSerial mySerial(8, 7);
// and make sure the switch is set to SoftSerial

// If using software serial, keep this line enabled
// (you can change the pin numbers to match your wiring):
SoftwareSerial mySerial(8, 7);

// If using hardware serial (e.g. Arduino Mega), comment out the
// above SoftwareSerial line, and enable this line instead
// (you can change the Serial number to match your wiring):

//HardwareSerial mySerial = Serial1;

Adafruit_GPS GPS(&mySerial);

#include <Time.h>             // Time Library
#include "Tones11.h"          // The code containing the frequencies of notes as variables
#include <LiquidCrystal.h>    // LCD Library
#include <Wire.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 9);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences.
#define GPSECHO  true

const int UTC_offset = -7;   // Pacific Time

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

char state;         //initializes the variable that will receive a char from Pi
int mode = 1;       //the mode of the display (default time, date, temp, humidity

// Used for converting the date, month, and year to the desired time zone
const int TimeZone = -8;  //Pacific Time
int DSTbegin[] = { //DST 2013 - 2025 in Canada and US
  310, 309, 308, 313, 312, 311, 310, 308, 314, 313, 312, 310, 309
int DSTend[] = { //DST 2013 - 2025 in Canada and US
  1103, 1102, 1101, 1106, 1105, 1104, 1103, 1101, 1107, 1106, 1105, 1103, 1102
int DaysAMonth[] = { //number of days a month
  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31

//initialization of variables for the time/date display
int Year;
int Month;
int Day = 0;
int Hour;
byte Minute;
byte Second;
char ap = 'A';
boolean suspendSec = false;

//initializes variables to refresh the display every few seconds
int timerNum = 200;
int refresh = 0;

// The Pi sends six characters (3 numbers for out temp) which will be filled into this array
char wea[6] = {'a', 'a', 'a', 'a', 'a', 'a'};

// Creates the degree symbol
byte degree[8] = {

// Creates the bell symbol
byte bell[8] = {

void setup()
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("RGB 16x2 Display ");
  lcd.setCursor(0, 1);
  lcd.print(" Multicolor LCD ");

  pinMode(13, OUTPUT);
  lcd.createChar(0, degree);
  lcd.createChar(1, bell);


  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  // uncomment this line to turn on only the "minimum recommended" data
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time

  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet

  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!

  // Ask for firmware version

Read more : Smartphone Controlled Atomic Weather Station

Leave a Comment

Your email address will not be published. Required fields are marked *