Raspberry Pi Zero 2 powered smart display with two modes: a Magic Mirror (Chromium kiosk via MagicMirror²) and a real-time audio spectrum analyzer & decibel meter (pygame + PyAudio). Modes are switched remotely via MQTT, with native Home Assistant integration. Designed for a 14" matte LCD to mimic an e-ink aesthetic.
- Raspberry Pi: Zero 2 WH or newer.
- Screen: 13.3" or 14" IPS Matte LCD (1920x1080) with HDMI controller board.
- Audio: INMP441 Microphone (I2S) for digital audio capture.
To connect the INMP441 I2S microphone to your Raspberry Pi, follow the wiring table below or the visual diagram:
| INMP441 Pin | Raspberry Pi Pin (Physical) | GPIO Pin | Function |
|---|---|---|---|
| VDD | Pin 1 (3.3V) | - | Power |
| GND | Pin 6 (GND) | - | Ground |
| L/R | Pin 9 (GND) | - | Channel Selec (Left) |
| SCK | Pin 12 | GPIO 18 | Serial Clock |
| WS | Pin 35 | GPIO 19 | Word Select |
| SD | Pin 38 | GPIO 20 | Serial Data |
-
Enable I2S Microphone: Update
/boot/firmware/config.txt:dtparam=i2s=on dtoverlay=googlevoicehat-soundcard
-
Enable GPU Acceleration: Ensure the KMS overlay is active in
/boot/firmware/config.txt:dtoverlay=vc4-kms-v3d gpu_mem=128
-
Configure Screen: Adapt to your needs:
# Forces HDMI and resolution 1080p 60Hz
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=82or force the kernel by adding into /boot/firmware/cmdline.txt:
video=HDMI-A-1:1920x1080M@60-
Power Management Tools: To ensure the screen shuts off immediately (avoiding the "No Signal" delay), install CEC and DDC utilities:
sudo apt update sudo apt install -y cec-utils ddcutil
(A reboot is required after applying these changes).
The Pi Zero 2 WH has limited RAM (512MB). To prevent Chromium from crashing and maintain a "snappy" UI, it is highly recommended to increase the swap size to 1.5GB using native Linux tools:
# 1. Disable a-la-carte swap scripts (if any)
sudo apt remove -y rpi-swap dphys-swapfile systemd-zram-generator
# 2. Create a permanent 1.5GB swap file
sudo swapoff -a
sudo fallocate -l 1.5G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 3. Make it permanent on boot:
# Open /etc/fstab and add this line at the bottom:
/swapfile none swap sw 0 0SmartFrame automatically detects the GPU state and will enable hardware-accelerated 2D canvas and GLES2 rendering if available.
git clone https://github.com/Perhan35/smart-frame.git
cd smart-frame
./scripts/setup_pi.shOn some systems (Raspberry Pi Zero 2) the RAM is too low for pip to install the dependencies. In that case, you should create a temporary directory:
mkdir -p ~/pip_tmp
TMPDIR=~/pip_tmp ./scripts/setup_pi.shThe setup script installs all OS-level dependencies (portaudio, SDL2, Chromium, etc.), creates a Python virtual environment (.venv/), and installs the Python packages inside it.
The setup script creates config.yaml from config.example.yaml automatically. Edit config.yaml to set your preferences (it is gitignored):
- MQTT: Set up your broker IP, port, and credentials.
- MagicMirror: Set the URL corresponding to your local MagicMirror instance.
- Audio Mode:
threshold_db_warning: Volume (in dB) where the dB text will turn yellow/orange (default: 60).threshold_db_error: Volume (in dB) where the dB text will turn red (default: 85).device_index: (Optional) Manual ALSA microphone index. If left blank, the SmartFrame will automatically discover and cache the best device (e.g. INMP441 I2S) for you.
Note: The setup script will warn you if
config.yamlstill has placeholder values and skip the service installation prompt until you configure it.
Manual startup:
source .venv/bin/activate
python3 main.pyTo install or update the service, run the install script:
./scripts/install_service.shThis generates the systemd service file from the template (scripts/smartframe.service), and installs/starts it.
SmartFrame features high-performance hardware display management, allowing it to bypass the slow "No Signal" standby delay and control the monitor's internal settings directly via DDC/CI.
- Instant Power: Uses
ddcutil/cec-clientto put the monitor into true standby instantly. - Hardware Brightness & Contrast: Direct 0-100% control of the backlighting and contrast ratio.
- Color Temperature Profiles: Switch between Warm (5000K), Natural (6500K), and Cool (9300K) via MQTT.
- Input Source Switching: Electronically switch the monitor between the Pi (HDMI-1), a secondary device (HDMI-2), or DisplayPort.
- Settings Persistence: All display settings are cached and automatically restored when the screen powers on.
Install the utilities to enable hardware-level control:
sudo apt update
sudo apt install -y cec-utils ddcutilNote: The setup script automatically handles group permissions (i2c) for these tools.
To ensure maximum responsiveness on the Pi Zero 2 WH, SmartFrame uses an advanced multi-layer caching system:
- Hardware Discovery Cache: Remembers which power command (DDC or CEC) and which HDMI port (
HDMI-1) works for your setup, skipping slow scans on boot. - Self-Configuring Audio: The orchestrator scans for the best microphone on the first run. It caches the hardware index in
.smartframe_cache, eliminating the 1-2 second delay when switching to Audio Mode. - Persistent Browser Profiles: Both Chromium and Cog use persistent data directories (
.chromium_profile/and.cog_profile/). This ensures that MagicMirror assets are cached locally. - Binary Path Caching: Remembers the exact location of tool binaries to eliminate redundant
whichshell calls.
SmartFrame natively supports Home Assistant MQTT Auto-Discovery. Once connected, it automatically creates a "Smart Frame" device with the following entities:
| Entity Name | Type | Function |
|---|---|---|
| SmartFrame Mode | select |
Switch between off, mirror, audio, etc. |
| SmartFrame Brightness | number |
Direct hardware backlight control (0-100%). |
| SmartFrame Contrast | number |
Direct hardware contrast control (0-100%). |
| SmartFrame Color Profile | select |
Switch between sRGB, Warm, Natural, and Cool. |
| SmartFrame Input | select |
Switch monitor input source (HDMI-1, HDMI-2, etc.). |
The orchestrator uses the following topics for integration with other systems (e.g., Node-RED):
smartframe/set_mode/smartframe/mode_statesmartframe/set_brightness/smartframe/brightness_statesmartframe/set_contrast/smartframe/contrast_statesmartframe/set_color_preset/smartframe/color_preset_statesmartframe/set_input_source/smartframe/input_source_statesmartframe/status(LWT:online/offline)smartframe/modes_available(JSON list of modes)



