Weather Display
In this project, we will be using an online weather service to display local weather and time on a Graphic LCD Phidget (LCD1100). Code is available for this project in C# and Python.
Supplies
The following hardware is used:
- VINT Hub Phidget (HUB0000_0)
- Graphic LCD Phidget (LCD1100_0)
Setup
Connect your Graphic LCD Phidget to your VINT Hub on any port.
Overview
As shown above, there are two main parts of this project:
- Accessing weather data
- Displaying weather data
Let's start by taking a look at accessing the data.
Accessing Weather Data
We will be using OpenWeather to access our local weather forecast. They provide free access to weather forecasts in over 200,000 cities. The following formats are supported:
- JSON
- XML
- HTML
For this project, we will be using XML format.
In order to access weather data, you must create a free account and get an API key.
Create Your Account
Follow this link to create a free account and get an API key. After getting your API key, you will can access data through this URL:
api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}
Replace {city name} with your city, and {API key} with your API key. For example, this is what ours looks like:
http://api.openweathermap.org/data/2.5/weather?q=Calgary&APPID=fakeid111111111111111111111111111&units=metric&mode=xml
Try entering your URL into any web browser. You will see XML formatted weather data as shown above. The next step is creating a program that can parse the data so it can be displayed.
Read/Parse Weather Data - C#
For C#, you can use the XMLTextReader class to quickly parse the XML data:
static string readXML(string arg1, string arg2) { String URLString = "http://api.openweathermap.org/data/2.5/weather?q=Calgary&APPID=fakeid111111111111111111111111111&units=metric&mode=xml"; XmlTextReader reader = new XmlTextReader(URLString); reader.ReadToFollowing(arg1); reader.MoveToAttribute(arg2); return reader.Value; }
You can use the function above like this:
static void updateWeather(LCD lcd) { string city = readXML("city", "name"); string temperature = readXML("temperature", "value"); string humidity = readXML("humidity", "value"); string windspeed = readXML("speed", "value"); string descript = readXML("weather", "value"); string iconID = readXML("weather", "icon"); }
There are other values available (sunrise time, sunset time, pressure, etc.) but for this project, we will only be displaying a subset of the values.
Read/Parse Weather Data - Python
For Python, you can use the ElementTree XML API to quickly parse the data:
import xml.etree.ElementTree as ET from urllib.request import urlopen url = urlopen('http://api.openweathermap.org/data/2.5/weather?q=Calgary&APPID=fakeid111111111111111111111111111&units=metric&mode=xml') tree = ET.parse(url) root = tree.getroot() def readXML(arg1, arg2): for item in root.iter(arg1): return item.get(arg2) print(readXML('city','name')) print(readXML('temperature','value')) print(readXML('humidity','value')) print(readXML('speed','value')) print(readXML('weather','value')) print(readXML('weather','icon'))
There are other values available (sunrise time, sunset time, pressure, etc.) but for this project, we will only be displaying a subset of the values.
OpenWeather Icons
You may have noticed that we stored the iconID above. This value represents an image describing the current weather. You can view the icons here. The Graphic LCD Phidget is capable of displaying bitmaps, we can easily implement these icons in our program. If you haven't explored bitmaps on the Graphic LCD Phidget, check out this project.
There are many pixel art programs available online, we used Piskel. It was easy to recreate the OpenWeatherMap icons because of the simple Export to C File option. The results of the bitmaps are provided in the github repo below.
Displaying Data - C#
Now that we have collected the weather data, the last step is to display it on the Graphic LCD Phidget:
static void updateWeather(LCD lcd) { string city = readXML("city", "name"); string temperature = readXML("temperature", "value"); string humidity = readXML("humidity", "value"); string windspeed = readXML("speed", "value"); string descript = readXML("weather", "value"); string iconID = readXML("weather", "icon"); if (temperature.Length > 5) { temperature = temperature.Remove(5); } //Temperature box int x = (44 - ((temperature.Length * 6) + 12)) / 2; lcd.WriteText(LCDFont.Dimensions_6x12, x, 15, temperature); lcd.WriteText(LCDFont.User1, x + temperature.Length * 6, 15, "0"); lcd.WriteText(LCDFont.Dimensions_6x12, x + temperature.Length * 6 + 6, 15, "C"); //Weather image + descript box byte[] temp; if (iconID == "01d") temp = _01d; else if (iconID == "02d") temp = _02d; else if (iconID == "03d") temp = _03d; else if (iconID == "04d") temp = _04d; else if (iconID == "09d") temp = _09d; else if (iconID == "10d") temp = _10d; else if (iconID == "11d") temp = _11d; else if (iconID == "13d") temp = _13d; else if (iconID == "50d") temp = _50d; else if (iconID == "01n") temp = _01n; else if (iconID == "02n") temp = _02n; else if (iconID == "10n") temp = _10n; else temp = unknown; lcd.WriteBitmap(2, 31, 32, 32, temp); lcd.WriteText(LCDFont.Dimensions_5x8, 40, 42, descript); //Extra info box lcd.WriteText(LCDFont.Dimensions_5x8, 50, 11, "Humidity: " + humidity + "%"); lcd.WriteText(LCDFont.Dimensions_5x8, 50, 20, "Wind: " + windspeed + "km/h"); } static void redraw(LCD lcd) { lcd.Clear(); //draw borders around outside lcd.DrawLine(0, 0, 127, 0); lcd.DrawLine(0, 0, 0, 63); lcd.DrawLine(127, 0, 127, 63); lcd.DrawLine(0, 63, 127, 63); //draw borders inside lcd.DrawLine(0, 10, 128, 10); lcd.DrawLine(43, 10, 43, 30); lcd.DrawLine(1, 30, 127, 30); lcd.WriteText(LCDFont.Dimensions_5x8, 1, 1, DateTime.Now.ToString(" ddd, MMM d hh:mm:ss tt")); updateWeather(lcd); lcd.Flush(); }<br>
Here is a quick review of the code above:
redraw
This function draws the main borders on the Graphic LCD. It also prints the current time and calls the updateWeather program.
updateWeather
This function arranges the data from the OpenWeather service onto the Graphic LCD.
Displaying Data - Python
Now that we have collected the weather data, the last step is to display it on the Graphic LCD Phidget:
def updateWeather(): city = readXML('city', 'name') temperature = readXML('temperature', 'value') humidity = readXML('humidity', 'value') windspeed = readXML('speed', 'value') descript = readXML('weather', 'value') iconID = readXML('weather', 'icon') if(len(temperature) > 5): temperature = temperature[:-1:] #remove last char so it fits #temperature box x = (44 - ((len(temperature) * 6) + 12)) / 2 x = int(x) #force to int lcd.writeText(LCDFont.FONT_6x12, x, 15, temperature) lcd.writeText(LCDFont.FONT_User1, x + len(temperature) * 6, 15, "0") lcd.writeText(LCDFont.FONT_6x12, x + len(temperature) * 6 + 6, 15, "C") #Weather icon + descript box temp = [] if(iconID == "01d"): temp = _01d elif(iconID == "02d"): temp = _02d elif (iconID == "03d"): temp = _03d elif (iconID == "04d"): temp = _04d elif (iconID == "09d"): temp = _09d elif (iconID == "10d"): temp = _10d elif (iconID == "11d"): temp = _11d elif (iconID == "13d"): temp = _13d elif (iconID == "50d"): temp = _50d elif (iconID == "01n"): temp = _01n elif (iconID == "02n"): temp = _02n elif (iconID == "10n"): temp = _10n else: temp = unknown lcd.writeBitmap(2, 31, 32, 32, temp) lcd.writeText(LCDFont.FONT_5x8, 40, 42, descript) #Extra info box lcd.writeText(LCDFont.FONT_5x8, 50, 11, "Humidity: " + humidity + "%") lcd.writeText(LCDFont.FONT_5x8, 50, 20, "Wind: " + windspeed + "km/h") def redraw(): lcd.clear() #Draw borders around outside lcd.drawLine(0, 0, 127, 0) lcd.drawLine(0, 0, 0, 63) lcd.drawLine(127, 0, 127, 63) lcd.drawLine(0, 63, 127, 63) #draw borders inside lcd.drawLine(0, 10, 128, 10) lcd.drawLine(43, 10, 43, 30) lcd.drawLine(1, 30, 127, 30) timeStr = datetime.now().strftime("%a, %b %d %I:%M:%S %p") lcd.writeText(LCDFont.FONT_5x8, 1, 1, timeStr) updateWeather() lcd.flush()<br>
Here is a quick review of the code above:
redraw
This function draws the main borders on the Graphic LCD. It also prints the current time and calls the updateWeather program.
updateWeather
This function arranges the data from the OpenWeather service onto the Graphic LCD.
Main Loop
The last thing to do is to create a main loop that updates the LCD on a set schedule. Here is what we recommend:
- Every second: update the time on the LCD
- Every 15 minutes: update the weather status on the LCD
Create an infinite loop that loops every second. Create a counter to track the loops, when the counter hits 900 (900 seconds is 15 minutes) update the weather.
Going Forward
The full code for this project is available here: https://github.com/phidgeteer/LCDWeather.git
If you have any questions, drop a comment below!