I needed to have an updatable calendar to keep track of my children's school agenda, as well as some post-school activities. So instead of using a whiteboard, I thought it would be a nice holiday project to do it with a Raspberry Pi 2 and an e-ink screen. I got some inspiration from this similar project and went for it, and here's the result:
- A Raspberry Pi (any model would do, I did it with a Pi 2), with the Raspberry Pi OS.
- Eink display: 640x384, 7.5inch E-Ink display HAT for Raspberry Pi, yellow/black/white three-color.
- A 1x4 matrix keypad to allow you to switch between the different calendars. There are multiple clones in different shops.
- A photo frame to house the setup. I bought one at a local shop, just make sure it has enough depth to host all the hardware.
- One or more Caldav calendars to display.
By default, the e-ink display includes a hat to connect it directly on top of the GPIO connectors. However, since we want to connect the keypad too, we need to use the cables directly. Refer to the vendor notes to check the GPIO pins you need to connect them to.
The keypad will be connected to GPIO pins 29, 31, 33, 35 and 37.
Once the basic setup and connections are done, you will need to set up the config.ini
file.
This is its syntax:
[DEFAULT]
video = pygame
keyboard = pygame
[weather]
owm_api_key = <insert API key here>
owm_location = <insert location id here>
[calendar]
urls = http://example.com/caldavcal1, http://example.com/caldavcal2, http://example.com/ical3.ics
names = user1, user2, user3
username = user
password = password
We can use two different drivers to be used for both video output and keyboard input. This allows us to hack and tests locally without using the e-ink screen all the time.
- For video, we can use
pygame
for the Pygame driver, oreink
to use the e-ink screen. - For keyboard input, we can use
pygame
to get input from your computer's keyboard, orgpio
to use the 1x4 keypad connected to the GPIO pins 29, 31, 33, 35 and 37 (5, 6, 13, 19 and 26 if you use the BCM2835 pin notation).
You need to subscribe to the "Current Weather Data" API.
Note that you need to sign in as a user (it's free). Once you get the API key and the
location id for your town, add them to the owm_api_key
and owm_location
keys in
the configuration file.
You can use any CalDav or iCal link; in my case, I set up 3 calendars in a Synology DiskStation using Synology Calendar. The code should adapt to any number of calendars, but keep in mind the resolution and font size.
The urls
parameter is a comma-separated list of CalDav or iCal URLs. Currently,
iCal URLs are identified by a trailing .ics
in the calendar URL. This may be
improved in the future.
Since each of those calendars will correspond to an actual person, names
will
contain the list of names for each url. Make sure you spefify the same number
of URLs and names.
The username
and password
fields are self-explaining: include the user and
password to access the calendars, only for CalDav URLs.
If you want to use a different type of calendar, such as Google Calendar, you will need to create a new driver. However, it is possible to export a read-only, secret address for your Google Calendar following this guide.
Note that the library used for iCal support, icalevents has a bug in version 0.1.25 that may prevent events from being properly loaded. This was fixed by this commit, so you will need to update to version 0.1.26 or later. As of this writing, version 0.1.26 is not available on PyPi.
The scripts directory contains a simple launcher script using a virtual environment, and a systemd unit file you can use to ensure the program runs on startup.
When the application is stopped, it should clear the e-ink display, which is a good
idea to avoid displa burnout. In some cases, it may not happen (for example if
you get a power disruption). You can use the reset_eink.py
script in those
cases to clear the screen.
When started, the calendar will show today's calendar for everyone, from 8:00 to 21:00 (times are not configurable at the moment). You can switch to a weekly, Monday-to-Friday calendar for each person by pressing the 2, 3 or 4 buttons in the keypad, and switch back to the daily calendar by pressing 1. Yes, that means that having more than 3 calendars could require code changes ;).
After 9 PM, the calendar will enter in screensaver mode, and display the image
in the img/night_image.jpg
file. The image will be converted to a 1-bit format,
so it's better if you use a 1-bit image already.
If there is a JPG or PNG file named after today's date, in DD-MM-YYYY format (for example, 01-01-2022.png for January 1st, 2022), the screensaver will use that image instead of the default one. Be creative!
Refer to the LICENSE file for licensing details.
The weathericons-regular-webfont font is licensed under the SIL OFL 1.1 license.
The DejaVuSansMono-Bold font is licensed under the Bitstream Vera and Public Domain.
The epd7in5bc.py
and epdconfig.py
files are taken from the Waveshare e-Paper repository,
including patches inspired by this pull request
to improve screen refresh performance.
Feel free to contact me. This project was mainly created to scratch a personal itch, but if it can be helpful to anyone, I'd be more than happy to improve it and its documentation.
Javier Peña (@fj_pena).