A minimal Raspberry Pi camera that automatically syncs your photos. It is based on Jeff Geerling’s Raspberry Pi Camera project.
The Pi Camera is a minimal digital camera build which automatically uploads your photographs.
When a picture is taken and saved to the ~/Pictures
directory, its presence is automatically detected by systemd.
When an internet connection is next available, systemd uploads the photos to either S3-compatible object storage with Rclone or to Immich with the Immich CLI.
The photos are then removed from local storage.
This is all accomplished with help of my AutoUpload project.
This repository documents how I’ve made the camera, the configuration files I’ve used, and the procedure to create the camera.
The Pi Camera is based off of the Raspberry Pi 4 and the Camera Module 3. The camera uses Pimoroni’s HyperPixel 4.0 screen which has good support in the Raspberry Pi kernel and full graphics acceleration. The screen also works under Wayland. A momentary push button is used to take pictures. The HyperPixel 4.0 screen takes up all of the pins, only exposing an I2C bus. The PCF8574 I2C GPIO Expander is used to connect the momentary push button and GPS to the Raspberry Pi. An I2C GPS is used to incorporate Exif geolocation metadata in the pictures.
ℹ️
|
Although the Raspberry Pi 5 is now out, it requires active cooling and a higher power input. This makes it less suitable for a portable camera than the Raspberry Pi 4. |
-
Raspberry Pi 4 Model B (2 GB RAM or better)
-
Camera Enclosure Case for Raspberry Pi Camera Module 3/V1/V2 and Arducam 16MP/64MP Camera
-
Pimoroni HyperPixel 4.0 - Hi-Res Display for Raspberry Pi - Touch
-
STEMMA QT / Qwiic JST SH 4-pin to Premium Male Headers Cable - 150mm Long
-
A sufficiently large and performant microSD card. The 128GB Samsung Pro Ultimate and 128GB Samsung Pro Endurance are two good options.
-
A USB battery bank. I’d recommend getting a battery with at least a 5000mAh capacity with the smallest form factor possible. I use the USB Li-Ion Power Bank with 2 x 5V Outputs @ 2.1A - 5000mAh.
-
A USB-C cable for powering the Pi.
-
A case. I found that LEGO Technics make a pretty sturdy case. A minimal $13 LEGO Technics set was sufficient for making the enclosure for the camera. I bought a second to make the case even better and add an enclosure for the battery. I’ve been avoiding dealing with CAD files, but it should be possible to make some modifications to the CAD files from Jeff Geerling’s Raspberry Pi Camera to account for the HyperPixel 4.0 screen.
The build is pretty straightforward. It requires solder and a soldering iron to wire the PCF8574 to the momentary push button.
-
Trim the length of the wires on the momentary push button. They can be trimmed pretty short, but keep enough room to make up for any mistakes. I only kept a couple of centimeters on each wire.
-
Solder the leads of the momentary push button to the PCF8574 I2C GPIO Expander breakout. Solder the black lead to ground and the red lead to
P0
. -
Attach the HyperPixel 4.0 to the Raspberry Pi. Follow the instructions from Getting Started with HyperPixel 4.0.
-
Plug the male header pins on the STEMMA QT / Qwiic JST SH 4-pin to Premium Male Headers Cable to the HyperPixel 4.0. With the screen face up, and the pins and micro HDMI ports facing towards you, the pins are ordered ground, clock, data, and power from left to right. The associated cable colors are documented in the following table.
Function | Color |
---|---|
Ground |
Black |
Clock |
Yellow |
Data |
Blue |
Power |
Red |
-
Attach the JST SH plug on STEMMA QT / Qwiic cable with male headers to the PCF8574 breakout. It can be connected to either end of the board.
-
Attach one of the JST SH plugs on the other STEMMA QT / Qwiic cable to the Adafruit Mini GPS PA1010D breakout. It can be connected to either end of the board.
-
Connect the flex cable to the 2-lane MIPI CSI camera port on the Raspberry Pi. This port is next to the audio jack on the Raspberry Pi 4 Model B. The side with the silver lines should face towards the micro HDMI ports. The blue side should face towards the USB ports. This process is documented by Raspberry Pi in the Connecting the Camera section of the Camera page.
🔥Be gentle with the camera port, as they are fairly breakable.
-
Connect the other end of the flex cable to the Raspberry Pi Camera Module 3. The silver lines should be facing up, towards the camera’s lens.
-
Install the camera module in the camera enclosure case.
-
Fit the case. I’m not going to detail my ad-hoc case build, though hopefully the pictures provide some guidance. However, be aware that the camera module should be positioned upright. This is confusing because upright actually looks sideways with how the text is printed on the camera module. This is important because the picamera2 library only allows flipping the image 180° at this time. Other software techniques are necessary to flip the camera image 90° or 270°. Issues #492, #774, and #792 in the picamera2 Project request this functionality.
-
Install the 64-bit full version of Raspberry Pi OS to a microSD card. The configuration files assume the primary user is
pi-camera
, which can be configured when using Raspberry Pi Imager to write the image. This project has been tested with Raspberry Pi OS 5 based on Debian Bookworm. -
Insert the microSD card into the Raspberry Pi.
-
Boot the Raspberry Pi.
-
Install just by following the instructions in the installation section.
-
Follow the instructions to configure the storage service and install the autoupload systemd units in the AutoUpload README to automatically upload photos in the
~/Pictures
directory. The commands to enable the units should look similar to the following. These use the system units, though user units work just as well.- Immich
-
sudo systemctl enable --now autoupload-immich@$(systemd-escape --path ~/Pictures).path
- Rclone
-
sudo systemctl enable --now autoupload-rclone@$(systemd-escape --path ~/Pictures).path
-
For security, be sure to disable password-based SSH authentication. After your public key has been added to the
~/.ssh/authorized_keys
file on the Pi Camera, this can be configured in the/etc/ssh/sshd_config
file. You can follow the instructions in my OpenSSH Config repository to accomplish this and a few other optimizations. -
Make the
~/Projects
directory.mkdir --parents ~/Projects
-
Clone this project’s repository to the
~/Projects
directory.git -C ~/Projects clone https://github.com/jwillikers/pi-camera.git
-
Update the package lists.
sudo apt-get update
-
Upgrade everything.
sudo apt-get --yes full-upgrade
-
Change to the project’s root directory.
cd ~/Projects/pi-camera
-
Set up the environment with
just init
. This will install dependencies and initialize the virtual environment.just init
-
Reboot for the updated
/boot/firmware/config.txt
file to take effect.sudo systemctl reboot
-
Use
just run
to run thecamera.py
Python script inside the virtual environment.just run
-
Install and activate the systemd service with
just install
.just install
One of the things that may need tweaked is the screen orientation.
This is technically configured in two places, the /boot/firmware/config.txt
file, where it can be changed using the rotate
dtparam
, and additionally in Wayfire.
The configuration for Wayfire is documented in the Setting the desktop environment resolution and rotation section of the Raspberry Pi Configuration documentation.
It is also described in the Configuration.md file in the Wayfire repository.
The instructions here describe the basics necessary to rotate the screen.
-
Determine the available display outputs with the
kmsprint
command. Here,DPI-1
corresponds to the HyperPixel 4.0.kmsprint | grep Connector Connector 0 (32) HDMI-A-1 (disconnected) Connector 1 (42) HDMI-A-2 (disconnected) Connector 2 (48) DPI-1 (connected)
-
Use
wlr-randr
to rotate the display. When running the command from an SSH connection, include theWAYLAND_DISPLAY=wayland-1
variable as done here.WAYLAND_DISPLAY=wayland-1 wlr-randr --output DPI-1 --transform 90
-
To make the change permanent, configure the rotation in the Wayfire configuration file.
~/.config/wayfire.ini[output:DPI-1] transform = 90
The Raspberry Pi Camera Module 3 supports HDR, but only at a lower resolution.
HDR support has to toggled when camera.py
isn’t running.
-
Show the available V4L subdevices.
ls /dev/v4l-subdev* /dev/v4l-subdev0 /dev/v4l-subdev1 /dev/v4l-subdev2 /dev/v4l-subdev3
-
To enable HDR support for the Raspberry Pi Camera Module 3, use the following command on one of the V4L subdevices. In my case, this ended up being
/dev/v4l-subdev2
.just hdr /dev/v4l-subdev2
-
To disable HDR support for the Raspberry Pi Camera Module 3, use this command with the corresponding V4L subdevice.
just hdr /dev/v4l-subdev2 disable
-
Run
just init-dev
to initialize the virtual environment for development. This will install all of the necessary dependencies and the {pre-commit} hooks.just init-dev
-
Run the tests with pytest by running
just test
.just test
-
To update dependencies, run
just update
.just update
-
Use
just --list
to list other available tasks.just --list
-
mypy
-
Make the camera application more robust. It crashes really easily.
-
Incorporate some sort of power button to safely shutdown.
-
Add a NixOS configuration and build SD card images.
The project’s Code of Conduct is available in the Code of Conduct file.
This repository is licensed under the GPLv3, available in the license file.
© 2023-2024 Jordan Williams