An over-engineered weather display. Face the inevitable wind and rain in style!
Depending on your preferences, you could either do a full battery-powered build or a simplified, USB-powered build.
- RaspberryPi Zero W (without GPIO headers)
- Long headers (18mm)
⚠️ Soldering required! - Pimoroni Inky pHAT display (my build has v1 of the pHAT, which is lower resolution)
- PiSupply PiJuice Zero
- PiSupply PiJuice Zero 1200mAh Battery
- 3D printed case
- Any RaspberryPi (pre-soldered GPIO works perfectly)
- Pimoroni Inky pHAT display
- Optional: A better-designed case, like the one from Balena Inkyshot
Again, depending on your build, there are two flavours:
- Config-file driven
- Wakes up PiZero every hour
- Reports the battery level to NewRelic (so you can get alerted when the battery is low)
- Updates the display
- Creates both a local and a remote (NewRelic) log entry for each run
- Sets PiZero to sleep for an hour (or until next morning, if in quiet time)
- A single CLI script that takes various arguments and either updates the Inky pHAT display or outputs image to a file
- Install RaspberryPi Lite OS — you could use the full-blown (desktop) OS but that will needlessly drain your battery on each wake-up.
- Configure your wireless networking. Ensure that "Wait for network on boot" is enabled in
raspi-config
- Enable I2C and SPI in
raspi-config
- Recommended: Set-up SSH on your RaspberryPi
- Install Inky pHAT software. In short:
curl https://get.pimoroni.com/inky | bash
and say Y to everything (to install all additional packages we'll need later). - Recommended: Verify that your installation works by running one of Pimoroni code examples, e.g. the Name Badge Example.
- Copy
weather.py
somewhere to your RaspberryPi. e.g./home/[you]
- Set up
weather.py
to run every half an hour:- Run the crontab editor:
crontab -e
- Add the following line:
*/30 * * * * python3 /home/[you]/weather.py
(this will give you weather in Amsterdam, see the following section on how to pass parameters)
- Run the crontab editor:
- Install PiJuice software. Since we're running headless, that boils down to
sudo apt-get install pijuice-base
- If you haven't connected the battery yet, power down, connect the battery, connect back to the power and run
pijuice_cli
.- Ensure that your battery is recognised correctly, and if not - change the battery profile
- Set the correct RTC time
- Set up a free NewRelic account
- Create a copy of
config.ini.SAMPLE
and call itconfig.ini
- Copy your NewRelic License API key to
config.ini
- Edit the rest of the file to reflect your preferences.
- Copy your NewRelic License API key to
- Copy all of the code from this repository somewhere to your RaspberryPi. e.g.
/home/[you]/inky-weatherbox
- Set up
runandturnoff.py
to run on every boot:- Run the crontab editor:
crontab -e
- Add the following lines:
@reboot python3 /home/[you]/inky-weatherbox/runandturnoff.py
(make sure to use the same path from the previous step)
- Run the crontab editor:
- Recommended: Set
runandturnoff.py
to run when you switch from USB power (charging) to battery power:- Enable "No power" System Event and set it to
USER_FUNC1
- Configure
USER_FUNC1
to point to/home/[you]/inky-weatherbox/runandturnoff.py
(make sure that the file is executable)
- Enable "No power" System Event and set it to
- Optional: Create a dashboard in NewRelic to track the battery life:
- Click + Create a Dashboard > Create a New Dashboard
- To view the battery level:
- Click Add a widget > Add a chart
- Add this query:
SELECT latest(battery.charge_level) FROM Metric WHERE app.name ='inky-weatherbox' TIMESERIES AUTO
(if you changed the app name inconfig.ini
update it here). - Click Run
- Set Chart name to "Battery"
- Expand Null values and set the dropdown value to Remove
- Click Save
- To view the latest log entries:
- Click Add a widget > Add a chart
- Add this query:
SELECT message,batt FROM Log ORDER BY timestamp DESC
- Click Save
- Optional: Set up an alert when the battery level is low
SELECT latest(battery.charge_level) FROM Metric WHERE app.name = 'inky-weatherbox'
runandturnoff.py
(source)
This file is, essentially, the implementation of the Full Build logic.
If it's run on battery power, it will turn RaspberryPi off after the run. If it's run while being charged via any of the USB ports (on RaspberryPi or PiJuice) it will not turn RaspberryPi off (and will not schedule the next run).
weather.py
(source)
This file is either called by runandturnoff.py
or it can be executed stand-alone. To see all the CLI parameters, run python3 weather.py -h
(or just ./weather.py -h
). The --mock
mode is useful for testing on a computer that doesn't have Inky pHAT connected as it will output the target image to a file (inky.png
).
./weather.py -lat 44.80 -lon 20.47 # Gets weather for Belgrade, RS in ºC and km/h
./weather.py -lat 54.97 -lon -1.61 -w mph # Gets weather for Newcastle upon Tyne, UK in ºC and mph
./weather.py -lat 25.04 -lon 77.35 -w kn -t F # Gets weather for Nassau, BS in ºF and knots
./weather.py -m v1 # Gets weather for Amsterdam and creates inky.png instead of updating the display
ℹ️ All of the previous examples can be run as python3 weather.py
as well.
🪫 The battery life is pretty bad.
Even with all of the unorthodox optimisations, I couldn't get more than ~12 days out of the 1200mAh battery. What drains the battery the most is the OS boot sequence, which takes about 2 minutes. I tried disabling a lot of services, using static DNS and IP address (to not wait for the DHCP server), and getting a blazing fast SD-card — all of which shaved a few seconds off the boot process, but not enough.
🛜 The WiFi is wonky AF.
I've spent many hours fighting with WiFi and trying to make sure that RaspberryPi has internet connection as quickly as possible and that the runandturnoff.py
is only run after the internet connection is fully established. With every patch (some of which are outlined in Networking section below) the system became more complex, but not more reliable.
🫥 The battery may not deliver enough power
After being on a holiday for a few weeks, and leaving inky-weatherbox
to drain its battery without recharging, I experienced that, upon a new charge, the display gave a washed-out image, and even that red colour wasn't getting displayed at all. At first, I thought that I had damaged the screen, but once I plugged the RaspberryPi into USB, the colours were vivid and sharp again. I remember reading that eInk screens need reliable power supply to properly update the image, and it might be that the battery I'm using got damaged (or that there's a different reason it stopped working after barely 3 12-day cycles). At this point I gave up on running this project off a battery, so I didn't investigate further.
🖼️ Only works sensibly on Inky pHAT
While the code will not break if you try to run it with Inky wHAT or Inky Impression, the output will be all over the place. Contributions welcome!
🧠 In short:
I've picked wrong tools for the task. I was blinded by the idea of having an ultra-tiny easily-programmable computer, and I got carried away equating single-purpose microcontrollers I have around my house, with generic-purpose high-level computer such as RaspberryPi. Still, it was a valuable lesson in building hardware as I had to learn a lot of new skills (how to solder and more so: how to desolder, how RTC/low power consumption works, how to find overly specific components, how to make a simple 3D model, etc).
🤔 Why bother sharing, then?
When I got the idea to build this, the information was very fragmented and spread across many websites. The code in here is patchwork of about 10 different online resources. While it's very far from perfect, at least there are 2 good things about it:
weather.py
works without you having to create any weird API keys (kudos to Open-Meteo)- I plan to reuse
runandturnoff.py
for a different incredibly original project soon. Maybe I generalise it then 🤷♂️
Here are some resources that I've been looking into when trying to shave seconds off the RaspberryPi's boot (to prolong the battery life).
- Set static IP address (Network Interfaces method)
- Real wait for network on boot (written for
networking.service
, notdhcpcd.service
)
- Disable system services
- Disable splash screen on boot
- See what's slowing up startup:
systemd-analyze blame
systemd-analyze critical-chain
Copyright © 2023 Dachaz. This software is licensed under the MIT License.
Parts of the image generation code Copyright © 2020 Derek Caelin.