reFrame builds a one-photo-at-a-time camera on a Raspberry Pi Zero and ePaper
reFrame is an experimental camera with a color ePaper display. Designed to capture and display one photo at a time, making every frame deliberate and memorable.
At a glance
- What is it?
- reFrame is an open source digital camera built from off-the-shelf parts, with a 6-color ePaper screen that takes roughly 20 seconds to refresh and keeps the last photo on screen after power off. It suits makers who want to build hardware and accept the slowness, not anyone who needs a camera that shoots quickly.
- Who is it for?
- reFrame is the right choice for a maker who wants to solder together a deliberately slow camera and then port it to other e-ink panels, and the wrong choice for anyone expecting a usable everyday camera, since the display needs about 20 seconds per refresh and the only way to clear the screen is to take another photo.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 26 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A camera where the slow refresh is the point
reFrame is an experimental digital camera that captures and displays a single photo at a time. The hardware is a Raspberry Pi Zero 2 W with a Camera Module 3 feeding a 4-inch Waveshare ePaper Spectra 6 screen, a six-colour panel. The capture pipeline dithers the original image down to that palette before pushing it to the display.
The refresh is slow. The screen takes about 20 seconds to show a photo, and the project documentation describes the effect as electrical charges physically moving ink particles into place while colours cycle. Once the image settles, it stays there. Powering the camera off does not clear the panel, and the only documented way to remove a photo is to take a new one, which replaces it.
That constraint is the design, not a defect. A camera that only shows one image at a time, in a display that keeps its content with no power, doubles as a desk photo frame between uses. The audience is people who want to build the hardware themselves and do not mind that the shutter experience takes a fifth of a minute.
The bill of materials is deliberately ordinary
The open source version of reFrame is built to avoid bespoke parts, so that anyone can assemble their own unit. The computer is a Raspberry Pi Zero 2 W, the camera is a Raspberry Pi Camera Module 3, and the display is a Waveshare 4-inch ePaper Spectra 6. Power comes from a PiSugar 3 battery, and the enclosure is 3D printed in PLA.
Every one of those is a standard purchase, which is the point of the exercise. The enclosure files are included in the repository under hardware/, so the case can be printed rather than machined. The build guide is linked from the project page as the reference for assembly, and a separate hardware porting document covers adapting the code to other e-ink displays, cameras or buttons.
Two different licences apply to the two halves of the project. Software in the repository is under the Apache License 2.0 unless a file says otherwise. Hardware design files under hardware/ are under CC BY 4.0. The documentation is offered for reuse with attribution where it is original to the project, and photos may include third-party products, packaging, logos or trademarks that the project does not license. The name, logo, domain and branding are reserved.
Installing on a flashed Raspberry Pi OS
Once the hardware is assembled and Raspberry Pi OS has been flashed to the card, the setup is a short shell sequence. The install script pulls the Python dependencies and registers the services described later:
sudo apt update
sudo apt install -y git
git clone https://github.com/kaloyaan/reframe.git
cd reframe
chmod +x install.sh
./install.shThe script name is install.sh and it lives at the top level of the repository, which is why the clone step matters before it can be run. The permission change on the script is not cosmetic on a fresh clone.
The Python side is small. The dependency file lists pillow and numpy for the image work, smbus2 for the I2C bus, fastapi and uvicorn for the web dashboard, aiofiles and httpx for asynchronous file and HTTP handling, and a pinned qrcode==7.4.2. The pin on qrcode is the only exact version constraint in the list, so it is the dependency most likely to conflict with something already on the card.
The project documentation points to a separate software setup page for configuration beyond this script, and a default configuration file is provided as settings.example.json.
One button, one photo, twenty seconds of waiting
The physical interaction is minimal by design. There is a single button, and no viewfinder, no flash and no zoom. The combined power and shutter button wakes the camera and takes a photo.
The sequence the documentation describes runs like this. The original image is saved, then dithered to a six-colour palette chosen to match the screen, and the processed image is sent to the ePaper panel. The screen then needs about 20 seconds before the photo appears. Pressing the button again takes another photo and replaces the previous one on the display. Turning the camera off leaves the last photo visible on the panel.
Two consequences follow from that design and they are worth stating plainly. First, the camera is single-shot in practice: there is no burst, no preview and no way to check a frame before committing to it. Second, because the panel retains its image, the device cannot be reused for a different purpose without taking a photograph, which for a desk object is a limitation and for a piece of artwork is the behaviour you want.
A local dashboard, a port 80 proxy, and five systemd units
The repository is a small set of Python programs with a service layer around them. reframe.py is the main camera application. dashboard.py is the web dashboard for photo management, and dashboard_proxy.py is a local port 80 dashboard proxy. Configuration defaults live in settings.example.json. The waveshare_epd directory holds the e-ink display drivers, and the scripts directory holds hardware and privileged system helpers, including enable_hdr.sh, reframe-apply-update and reframe-rtc-sync.
The service definitions live under systemd/: reframe.service, reframe-dashboard.service, reframe-dashboard-proxy.service, reframe-rtc-restore.service and reframe-rtc-update.service. The camera, the dashboard, the proxy and the real-time-clock handling are separate units, which is what lets the dashboard and the clock work even when the camera itself is idle.
The dashboard is reachable over the local network and lets you browse photos, download the originals, change which image is displayed, adjust camera settings, and optionally upload dithered photos to Are.na. That Are.na upload is an extension described separately in the dashboard extensions document, so the core gallery works without it. The real-time-clock scripts and services exist because a Pi Zero without a battery-backed clock loses time, and a camera that stamps photos needs a correct timestamp.
Reaching the dashboard two ways, and one hard limit on the display
There are two approaches to getting at the dashboard, and the difference is practical rather than cosmetic. The first is to reach the dashboard application directly over the local network from a browser on the same network. The second is to use the separate dashboard_proxy.py service, which sits on local port 80 as a proxy in front of it. A dedicated unit exists for the proxy, so it is a supported configuration rather than a workaround.
The hard limit applies to the panel. Six colours and a dithering pass mean photographs lose most of their tonal range before they ever reach the screen, so the output is not a preview of the capture but a stylised version of it. The originals are preserved and downloadable from the dashboard, which is the practical answer for anyone who cares about the unprocessed file. The screen version is the deliberate object.
For anyone tempted to treat reFrame as a general-purpose camera, the twenty-second refresh rules it out. Nothing in the project documentation describes a way to shorten the panel update or to display a live preview, so the constraints are inherent to the six-colour ePaper approach rather than a missing feature in the software.
No tagged releases, and a porting path for other panels
The project publishes no GitHub releases, so there is no versioned binary to pin and no changelog to read before upgrading. The last push to the main branch was on 2026-09-26, and the upgrade path is simply to pull the branch and re-run the setup script, which is what the reframe-apply-update helper in the scripts directory exists to support.
Because there are no tags, the upgrade cost sits entirely in the dependencies. Eight Python packages are required, and one of them, qrcode, is pinned to an exact version. The rest float, so a fresh install months from now can pull different releases of pillow, numpy, fastapi or uvicorn than the ones the author tested against. Anyone deploying this into a long-lived setup would want to capture the resolved environment after the first successful install.
The software is Apache 2.0, which permits commercial use and modification with attribution and patent grant, while the enclosure files are CC BY 4.0 and the branding is reserved. The upstream project began as a thesis prototype at Yale under the name eink.cam, and the project page is reframe.camera, where the build guide, software setup, hardware porting notes and dashboard extension notes are published.
Editorial conclusion
reFrame is the right choice for a maker who wants to solder together a deliberately slow camera and then port it to other e-ink panels, and the wrong choice for anyone expecting a usable everyday camera, since the display needs about 20 seconds per refresh and the only way to clear the screen is to take another photo. Before starting, read docs/build-guide.md for the full bill of materials and confirm your Pi Zero 2 W can run the FastAPI and uvicorn dashboard, then install with ./install.sh on Raspberry Pi OS.
Frequently asked questions
What hardware does reFrame need?
The open source version uses a Raspberry Pi Zero 2 W, a Raspberry Pi Camera Module 3, a Waveshare 4-inch ePaper Spectra 6 display, a PiSugar 3 battery and a 3D printed PLA enclosure. The full bill of materials is in the build guide.
How long does reFrame take to show a photo?
The ePaper display takes about 20 seconds to refresh after the shutter is pressed, while colours cycle as the ink particles move into place. The photo then stays on screen, and powering the camera off does not clear it.
How do I install the reFrame software on the Raspberry Pi?
With Raspberry Pi OS already flashed, clone the repository, make install.sh executable and run it. The script installs the Python dependencies, which include pillow, numpy, smbus2, fastapi, uvicorn, aiofiles, httpx and qrcode==7.4.2.
Can I use reFrame with a different e-ink display or camera?
Yes. The project publishes hardware porting notes for adapting the code to other e-ink displays, cameras or buttons, and the e-ink display drivers are kept in a separate waveshare_epd directory.
Can I get the photos off the reFrame camera?
Yes. A web dashboard reachable over the local network lets you browse photos, download the originals, change the displayed image and adjust camera settings, and the dashboard extensions document covers uploading dithered photos to Are.na.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kaloyaan-reframe)Was this useful?