Products for USB Sensing and Control
Products for USB Sensing and Control

Phidgets Weather Display


by Lucas

Introduction

In this project, we will be using the online weather service with Phidgets to display the local weather and time on a LCD1100. We will be using C# to create this project, however, it can be easily ported to your preferred programming language.

Weather display in action!

Hardware

Software

Libraries and Drivers

This project assumes that you are somewhat familiar with the basic operation of Phidgets (i.e. attaching and opening devices, reading data, etc) and with running examples in the Phidget Control Panel . If this is your first time building a Phidgets project with C#, please refer to the C# page for instructions on how to setup your environment and get started.

Overview

A simple C# console application will perform the following tasks:

  • Get information from an online weather service and update the LCD1100 every 15 minutes.
  • Get local time and display every second.

Create PhidgetLCD & Enable Logging

The first step, as always, is enabling Phidget logging and creating the required Phidgets.

  
static void Main(string[] args){
    ...
    Phidget.EnableLogging(LogLevel.Info, "LCDWeatherDisplay.log");
    try
    {
        LCD lcd = new LCD(); 
        lcd.DeviceSerialNumber = 370229;
        lcd.Open(2000);
        lcd.Contrast = 0.25;//Contrast and backlight both have default values, so setting them is not required
        lcd.Backlight = 0.8;
        ...
    }catch (PhidgetException ex){
        Phidget.Log(LogLevel.Error, ex.Description);
    }
}

Accessing weather data

In order to display weather data, we need to access weather data. Fortunately, there are many resources available for obtaining weather forecasts. We ended up using OpenWeatherMap which provides free access to weather forecasts in over 200,000 cities. Weather data is available in multiple formats including:

  • JSON
  • XML
  • HTML

For this project, we used the XML format along with the XmlTextReader class. We made a request using the following URL:

http://api.openweathermap.org/data/2.5/weather?q=Calgary&APPID=YOUR_APP_ID&units=metric&mode=xml

In order to get an APPID you must sign up for a free account at OpenWeatherMap.

You can see an example of the returned XML below:

XML returned from OpenWeatherMap

Parsing XML

Parsing the returned XML is extremely simple in C#. Using the XmlTextReader class, we can quickly access the information we need. The code for parsing is shown below:

  
static string readXML(string arg1, string arg2){
    String URLString = "http://api.openweathermap.org/data/2.5/weather?q=Calgary&APPID=YOUR_APP_ID&units=metric&mode=xml";
    XmlTextReader reader = new XmlTextReader(URLString);
    reader.ReadToFollowing(arg1);
    reader.MoveToAttribute(arg2);
    return reader.Value;
}

static void updateWeather(LCD lcd){
...
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");
...
}

Done! Now we have up-to-date values for the following:

  • Temperature
  • Humidity
  • Wind speed
  • Temperature description
  • Icon ID - more on this below

OpenWeatherMap 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. Seeing as the LCD1100 is capable of displaying bitmaps, we can easily implement these icons in our program!

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.

Creating bitmap with Piskel. This is the recreation of 02d.png from OpenWeatherMap

Getting local time

You can access the local time in C# using the following line of code:

DateTime.Now.ToString(" ddd, MMM d hh:mm:ss tt")

If you would like to format the date differently, check out this page by Microsoft.

Outputting to LCD1100

Now that we have the local weather, weather icon bitmaps, and local time, we can output all of the information to the LCD1100.

  
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");

    //Temperature box
    int x = (43 - ((temperature.Length * 6) + 12)) / 2; //find where we should start so temp is centered
    lcd.WriteText(LCDFont.Dimensions_6x12, x, 15, temperature);
    lcd.WriteText(LCDFont.User1, x + temperature.Length * 6 + 2, 15, "0");//write bitmap for degree symbol created previously
    lcd.WriteText(LCDFont.Dimensions_6x12, x + temperature.Length * 6 + 8, 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;
    
    //Weather image and description
    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 outside borders
    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 inside borders
    lcd.DrawLine(0, 10, 128, 10);
    lcd.DrawLine(43, 10, 43, 30);
    lcd.DrawLine(1, 30, 127, 30);

    //update time and weather information
    lcd.WriteText(LCDFont.Dimensions_5x8, 1, 1, DateTime.Now.ToString(" ddd, MMM d hh:mm:ss tt"));
    updateWeather(lcd);

    //Flush all to screen
    lcd.Flush();
}

Below is the main loop that utilizes the two functions shown above.

  
int count = 0;
...
while (true){
    Thread.Sleep(1000);
    if (count++ == 900){ //900 seconds = 15 minutes
        count = 0;
        redraw(lcd);
    }
    else{
        //Date & time with underline
        lcd.WriteText(LCDFont.Dimensions_5x8, 1, 1, DateTime.Now.ToString(" ddd, MMM d hh:mm:ss tt"));
        lcd.Flush();
    }
} 

Here is the C# project in case you want to try running it yourself.

Source Code

Conclusion

The weather & time display is complete. If you have any ideas on how to make the project better, let us know!