Skip to content

jwillikers/pi-camera

Repository files navigation

Pi Camera

Tests pre-commit Ruff

A minimal Raspberry Pi camera that automatically syncs your photos. It is based on Jeff Geerling’s Raspberry Pi Camera project.

Pi Camera Front Hand

Overview

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.

Components

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.

Pi Camera Components

Build

The build is pretty straightforward. It requires solder and a soldering iron to wire the PCF8574 to the momentary push button.

Pi Camera PCF8574

  1. 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.

  2. 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.

  3. Attach the HyperPixel 4.0 to the Raspberry Pi. Follow the instructions from Getting Started with HyperPixel 4.0.

  4. 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.

Table 1. Stemma Qt / Qwiic Cable Colors
Function Color

Ground

Black

Clock

Yellow

Data

Blue

Power

Red

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. Install the camera module in the camera enclosure case.

  6. 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

  1. 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.

  2. Insert the microSD card into the Raspberry Pi.

  3. Boot the Raspberry Pi.

  4. Install just by following the instructions in the installation section.

  5. 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
  6. 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.

  7. Make the ~/Projects directory.

    mkdir --parents ~/Projects
  8. Clone this project’s repository to the ~/Projects directory.

    git -C ~/Projects clone https://github.com/jwillikers/pi-camera.git
  9. Update the package lists.

    sudo apt-get update
  10. Upgrade everything.

    sudo apt-get --yes full-upgrade
  11. Change to the project’s root directory.

    cd ~/Projects/pi-camera
  12. Set up the environment with just init. This will install dependencies and initialize the virtual environment.

    just init
  13. Reboot for the updated /boot/firmware/config.txt file to take effect.

    sudo systemctl reboot
  14. Use just run to run the camera.py Python script inside the virtual environment.

    just run
  15. Install and activate the systemd service with just install.

    just install

Configure Screen Orientation

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.

  1. 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)
  2. Use wlr-randr to rotate the display. When running the command from an SSH connection, include the WAYLAND_DISPLAY=wayland-1 variable as done here.

    WAYLAND_DISPLAY=wayland-1 wlr-randr --output DPI-1 --transform 90
  3. To make the change permanent, configure the rotation in the Wayfire configuration file.

    ~/.config/wayfire.ini
    [output:DPI-1]
    transform = 90

HDR

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.

  1. Show the available V4L subdevices.

    ls /dev/v4l-subdev*
    /dev/v4l-subdev0  /dev/v4l-subdev1  /dev/v4l-subdev2  /dev/v4l-subdev3
  2. 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
  3. 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

Development

  1. 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
  2. Run the tests with pytest by running just test.

    just test
  3. To update dependencies, run just update.

    just update
  4. Use just --list to list other available tasks.

    just --list

todo

  • 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.

Code of Conduct

The project’s Code of Conduct is available in the Code of Conduct file.

License

This repository is licensed under the GPLv3, available in the license file.

© 2023-2024 Jordan Williams

Authors