Weather Report: building a weather station

As a project idea for a young engineer we wanted to build a Raspberry Pi-based Weather Station. Our last attempt at building something – a sound-responsive LED display – was a failure. So it was important to build something really easy to help us get back on track. Here are some notes.

We essentially followed this guide from Adafruit which links out to this guide for the CircuitPython part. Both were easy enough to understand although there are a few choices to make, so I thought this short post would be worth it to show how we got this project working.

Hardware

First choice was hardware. There’s a chip shortage at the moment and although I wanted to build this on a Pi ZeroW, I couldn’t source one. I happened to have a Raspberry Pi 3A which was unused. This model is wi-fi enabled, so I went ahead with it. For the screen, I bought an Adafruit 2.13″ Monochrome E-Ink Bonnet for Raspberry Pi (Think Ink) from the Pi Hut. This is as simple as it gets because the bonnet just sits on the GPIO pins on the Pi and no further fuss is needed. You can do this build using other, simpler boards and use a display that requires wiring in, but I knew my young companion would not have the patience for that. Our Pi 3A was already in a Pimironi rainbow case. It turned out that the bonnet could sit on the pins and be clear of the case, so that all worked out.

On to the setup

Setting up a Raspberry Pi is straightforward. Just use the imager to write the OS to the SD card. Configure and enable SSH, and away you go. First step is to enable the e-Ink display with CircuitPython and then install the weather station code.

CircuitPython setup

The instructions for this are straightforward but they start on the third page of this guide. So, in brief over ssh or on the Pi itself if you have attached a monitor:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pip
sudo pip3 install --upgrade setuptools
cd ~
sudo pip3 install --upgrade adafruit-python-shell
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
sudo python3 raspi-blinka.py

Next you need to verify that I2C and SPI are enabled.

ls /dev/i2c* /dev/spi*

Should give

/dev/i2c-1 /dev/spidev0.0 /dev/spidev0.1

We ran the suggested test file blinkatest.py which is described on the page, but you could skip if you want.

Next there are just a couple of steps required on the Pi before you can install the Weather Station code.

sudo pip3 install adafruit-circuitpython-epd
sudo apt-get install fonts-dejavu
sudo apt-get install python3-pil

That’s it for CircuitPython setup.

Weather station setup

To make requests we need an API key for OpenWeatherMap.org – it’s free and sign-up is here. You should get an email with your 33 character API key. Next, we need the code to run the weather station.

wget -O EInk_Bonnet_Weather_Station.zip https://learn.adafruit.com/pages/19816/elements/3075247/download?type=zip

Here, I am using the code from the guide. There is a GitHub repo which may be more up-to-date.

unzip EInk_Bonnet_Weather_Station.zip
cd EInk_Bonnet_Weather_Station/
sudo nano code.py

The code you downloaded needs to be edited to add your API key and your location. Place these between quotes after the variables OPEN_WEATHER_TOKEN and LOCATION

# You'll need to get a token from openweathermap.org, looks like:
# 'b6907d289e10d714a6e88b30761fae22'
OPEN_WEATHER_TOKEN = ""
# Use cityname, country code where countrycode is ISO3166 format.
# E.g. "New York, US" or "London, GB"
LOCATION = "Manhattan, US"

The most challenging part of this project was getting my young companion to rekey the 33 character API code in nano ! Exit nano by ctrl + x and confirm the save with y.

Now, if you run it, it should work.

python3 weather.py

And sure enough:

Success!

Note that if python3 is the default on your system (it should be) you can just use python rather than python3

The code is set to refresh the display and update the weather every five minutes.

There is some more detail on the guide about how to get things working more smoothly. Here is a quick summary of what we did.

Final touches

It’s recommended to move the font into the system fonts. From home:

sudo mkdir /usr/share/fonts/truetype/meteocons
sudo cp EInk_Bonnet_Weather_Station/meteocons.ttf /usr/share/fonts/truetype/meteocons/meteocons.ttf

Then edit the file weather_graphics.py

cd EInk_Bonnet_Weather_Station/
sudo nano weather_graphics.py

so that the location of the font is correct, i.e. edit this line to read:

icon_font = ImageFont.truetype("/usr/share/fonts/truetype/meteocons/meteocons.ttf", 48)

Then edit code.py so that a) it shows the temperature in celsius and b) runs correctly on boot:

display.rotation = 1

gfx = Weather_Graphics(display, am_pm=False, celsius=True)
weather_refresh = None

# when running on boot using rc.local we need a delay to allow network setup
time.sleep(20)

while True:

Now, b above is a hack to get around a problem that took a while to resolve. We wanted the weather station to just work on booting up with no further maintenance required.

I moved code.py and weather_graphics.py out of their directory and into home to make things simpler. Now to run on boot we can add this line to rc.local just run

sudo nano /etc/rc.local

and then add

python /home/username/code.py &

before the line exit 0

What this does is runs this line at the end of the boot sequence. The ampersand & at the end of the line is very important as it means that the Pi is free to do other things without waiting for code.py to finish (which it doesn’t, it just continually refreshes).

While this worked, it gave an error because the boot sequence completed, and the code ran for the first iteration before a network connection was established. The result was that the script crashed. Rather than do anything more complicated on the system side, I introduced a short delay until the first request to OpenWeather is made (this is the hack “b” above).

Result: the Weather Station runs nicely and will just start working when plugged in at a new location.

Conclusion

After a previous build that became very complicated, it was important to build something simple that “just worked”. My young companion was very pleased that she managed to make the weather station and that it accurately reports the weather.

The post title comes from a band this time. How could it not be “Weather Report”?