Weather Display on e-Paper Using Raspberry Pi

Introduction

Continue from the previous tutorial, now we will make the weather display on e-paper using Raspberry Pi. The data will be obtained from openweathermap.org.

Video

This video shows how to create weather display on e-paper using Raspberry Pi.

Hardware Preparation

This is the list of items used in the video.

Sample Program

This is python3 sample program to display weather data (from openweathermap.org) on e-paper using Raspberry Pi. You may need to install meteocons font with following command:

curl --remote-name https://www.alessioatzeni.com/meteocons/res/download/meteocons-font.zip && unzip meteocons-font.zip
# This code was based on code taken from a tutorial on the Adafruit website.
# https://learn.adafruit.com/raspberry-pi-e-ink-weather-station-using-python
#
# e-Paper:
# – https://my.cytron.io/p-universal-e-paper-raw-panel-driver-hat?tracking=idris
# – https://my.cytron.io/p-2.9-inch-e-ink-raw-display-panel-tri-color?tracking=idris
#
# Register at https://openweathermap.org/ and get the token (API key)
#
# Download meteocons font and unzip
# curl –remote-name https://www.alessioatzeni.com/meteocons/res/download/meteocons-font.zip && unzip meteocons-font.zip
import time
import urllib.request
import urllib.parse
import digitalio
import busio
import board
from adafruit_epd.il0373 import Adafruit_IL0373
from weather_graphics import Weather_Graphics
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D25)
rst = digitalio.DigitalInOut(board.D17)
busy = digitalio.DigitalInOut(board.D24)
srcs = None
# 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 = "Kuala Lumpur, MY"
DATA_SOURCE_URL = "http://api.openweathermap.org/data/2.5/weather"
if len(OPEN_WEATHER_TOKEN) == 0:
raise RuntimeError(
"You need to set your token first. If you don't already have one, you can register for a free account at https://home.openweathermap.org/users/sign_up"
)
# Set up where we'll be fetching data from
params = {"q": LOCATION, "appid": OPEN_WEATHER_TOKEN}
data_source = DATA_SOURCE_URL + "?" + urllib.parse.urlencode(params)
# Initialize the Display
display = Adafruit_IL0373(
128, 296, spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy
)
display.rotation = 3
gfx = Weather_Graphics(display, am_pm=True, celsius=True)
weather_refresh = None
while True:
# only query the weather every 10 minutes (and on first run)
if (not weather_refresh) or (time.monotonic() weather_refresh) > 600:
response = urllib.request.urlopen(data_source)
if response.getcode() == 200:
value = response.read()
print("Response is", value)
gfx.display_weather(value)
weather_refresh = time.monotonic()
else:
print("Unable to retrieve data at {}".format(url))
gfx.update_time()
time.sleep(300) # wait 5 minutes before updating anything again

view raw
weather.py
hosted with ❤ by GitHub

from datetime import datetime
import json
from PIL import Image, ImageDraw, ImageFont
from adafruit_epd.epd import Adafruit_EPD
small_font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 16
)
medium_font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20
)
large_font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24
)
icon_font = ImageFont.truetype(
"./meteocons.ttf", 48
)
# Map the OpenWeatherMap icon code to the appropriate font character
# See http://www.alessioatzeni.com/meteocons/ for icons
ICON_MAP = {
"01d": "B",
"01n": "C",
"02d": "H",
"02n": "I",
"03d": "N",
"03n": "N",
"04d": "Y",
"04n": "Y",
"09d": "Q",
"09n": "Q",
"10d": "R",
"10n": "R",
"11d": "Z",
"11n": "Z",
"13d": "W",
"13n": "W",
"50d": "J",
"50n": "K",
}
# RGB Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Weather_Graphics:
def __init__(self, display, *, am_pm=True, celsius=True):
self.am_pm = am_pm
self.celsius = celsius
self.small_font = small_font
self.medium_font = medium_font
self.large_font = large_font
self.display = display
self._weather_icon = None
self._city_name = None
self._main_text = None
self._temperature = None
self._description = None
self._time_text = None
def display_weather(self, weather):
weather = json.loads(weather.decode("utf-8"))
# set the icon/background
self._weather_icon = ICON_MAP[weather["weather"][0]["icon"]]
city_name = weather["name"] + ", " + weather["sys"]["country"]
print(city_name)
self._city_name = city_name
main = weather["weather"][0]["main"]
print(main)
self._main_text = main
temperature = weather["main"]["temp"] 273.15 # its…in kelvin
print(temperature)
if self.celsius:
self._temperature = "%d °C" % temperature
else:
self._temperature = "%d °F" % ((temperature * 9 / 5) + 32)
description = weather["weather"][0]["description"]
description = description[0].upper() + description[1:]
print(description)
self._description = description
# "thunderstorm with heavy drizzle"
self.update_time()
def update_time(self):
now = datetime.now()
self._time_text = now.strftime("%I:%M %p").lstrip("0").replace(" 0", " ")
self.update_display()
def update_display(self):
self.display.fill(Adafruit_EPD.WHITE)
image = Image.new("RGB", (self.display.width, self.display.height), color=WHITE)
draw = ImageDraw.Draw(image)
# Draw the Icon
(font_width, font_height) = icon_font.getsize(self._weather_icon)
draw.text(
(
self.display.width // 2 font_width // 2,
self.display.height // 2 font_height // 2 5,
),
self._weather_icon,
font=icon_font,
fill=BLACK,
)
# Draw the city
draw.text(
(5, 5), self._city_name, font=self.medium_font, fill=BLACK,
)
# Draw the time
(font_width, font_height) = medium_font.getsize(self._time_text)
draw.text(
(5, font_height * 2 5),
self._time_text,
font=self.medium_font,
fill=BLACK,
)
# Draw the main text
(font_width, font_height) = large_font.getsize(self._main_text)
draw.text(
(5, self.display.height font_height * 2),
self._main_text,
font=self.large_font,
fill=BLACK,
)
# Draw the description
(font_width, font_height) = small_font.getsize(self._description)
draw.text(
(5, self.display.height font_height 5),
self._description,
font=self.small_font,
fill=BLACK,
)
# Draw the temperature
(font_width, font_height) = large_font.getsize(self._temperature)
draw.text(
(
self.display.width font_width 5,
self.display.height font_height * 2,
),
self._temperature,
font=self.large_font,
fill=BLACK,
)
self.display.image(image)
self.display.display()

view raw
weather_graphics.py
hosted with ❤ by GitHub

Thank You

References:

Thanks for reading this tutorial. If you have any technical inquiries, please post at Cytron Technical Forum.

Please be reminded, this tutorial is prepared for you to try and learn.
You are encouraged to improve the code for better application.

Leave a Comment

Your email address will not be published.

Share this Tutorial

Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest
Share on facebook
Share on whatsapp
Share on email
Share on print
Share on twitter
Share on pinterest

Latest Tutorial

Making A Lucky Draw Device Using Raspberry Pi Pico
Raspberry Pi Pico VS Arduino MKRZero
Raspberry Pi Pico VS Teensy LC
A New Challenger in MCU Platform – Raspberry Pi Pico
Raspberry Pi Pico VS Arduino UNO
Scroll to Top