Pi Day (March 14) has come and gone, leaving behind wonderful memories and many Raspberry Pi projects waiting for us to try. It’s hard to return to work after any exciting, joyful holiday, and Pi Day is no exception. As we look back on March, we yearn for the joy of those days. But fear not, dear Pi Day celebrators, we are starting the long countdown to the next holiday!
Alright, let’s get serious. I made a Pi Day countdown timer, and you can too!
A while ago, I bought a Raspberry Pi Zero W and used it to solve WiFi signal issues. I was also very interested in using e-paper as its display. Although I didn’t know what to do with it, it looked really fun! I bought a 2.13-inch WaveShare display that fits perfectly on top of the Raspberry Pi. The installation was simple: just connect the display to the Raspberry Pi’s GPIO.
I used the Raspberry Pi Operating System to implement the project, although other operating systems could certainly work too. However, the raspi-config
command is very easy to use on the Raspberry Pi system.
Setting up the Raspberry Pi and e-paper display
To get the Raspberry Pi and e-paper display to work together, you need to enable the Serial Peripheral Interface (SPI) in the Raspberry Pi software, install the BCM2835 C library (to access the GPIO functions of the Broadcom BCM 2835 chip on the Raspberry Pi), and install the Python GPIO library to control the e-paper display. Finally, you need to install the WaveShare library to control the 2.13-inch display using Python.
Here are the steps to complete these tasks.
Enabling SPI
The easiest way to enable SPI on the Raspberry Pi is to use the raspi-config
command. The SPI bus allows for serial data communication with devices—in this case, the e-paper display:
$ sudo raspi-config
From the pop-up menu, select “Interface Options-> SPI -> Yes” to enable the SPI interface, then reboot.
Installing the BCM2835 library
As mentioned above, the BCM2835 library is software for the Broadcom BCM2385 chip on the Raspberry Pi, allowing access to GPIO pins to control devices.
As of the time of writing this article, the latest version of the Broadcom BCM2385 library for the Raspberry Pi is v1.68. To install this library, you need to download the software package and then use make
to install:
# Download the BCM2853 library and extract
$ curl -sSL http://www.airspayce.com/mikem/bcm2835/bcm2835-1.68.tar.g> -o - | tar -xzf -
# Enter the extracted folder
$ pushd bcm2835-1.68/
# Configure, check, and install the BCM2853 library
$ sudo ./configure
$ sudo make check
$ sudo make install
# Return to the parent directory
$ popd
Installing the required Python libraries
To control the e-paper display with Python, you need to install the Python library RPi.GPIO
, and you also need to use the python3-pil
package for drawing. Obviously, the PIL package is no longer maintained, but Pillow can be used as a replacement. I haven’t tested Pillow for this project, but it should work:
# Install the required Python libraries
$ sudo apt-get update
$ sudo apt-get install python3-pip python3-pil
$ sudo pip3 install RPi.GPIO
Note: These are commands for Python3. You can find commands for Python2 on the WaveShare website.
Downloading WaveShare examples and Python libraries
Waveshare maintains a GitHub repository for Python and C to use with their e-paper displays and provides examples of how to use them. For this countdown clock, you need to clone this repository and use the library for the 2.13-inch display:
# Clone this WaveShare e-Paper git repository
$ git clone https://github.com/waveshare/e-Paper.gi>
If you are using a different display or products from another company, you will need to use the appropriate software.
Waveshare provides a lot of guidance:
Getting fun fonts (optional)
You can use the display however you like, so why not have some fun? Find a cool font!
There are many fonts available under open font licenses. I really love the Bangers font. If you’ve seen it on YouTube, you’ve probably seen this font; it’s quite popular. You can download it to the local shared fonts directory, and all applications can use it, including this project:
# The "Bangers" font is licensed under an open license by Vernon Adams using Google Fonts
$ mkdir -p ~/.local/share/fonts
$ curl -sSL https://github.com/google/fonts/raw/master/ofl/bangers/Bangers-Regular.ttf -o fonts/Bangers-Regular.ttf
Creating a Pi Day countdown timer
Now that you have installed the software, you can use the e-paper display with the cool font. You can create a fun project: a countdown to the next Pi Day!
If you want, you can directly download the countdown.py Python file from the project’s GitHub repository and jump to the end of the article.
To satisfy everyone’s curiosity, I will explain step by step.
Importing some libraries
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import logging
import os
import sys
import time
from datetime import datetime
from pathlib import Path
from PIL import Image,ImageDraw,ImageFont
logging.basicConfig(level=logging.INFO)
basedir = Path(__file__).parent
waveshare_base = basedir.joinpath('e-Paper', 'RaspberryPi_JetsonNano', 'python')
libdir = waveshare_base.joinpath('lib')
Start by importing some standard libraries that will be used in the script. You also need to import Image
, ImageDraw
, and ImageFont
from PIL, which you will use to draw some simple graphics. Finally, set some variables for the local lib
directory, which contains the Waveshare Python library for the 2.13-inch display that you will use later to load the library from the local directory.
Font size helper function
The next part is to create a helper function to adjust the size of the Bangers-Regular.ttf font that you choose. This function will take an integer variable as the size parameter and return a graphic font object to be used for display:
def set_font_size(font_size):
logging.info("Loading font...")
return ImageFont.truetype(f"{basedir.joinpath('Bangers-Regular.ttf').resolve()}", font_size)
Countdown logic
Next is a function to calculate how long until the next Pi Day. If it’s January, calculating the remaining days will be simple. However, you need to consider whether this year’s Pi Day has already passed (sadly). If it has, then calculate how many days until you can celebrate again:
def countdown(now):
piday = datetime(now.year, 3, 14)
# If missed, add a year
if piday < now:
piday = datetime((now.year + 1), 3, 14)
days = (piday - now).days
logging.info(f"Days till piday: {days}")
return day
Main function
Finally, we reach the main function, where you need to initialize the display and write data to it. Here, you should write a greeting and then start the countdown. But first, you need to load the Waveshare library:
def main():
if os.path.exists(libdir):
sys.path.append(f"{libdir}")
from waveshare_epd import epd2in13_V2
else:
logging.fatal(f"not found: {libdir}")
sys.exit(1)
The code snippet above checks to ensure that the library has been downloaded to the directory next to the countdown script, then loads the epd2in13_V2
library. If you are using a different display, you will need to use a different library. If you want, you can write your own. I found it interesting to read the Python code provided by Waveshare with the display, which is much simpler than I imagined.
The next piece of code creates an EPD (electronic paper display) object to interact with the display and initializes the hardware:
logging.info("Starting...")
try:
# Create a display object
epd = epd2in13_V2.EPD()
# Initialize and clear the display
# ePaper retains its state between updates
logging.info("Initialize and clear...")
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
One interesting thing about e-paper: it only consumes power when changing pixels from white to black or from black to white. This means that when the device is powered off or the application stops for any reason, anything on the screen will remain. This is great from a power consumption perspective, but it also means you need to clear the display at startup; otherwise, your script will just overwrite whatever is already on the screen. Therefore, epd.Clear(0xFF)
is used to clear the display at the start of the script.
Next, create a “canvas” to draw the remaining display output:
# Create a graphic object
# Note: "epd.height" is the long side of the screen
# Note: "epd.width" is the short side of the screen
# Quite counterintuitive…
logging.info(f"Creating canvas - height: {epd.height}, width: {epd.width}")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
This matches the width and height of the display—but it’s a bit counterintuitive since the short side of the display is the width. I thought the long side was the width, so this is just something to keep in mind. Note that epd.height
and epd.width
are set by the Waveshare library to correspond to the device you are using.
Greeting
Next, you will start drawing some graphics. This involves setting data on the “canvas” object you created earlier. This has not yet drawn it to the e-paper display—you are just building the image you want. You can draw an image of a pie to create a welcome message celebrating Pi Day:
Drawing a pie
Isn’t it cute?
logging.info("Set text text...")
bangers64 = set_font_size(64)
draw.text((0, 30), 'PI DAY!', font = bangers64, fill = 0)
logging.info("Set BMP...")
bmp = Image.open(basedir.joinpath("img", "pie.bmp"))
image.paste(bmp, (150,2))
Finally, truly finally, you can display your drawing:
logging.info("Display text and BMP")
epd.display(epd.getbuffer(image))
The above snippet updates the display to show the image you drew.
Next, prepare another image to show your countdown:
Pi Day countdown
First, create an image object to display the countdown. You will also need to set the font size for the numbers:
logging.info("Pi Date countdown; press CTRL-C to exit")
piday_image = Image.new('1', (epd.height, epd.width), 255)
piday_draw = ImageDraw.Draw(piday_image)
# Set font size
bangers36 = set_font_size(36)
bangers64 = set_font_size(64)
To make it look more like a countdown when displayed, updating part of the image is a more efficient approach, changing only the parts of the display data that have changed. The following code prepares to run in this way:
# Prepare to update the display
epd.displayPartBaseImage(epd.getbuffer(piday_image))
epd.init(epd.PART_UPDATE)
Finally, you need to time it, starting an infinite loop to check how long until the next Pi Day and display it on the e-paper. If it reaches Pi Day, you can output a celebratory phrase:
while (True):
days = countdown(datetime.now())
unit = get_days_unit(days)
# Clear the bottom half of the screen by drawing a rectangle filled with white
piday_draw.rectangle((0, 50, 250, 122), fill = 255)
# Draw header
piday_draw.text((10,10), "Days till Pi-day:", font = bangers36, fill = 0)
if days == 0:
# Draw celebratory phrase
piday_draw.text((0, 50), f"It's Pi Day!", font = bangers64, fill = 0)
else:
# Draw time until next Pi Day
piday_draw.text((70, 50), f"{str(days)} {unit}", font = bangers64, fill = 0)
# Render the screen
epd.displayPartial(epd.getbuffer(piday_image))
time.sleep(5)
The script ends with some error handling, including catching keyboard interrupts so that you can use Ctrl + C
to end the infinite loop, along with a function to print day
or days
based on the count:
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
logging.info("Exiting...")
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
time.sleep(1)
epd2in13_V2.epdconfig.module_exit()
exit()
def get_days_unit(count):
if count == 1:
return "day"
return "days"
if __name__ == "__main__":
main()
Now you have a script that counts down and displays the remaining days!
Installing systemd service (optional)
If you want to run the countdown display when the system boots, without needing to log in and run the script, you can install an optional systemd unit as a systemd user service.
Copy the piday.service file from GitHub to ${HOME}/.config/systemd/user
. If this directory doesn’t exist, create it first. Then you can enable and start the service:
$ mkdir -p ~/.config/systemd/user
$ cp piday.service ~/.config/systemd/user
$ systemctl --user enable piday.service
$ systemctl --user start piday.service
# Enable lingering, to create a user session at boot
# and allow services to run after logout
$ loginctl enable-linger $USER
The script will output to the systemd logs, which you can view using the journalctl
command.
It’s starting to look like Pi Day!
This is your work! A countdown timer for Pi Day displayed on an e-paper display using Raspberry Pi Zero W! And it starts using the systemd unit file at system boot! Now there are many days until we can gather again to celebrate Pi Day—a wonderful device—Raspberry Pi. Through our little project, we can see the exact number of days at a glance.
But in reality, everyone can celebrate Pi Day in their hearts every day, so please use your Raspberry Pi to create some fun and educational projects!
via: https://opensource.com/article/21/3/raspberry-pi-countdown-clock
Author: Chris Collins Edited by: lujun9972 Translated by: Donkey Proofread by: wxy
This article is originally compiled by LCTT and proudly presented by Linux China
|
Leave a Comment
Your email address will not be published. Required fields are marked *