Create a Raspberry Pi Countdown Timer for Pi Day

Create a Raspberry Pi Countdown Timer for Pi Day
Introduction: Use Raspberry Pi and an e-paper display to start the countdown to your next holiday.
Article length: 9501 words, reading time approximately: 12 minutes

Pi Day🔗 en.wikipedia.org(Pi Day) (March 14) has come and gone, leaving behind wonderful memories and many Raspberry Pi projects🔗 opensource.com 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🔗 www.raspberrypi.org and used it to solve WiFi signal issues🔗 opensource.com. I was also very interested in using e-paper(ePaper) 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🔗 www.waveshare.com 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🔗 www.raspberrypi.org 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.

Create a Raspberry Pi Countdown Timer for Pi Day

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.

Create a Raspberry Pi Countdown Timer for Pi Day

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(Interfacing Options)-> SPI -> Yes(Yes)” to enable the SPI interface, then reboot.

Create a Raspberry Pi Countdown Timer for Pi Day

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

Create a Raspberry Pi Countdown Timer for Pi Day

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.

Create a Raspberry Pi Countdown Timer for Pi Day

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:

◈ WaveShare e-paper setup guide🔗 www.waveshare.com
◈ WaveShare e-paper library installation guide🔗 www.waveshare.com

Create a Raspberry Pi Countdown Timer for Pi Day

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🔗 scripts.sil.org. 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

Create a Raspberry Pi Countdown Timer for Pi Day

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🔗 github.com Python file from the project’s GitHub repository🔗 github.com and jump to the end of the article.

To satisfy everyone’s curiosity, I will explain step by step.

Create a Raspberry Pi Countdown Timer for Pi Day

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.

Create a Raspberry Pi Countdown Timer for Pi Day

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)

Create a Raspberry Pi Countdown Timer for Pi Day

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

Create a Raspberry Pi Countdown Timer for Pi 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.

Create a Raspberry Pi Countdown Timer for Pi Day

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:

Create a Raspberry Pi Countdown Timer for 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:

Create a Raspberry Pi Countdown Timer for Pi Day

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!

Create a Raspberry Pi Countdown Timer for Pi Day

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🔗 wiki.archlinux.org.

Copy the piday.service🔗 github.com 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.

Create a Raspberry Pi Countdown Timer for Pi Day

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

Create a Raspberry Pi Countdown Timer for Pi Day
LCTT Translator: Donkey
🌟🌟
Create a Raspberry Pi Countdown Timer for Pi Day
Translation: 2.0 articles

|

Contribution: 9 days
2022-06-09
→
2022-06-18
https://linux.cn/lctt/Donkey-Hao
Welcome to reprint in accordance with the CC-BY-SA agreement,
If you need to reprint, please leave a message under the article “Reprint: Public Account Name“,
We will add you to the whitelist and authorize “to modify when reprinting the article“.

Leave a Comment

Your email address will not be published. Required fields are marked *