This project was created in haste in under two weeks. I didn’t even have time to put the project on GitHub before.
The project itself exists because of two things:
- The supervisor of my student research group asked me to build something cool for the student research groups seminar, and I think kitbashing an ebook reader in just two weeks definitely counts as “something cool.”
- I bought my first ever e-ink device and I love E-Ink technology, but the reader I bought was garbage, so I decided I could make a better one. Currently, it’s not perfect, but at least it’s something I can improve.
- Compact size – The smallest Raspberry Pi capable of running a full-fledged OS (half the size of the Raspberry Pi 4)
- All-in-one – GPIO header, WiFi, Bluetooth, HDMI, Micro USB ports, full-featured Linux
- Price – 80 PLN for a microcomputer that can run a complete operating system (3–4 times cheaper than Raspberry Pi 4)
- Support – Access to Debian packages and official Raspberry drivers/libraries
- Size: 7.5 inches
- Resolution: 800×480 px
- Interface: SPI
- Power supply: 3.3V / 5V
- Type: Passive reflective (no backlight)
- Refresh time: Full refresh – 5s, partial refresh – 0.3s
- Simultaneous charging and powering (5V output)
- I2C monitoring of voltage, current, power, and battery status
- Battery protection against overcharge, deep discharge, overload, and short circuit
- Easy connection using pogo spring pins, compatible with other HATs
I created a simple case (in OpenSCAD) to limit battery movement:

Add settings for automatic connection to WiFi

The address where the Raspberry Pi appears after booting
should be visible in your router's control panel.
But if that's not possible, or you'd like to do it differently,
you can use the Nmap scanner for this task.
Use the following command:
ip aYou should see something like this:
inet 192.168.1.101/24 brd 192.168.1.255 scope global dynamic noprefixroute enp7s0Here, 192.168.1.101 is your own IP address.
We’ll scan all hosts in the 192.168.1.0/24 subnet.
-p 22— scan port 22 (SSH)-sV— detect service versions (sometimes includes hostname in banner)
nmap -p 22 -sV 192.168.1.101/24Look for a device that identifies itself as Raspbian:
Nmap scan report for 192.168.1.102
Host is up (0.045s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Raspbian 2+deb12u5 (protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Login to the Raspberry Pi over SSH:
ssh user@192.168.1.102Update package list:
sudo apt updateInstall required packages:
sudo apt install neovim python3-pip python3-pil python3-numpy python3-gpiozero git xvfb x11-utils \
imagemagick x11-apps xserver-xephyr xserver-xorg-video-dummy xserver-xorg-input-libinput i3 zathura -yRemove unnecessary packages:
sudo apt remove nano -yTo change Raspberry Pi settings, use the dedicated menuconfig tool provided by Raspberry Pi:
sudo raspi-configReboot the system:
sudo rebootWait a moment and log in again:
ssh user@192.168.1.102Check if SPI is working:
ls /dev/spidev0.*If you see something like this, SPI is enabled:
/dev/spidev0.0 /dev/spidev0.1Clone the library:
git clone https://github.com/waveshare/e-PaperNavigate to the examples directory:
cd e-Paper/RaspberryPi_JetsonNano/python/examplesWe have the 7.5 V2 display, so grant execution permissions to the appropriate script:
chmod +x epd_7in5_V2_test.pyRun the example:
sudo ./epd_7in5_V2_test.pyThe screen should flicker a few times and display some test images.
- Xorg
This is a popular display server for Linux responsible for the graphical environment (window display, mouse and keyboard handling).
In our project, we runXorgwith a dummy configuration — a "virtual" screen without a physical monitor. - i3
This is a tiling window manager (divides the screen into tiles), lightweight and configurable.
We use it to manage windows in the Xorg session, allowing us to run applications likezathura. - Zathura
A minimalist PDF viewer that works well with i3.
In our script, it is used to open a PDF file on the virtual screen, which is then visible on the e-paper display.
- Dummy driver is a virtual display driver for Xorg.
- It allows running the X server without a physical monitor connected to the Raspberry Pi.
- Enables rendering graphics in memory and access to the display (DISPLAY=:0).
- Useful in headless systems, e.g., for e-paper handling where no physical screen is needed.
Create the configuration directory and file:
sudo mkdir -p /etc/X11/xorg.conf.d
sudo nvim /etc/X11/xorg.conf.d/10-dummy.confAnd add the following configuration: 10-dummy.conf
Create a new file, and paste this content: renderer.py
nvim /home/user/e-Paper/RaspberryPi_JetsonNano/python/examples/renderer.py- Starts a virtual display server (
Xorg) and a window manager (i3) if they are not running. - Opens a PDF viewer (
zathura) to display a document. - Periodically captures a screenshot of the virtual desktop.
- Compares it to the previous image using histogram difference.
- Updates the e-paper display only if the screen has changed.
- Minimizes unnecessary e-paper updates to reduce annoying flickering
Let's quickly go back to your computer and transfer the book:
scp advanced_bash_shell_guide.pdf user@192.168.1.102:~/book.pdfCheck if our code runs on the Raspberry Pi:
cd /home/user/e-Paper/RaspberryPi_JetsonNano/python/examples
sudo ./renderer.pyThe book located at /home/user/book.pdf should appear on the display.
We have a working e-ink book renderer. Ideally, it should start automatically when the system boots.
- systemd is a modern init system and service manager for Linux systems.
- It is responsible for starting, stopping, and monitoring system services (daemons).
- A systemd daemon runs continuously in the background, managing processes and system resources.
- It allows defining services via unit files that control their behavior.
- Provides fast system startup and automatic service restarts in case of failures.
Create a new file:
sudo nvim /etc/systemd/system/renderer.serviceand add following content renderer.service
After saving the service file:
sudo systemctl daemon-reexec
sudo systemctl enable renderer.service
sudo systemctl start renderer.serviceChecking the status:
sudo systemctl status renderer.serviceChecking Logs:
journalctl -u renderer.serviceDescription– service description shown during service management.After– defines startup order; this service starts after:multi-user.target(multi-user mode),network-online.target(network is online),ssh.service(SSH server is running).
Wants– indicates a desire to startnetwork-online.targetbut it's not critical.
Type=simple– service runs as a single process (default).ExecStart– command to start the service, here our Python script.Restart=always– automatically restart the service if it stops.RestartSec=10– wait 10 seconds before restarting.Environment– sets environment variables:DISPLAY=:0– points to X server display.HOME=/root– home directory (important for permissions).XDG_RUNTIME_DIR=/run/user/0– runtime directory for root user.
WantedBy=multi-user.target– specifies the service should start automatically in multi-user mode (standard system runlevel).- Allows the service to start on boot after running
systemctl enable renderer.service.










