In this article, I explain how I created a tabletop weather station with ePaper display, a Raspberry Pi, and an enclosure.
In this article, I explain how to build a weather station with an ePaper display (like the kind you find on a Kindle, except this one is tri-color – white, black and red) and a Raspberry Pi and put it in an enclosure so that you have a finished project that you can display on your coffee table or night stand and see the weather information for your location (or locations) of choice!
For the weather data, I use Open Weather Map, a cloud service that offers a Weather API and that has a free tier plan available. It even has a Python wrapper library available to easily invoke the APIs and get the weather data in an object oriented manner, without worrying about underlying protocols and processing JSON results.
For the ePaper display, I use an ePaper HAT for the Raspberry Pi by Waveshare, who also provide a python library for interfacing with it.
Lastly comes the enclosure. Some of you may be aware that I’ve created a new stackable, modular enclosure system called ProtoStax. It was a personal itch that I had to scratch – I wanted an enclosure that supported different stages of prototyping, offering protection and open access when starting out, with the ability to add side walls and the top later, but also have the ability to stack multiple units either side-by-side or one on top of the other, thereby having the ability to expand with prototyping needs and the addition of other boards and components.
In this example I use ProtoStax for Raspberry Pi B+, a clear acrylic enclosure for the Raspberry Pi B+ that is also stackable and modular and has room comfortably for the ePaper Display HAT. It is clear and sturdy and also has rubber feet to slightly elevate it and protect the surface of your table or nightstand, so you can display your weather station and have it easily accessible by your nightstand or coffee table to get the weather information to plan your day! 😊
You can, of course, use any Raspberry Pi, compatible ePaper display or enclosure and just use the code in this project.
Ok, let’s get started!
Step 1 – Mount the Raspberry Pi B+ to the Enclosure Base Plate
Let us first mount the Raspberry Pi to the enclosure’s base plate. This gives it protection while offering full open access to it to configure and setup the RPi and play around with it. When you are ready to close it up, It is easy to add the side walls and top plate and secure everything with screws.
Mount the Raspberry Pi to the base plate, and add feet and other hardware to prepare the enclosure in Platform Configuration. See steps below in the slideshow – the caption for each image is numbered and gives additional explanation for each step.
Here are all the steps as an animated gif:
Step 2 – Plug the Waveshare ePaper HAT into the Raspberry Pi
Next step is to plug the Waveshare ePaper HAT into the Raspberry Pi. Its female header fits into the GPIO pins of the Raspberry Pi. It comes with standoffs to attach it more firmly to the Raspberry Pi. Since we are using it inside a protected enclosure, this step is not necessary and I skipped it. Reuse the standoffs for any later projects! 😉
Step 3 – Configure the Raspberry Pi
The ePaper display uses SPI for communication. We therefore need to enable SPI on the Raspberry Pi, if you haven’t already done so.
Steps to Enable SPI
Launch raspi-config. Go to “Interfacing Options”. Navigate to SPI and press enter. Say yes when asked if you would like the SPI interface to be enabled. See steps below in the slideshow – the caption for each image is numbered and gives additional explanation for each step.
Next, we will need to install the necessary software packages
You can choose to make calls to the Open Weather Map REST APIs and process the JSON object that it returns to extract the fields of choice directly. Or alternately, you can use the PyOWM library – it is an elegant client Python wrapper for the OpenWeatherMap web APIs. You can very quickly make calls to the OWM APIs and consume the data easily using a more object-oriented approach. This is what I went with! Thanks to Claudio Sparpaglione for the PyOWM library!
To install PyOWM on your Raspberry Pi, do the following:
$ pip install pyowm
Read the PyOWM documentation to know more and to see their examples – https://pyowm.readthedocs.io/en/latest/index.html
ProtoStax Weather Station Demo Code
Grab the weather station demo code from the ProtoStax GitHub repository. You can clone it to your Raspberry Pi using the following command:
$ git clone https://github.com/protostax/ProtoStax_Weather_Station_Demo.git
You will need git on your Raspberry Pi of course! Use the following to install git if required:
$ sudo apt-get install git
You can also directly download it in zip format and unzip it.
[Note: The example also uses Waveshare’s e-Paper python3 library. You can find the library on Github at https://github.com/waveshare/e-Paper, but it has the libraries and code for a multitude of displays. I’ve taken the two files that are needed for my e-Paper display and have incorporated them into my own code base, so you don’t need to additionally get and install that library from GitHub. You can refer to the aboveGithub link, and if you are using a different sized display, you can always grab the requisite library files from the above repository! ]
Step 4 – Get Open Weather Map API Key
Sign up for account at Open Weather Map
Generate an API key. Note the API key generated – you will use it later in the Weather Station python program.
See steps below in the slideshow – the caption for each image is numbered and gives additional explanation for each step.
Step 5 – Demo Code
Let’s take a look at the demo code and see what it is doing. To do that, we can split it up into two main parts.
- Open Weather Map
- ePaper display
You can quickly reference the demo code here:
You initialize your instance of the ePaper display using the following:
epd = epd2in7b.EPD()
init() and Clear() methods are used to initialize the object, and clear the contents of the display, respectively.
You can draw on the display using Python PIL’s Image, ImageDraw and ImageFont. The epd library uses two images, one for black and one for red, to display black and red images on top of a white background. You first create two Images as shown:
# Drawing on the Horizontal image HBlackimage = Image.new('1', (epd2in7b.EPD_HEIGHT, epd2in7b.EPD_WIDTH), 255) # 298*126 HRedimage = Image.new('1', (epd2in7b.EPD_HEIGHT, epd2in7b.EPD_WIDTH), 255) # 298*126
After drawing on the individual black and white Images all the text and icons and stuff you want to display (we’ll look at this later), you make the ePaper display it using
The actual formatting of the Images will be discussed in the section below.
Open Weather Map – Getting and Displaying the Data
Firstly, you will need to replace the placeholder string below with your own OWM API Key that you generated in the previous step:
owm = pyowm.OWM('REPLACE_WITH_YOUR_OWM_API_KEY')
With the owm object thus initialized, you can invoke methods on it that will in turn call the APIs and return the results as objects.
You can invoke the weather APIs by either City Name, City ID, Lat/Lon or Zip Code. According to Open Weather Map,
“We recommend to call API by city ID to get unambiguous result for your city. “
You can find your own city id by downloading, unzipping and checking the JSON file from the following:
Locate your city there and note the city ID. You can replace it in the code below. In the example, the city ID for Mountain View, CA is used.
# REPLACE WITH YOUR CITY ID city_id = 5375480 # Mountain View, CA, USA
You can, of course, play around with other modes of invoking the APIs, like Lat/Lon, for example.
In the main function, we start with getting the current weather data for the city specified by the city_id.
def main(): epd = epd2in7b.EPD() while True: # Get Weather data from OWM obs = owm.weather_at_id(city_id) location = obs.get_location().get_name() weather = obs.get_weather() reftime = weather.get_reference_time() description = weather.get_detailed_status() temperature = weather.get_temperature(unit='fahrenheit') humidity = weather.get_humidity() pressure = weather.get_pressure() clouds = weather.get_clouds() wind = weather.get_wind() rain = weather.get_rain() sunrise = weather.get_sunrise_time() sunset = weather.get_sunset_time() ...
It is fairly self-explanatory. We get the weather (obs.weather_at_id()) for the specified city_id. From that returned observation object, we can get the location information (e.g. Mountain View), as well as the weather object. The weather object has details like reference time when the observation was made, temperature, humidity, pressure, clouds, rain, sunrise time, sunset time, and so on.
Next, we would like to take that information and present it in a human-readable format. For example, temperature readings are good enough to round up to the nearest integer, as is the humidity. We would like to present the sunrise and sunset times in the local time, with AM/PM identifiers. We would also like to use icons and images to spruce up the interface and break the visual monotony.
An easy way to display icons and artwork on your ePaper display is to use a font like Meteocons, which maps font letters to specific icons, so by printing a character “B” you can print a Sunny icon!
Open Weather Map has weather codes for the current weather report, that correspond to different conditions like sunny, cloudy, etc. Check Weather Condition Codes under https://openweathermap.org/weather-conditions for the full list of weather codes.
I have created a weather_icon_dict dictionary that maps the weather codes from OWM to suitable icons from Meteocons. This enables us to easily use artwork and icons for display by simply using the character corresponding to that icon!
For example, I take the weather_code that I receive from OWM, and use the weather_icon_dict to get the mapping to the corresponding Meteocons icon, and then display that icon by just printing that character with the Meteocons font as shown below:
drawred.text((264 - w3 - 10, 0), weather_icon_dict[weather.get_weather_code()], font = fontweatherbig, fill = 0)
This will display icons for weather codes, like Sunny or Partly Cloudy etc. You can always modify the weather_icon_dict to the change the mapping to your taste!
Refer to http://www.alessioatzeni.com/meteocons/ for the mapping of meteocons to characters, and modify the dictionary below to change icons you want to use for different weather conditions!
Meteocons is free to use – you can customize the icons – do consider contributing back to Meteocons!
Because of the usage of Meteocons icons, every bit of information in the display below is just a text string, and the font size can be easily changed to play around with proportions. I played around with the information and the layout until I was satisfied with the look and feel, and showing the fields that were important to me.