### The Problem

Smart speakers and streaming devices have a fundamental flaw: they assume you can see. Voice assistants help, but they need a cloud connection, they listen all the time, and they get frustrating when they mishear you. For blind and visually impaired users, the alternatives are either expensive specialized hardware or being locked into Amazon, Google, or Apple ecosystems.

### The Solution

Feel the Knobs is a self-contained media center that needs no screen and no internet account. Two large 11-position rotary switches — one for program selection (radio, YouTube, audiobooks), one for station or channel — give you tactile, muscle-memory-friendly control. A potentiometer handles volume. Text-to-speech confirms every selection. That's it. No app, no touchscreen, no cloud.

It lives in a laser-cut 6mm MDF enclosure and drives two 75W full-range speakers through a HiFiBerry AMP2. The whole thing runs off a single 20V power brick.

### How It Works

Two Arduino Nanos act as I2C slaves, each reading one rotary switch via analog voltage dividers. The Raspberry Pi 4 polls their positions over I2C every 200ms and launches the right player — mpd for radio, yt-dlp for YouTube, VLC for audiobooks. A GPIO pin switches audio output between the speakers and Bluetooth headphones.

A companion VPS backend (also open source) provides a web interface for managing radio stations, YouTube channels, and uploading audiobooks. The Pi syncs every 10 minutes via cron. No static IP, no port forwarding needed.

### Why This Matters

This is not an accessibility feature bolted onto a general-purpose device. It was designed from the ground up around haptic interaction and acoustic feedback. The entire interface is physical — you operate it by feel alone, without touching a screen or talking to a voice assistant.

### Hardware Architecture

┌───────────────────────────────────────────────┐
│              MDF Enclosure (3mm)              │
│                                               │
│ ┌──────────┐       ┌──────────┐ ┌─────────┐   │
│ │ Rotary   │       │ Rotary   │ │ Volume  │   │
│ │ Switch 1 │       │ Switch 2 │ │ Pot     │   │
│ │ (Program)│       │ (Station)│ │         │   │
│ └────┬─────┘       └────┬─────┘ └────┬────┘   │
│      │                  │            │        │
│ ┌────┴───────────┐  ┌───┴────────────┴─────┐  │
│ │ Arduino Nano 1 │  │   Arduino Nano 2     │  │
│ │    (0x08)      │  │      (0x09)          │  │
│ │ Reads Switch 1 │  │ Reads Switch 2 + Pot │  │
│ └────────┬───────┘  └───────────┬──────────┘  │
│          │                      │             │
│ ┌────────┴────────┐  ┌─────────┴───────────┐  │
│ │ Level Shifter 1 │  │  Level Shifter 2    │  │
│ │  (3.3V <-> 5V)  │  │   (3.3V <-> 5V)     │  │
│ └────────┬────────┘  └────────┬────────────┘  │
│          │                    │               │
│          └──────────┬─────────┘              │
│                     │ I2C bus                 │
│ ┌───────────────────┴───────────────────────┐ │
│ │         Raspberry Pi 4 (4GB)              │ │
│ │    Boots from SSD (USB-SATA adapter)      │ │
│ │    GPIO4 -> audio output switch           │ │
│ └───────────────────┬───────────────────────┘ │
│                     │ I2S                     │
│ ┌───────────────────┴───────────────────────┐ │
│ │     HiFiBerry AMP2 (2x60W Class-D)        │ │
│ └───────────────────┬───────────────────────┘ │
│                     │                         │
│        ┌────────────┴────────────┐            │
│        │  2x Lonpoo 75W Speakers │            │
│        └─────────────────────────┘            │
└───────────────────────────────────────────────┘
``` 

### Software Stack

| Layer | Technology |
|---|---|
| Audio backend | PipeWire + PulseAudio |
| Radio playback | mpd + mpc |
| YouTube playback | yt-dlp then VLC |
| Audiobook playback | VLC + TTS (position tracking) |
| Bluetooth audio | PipeWire bluez5, custom bt-agent systemd service |
| I2C communication | Python smbus, polling at 200ms |
| GPIO switching | RPi.GPIO (GPIO4 toggles AMP2/headphones) |
| Remote management | FileBrowser web UI + PHP admin panel on VPS |
| Sync | Cron every 10 min, pulls from VPS via REST API |
| Remote access | Tailscale VPN (primary) + reverse SSH tunnel (fallback) |

### Three Audio Paths

The system supports three audio outputs, switched via GPIO4:

1. **AMP2** — HiFiBerry amplifier driving the stereo speakers. Default for room listening.
2. **Bluetooth Headphones** — PipeWire A2DP sink. A custom package handles connection, sink detection, and audio routing.
3. **Wired Headphones** — 3.5mm jack, fallback when no Bluetooth device is paired.

Each path has its own Python package with identical structure.

### I2C Without Interrupts

The Arduinos communicate over I2C, but instead of GPIO interrupts (which caused conflicts), the Python readers poll at 200ms intervals. A threading.Event signals when a new position is available. Simple, reliable, and zero GPIO conflicts with the audio switch.

### Remote Infrastructure

The Pi has no static IP and sits behind whatever WiFi it connects to. Two solutions:

- **Tailscale Mesh VPN** (primary) — SSH from anywhere without port forwarding
- **Reverse SSH tunnel** (fallback) — systemd service on port 2222 to a VPS

The companion VPS runs:

- Nginx reverse proxy with Let's Encrypt
- FileBrowser for web-based file management
- PHP admin panel for editing radio stations, YouTube channels, WiFi settings
- Demo mode at media.b481.de/demo/ (login: demo / demo2026)

### Bluetooth Remote Control

A custom bt-agent systemd service polls the VPS every 60 seconds for commands. Supports scan, connect, disconnect, pair, list_paired. You can manage Bluetooth devices from the web interface without ever touching the Pi.

### Links

    Application: https://github.com/mcgutschy/media_center_final

    Backend: https://github.com/mcgutschy/media_center_backend

    Project Website: https://b481.de/media-center/

    Live Demo Media Center BackEnd:

https://media.b481.de/demo/ (login: demo / demo2026)