An open API service indexing awesome lists of open source software.

https://github.com/mfenniak/pixelperfectpi

pixelperfectpi is an application for the Raspberry Pi that drives an LED matrix panel in order to create a custom digital clock
https://github.com/mfenniak/pixelperfectpi

digital-clock icalendar led-matrix purpleair raspberry-pi

Last synced: 5 months ago
JSON representation

pixelperfectpi is an application for the Raspberry Pi that drives an LED matrix panel in order to create a custom digital clock

Awesome Lists containing this project

README

          

> [!IMPORTANT]
> This repository is archived. The active project has been moved to [https://forgejo.kainnef.com/mfenniak/pixelperfectpi](https://forgejo.kainnef.com/mfenniak/pixelperfectpi)

# pixelperfectpi

pixelperfectpi is an application for the Raspberry Pi that drives an LED matrix panel in order to create a custom digital clock.

This app isn't really intended to be re-used -- it isn't very configurable. It was just built for my own use, and the code is shared so that anyone else who tries to do the same thing has some starting point, or hints and shortcuts.

Features:
- Displays the time.
- Reads and displays AQI and temperature from a local PurpleAir sensor.
- Displays the next weather forecast sourced from Environment Canada.
- Displays the next three calendar events from an iCal feed.

Example installation:

https://github.com/mfenniak/pixelperfectpi/assets/91093/f42331e7-f9d0-4a45-8c1d-4392a088cb44

# Running

## Dependencies

Using a nix devshell (`nix develop`) or direnv (`direnv allow`) will install all the required dependencies to run pixelperfectpi either emulated on a desktop, or on a raspberry pi.

## Config

For development, you can copy `config_template.py` to `config.py` and fill in the config values to get an easy-to-reproduce testing environment, either on a desktop or a Pi.

Performing all configuration through cmdline options is the approach I've taken for a permanent install. See the NixOS configuration below for an example.

## Emulation

If you run pixelperfectpi on any device that isn't detected as a Raspberry Pi (via `/proc/cpuinfo`), it will use https://github.com/ty-porter/RGBMatrixEmulator to run an emulator that can be loaded in a web browser, pygame, a console, etc. This is a handy way to do development. The `emulator_config.json` generated by RGBMatrixEmulator can be tweaked to run in different modes; see RGBMatrixEmulator's README for more information.

## LED Matrix

In order to get the Raspberry Pi -> LED Matrix wired up and working, follow the instructions at https://github.com/hzeller/rpi-rgb-led-matrix.

## NixOS Configuration

Although this is a typicalish Python application, I've deployed it on my Raspberry Pi through NixOS. After installing NixOS (https://nix.dev/tutorials/nixos/installing-nixos-on-a-raspberry-pi), the following flake configuration can be used to set up this app and have it autostart on boot, and set up the Raspberry Pi hardware correctly:

### flake.nix
```
{
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
pixelperfectpi.url = "github:mfenniak/pixelperfectpi";
nixos-hardware.url = "github:NixOS/nixos-hardware";
};

outputs = { self, nixpkgs, nixos-hardware, pixelperfectpi, ... }: {
nixosConfigurations.nixclock = nixpkgs.lib.nixosSystem rec {
system = "aarch64-linux";
modules = [
./nixclock.nix
nixos-hardware.nixosModules.raspberry-pi-4
{ nixpkgs.overlays = [ pixelperfectpi.overlays.${system}.default ]; }
];
};
};
}
```

### nixclock.nix

```
{ config, pkgs, lib, ... }:

{
boot = {
kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" ];
loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};

kernelParams = [
# per https://github.com/hzeller/rpi-rgb-led-matrix#cpu-use...
"isolcpus=3"
# https://github.com/NixOS/nixpkgs/issues/122993
"iomem=relaxed"
"strict-devmem=0"
];

blacklistedKernelModules = [
# disable snd module: https://github.com/hzeller/rpi-rgb-led-matrix#use-minimal-raspbian-distribution
"snd_bcm2835"
];
};

fileSystems = {
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
};

networking = {
hostName = "nixclock";
wireless = {
enable = true;
networks."...yourSID...".psk = "...yourPSK..."; # FIXME: there's probably a better way than hardcoding a pwd here
interfaces = [ "wlan0" ];
};
};

environment.systemPackages = with pkgs; [ vim ];

services.openssh.enable = true;

time.timeZone = "America/Edmonton";

# nix settings
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.trusted-users = [ "root" ];
nix.settings.auto-optimise-store = true;
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};

systemd.services.pixelperfectpi = {
description = "pixelperfectpi";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "always";
# NOTE: any % in the iCal URL needs to be escaped as %% due to systemd's usage of it as a special char;
# Google Calendar's private shared URLs have % embedded in them
ExecStart = ''
${pkgs.pixelperfectpi}/bin/pixelperfectpi.py \
--led-rows=32 \
--led-cols=64 \
--led-gpio-mapping=regular \
--led-slowdown-gpio=4 \
--font-path ${pkgs.pixelperfectpi}/fonts \
--ical-url="...your-ical-url..."
'';
};
};

hardware.enableRedistributableFirmware = true;
system.stateVersion = "23.11";
}
```