openhome

openhome mini — DIY Local "Alexa" Build Guide

A privacy-first smart speaker on a Raspberry Pi 4 that matches an Amazon Echo's core

experience — far-field "Alexa" wake word, natural voice replies, smart-home control,

timers, music, and a light ring — but runs locally and answers only to you.

Status: design v1 (2026-07-30). Researched against current parts + software.
Companion files: hardware/enclosure/openhome-mini.scad (printable shell),
hardware/mockups/06-photoreal.jpg (retail concept), 07-mvp-prototype.jpg (build).

1. Goal & requirements (what "match a real Alexa" means)

Echo capabilityopenhome mini equivalentMet by
"Alexa" wake word, hears across a room4-mic far-field array + openWakeWord alexaXVF3800 + OWW
Understands speechLocal STT (Whisper)faster-whisper
Talks back naturallyLocal TTSPiper
Controls smart homeHome Assistant AssistHA
Timers / alarms / weatherAssist intentsHA
Plays musicMusic Assistant → speakerHA + MA
Light-ring feedback16-LED addressable ringWS2812
Private / offlinenothing leaves the LAN(Alexa can't do this)
Open-question "brain" (optional)LLM conversation agentGemini/OpenAI/local

Hard requirements


2. System architecture

                       ┌─────────────────────────── openhome mini (one Pi 4) ───────────────────────────┐
  voice ──▶ [XVF3800 4-mic array] ──USB(16k mono, AEC/beamformed)──▶ ┐
                                                                     │
                                              ┌── openWakeWord ("alexa")   ── wake ──┐
                                              │                                       ▼
                       [ Home Assistant + Assist pipeline ] ── STT (faster-whisper) ─▶ intent ─▶ TTS (Piper)
                                              │                                       │
   speaker ◀─ [3" driver] ◀─ [MAX98357A I2S] ◀── audio out ◀───────────────────────┘
                                              │
   ring   ◀─ [WS2812 ×16] ◀── SPI (GPIO10) ◀──┘   (state: idle/listen/think/speak/mute)
                       └───────────────────────────────────────────────────────────────────────────────┘

Two deployment shapes:

Simplest; ~2–4 s latency with whisper-base. This is "one box I can build."

LEDs (via linux-voice-assistant); a separate HA box does STT/TTS/intent. Sub-second,

scales to many rooms. Same hardware, just moves the heavy compute off-device.


3. Bill of materials (with links)

#PartWhyPriceLink
1Raspberry Pi 4 Model B (4 GB)compute / runs everything~$55buy
2SanDisk Extreme 32 GB microSD (A2)OS + models~$10buy
3ReSpeaker XVF3800 USB 4-Mic Arrayfar-field, HW AEC/beamforming/DoA, USB or I2S$60.99buy
4Adafruit MAX98357A I2S ampdigital audio out, 3 W$5.95buy
53" 4 Ω 3 W speakerroom-filling driver$1.95buy
6NeoPixel Ring — 16 × WS2812light-ring feedback~$9buy
7Official USB-C PSU 5.1 V / 3 Apower (see §7 audit)~$8buy
8Heatsink + 30 mm fanWhisper heats the Pi~$6buy
9M2.5 heat-set inserts + screwsserviceable base~$8buy
10Dupont/JST jumper wireswiring~$7buy
113D-printed shell (PETG, ~150 g)enclosure (openhome-mini.scad)~$3in this repo

Total ≈ $175 @ qty 1 (~$150 at a batch of 10). Compare: Echo (4th gen) ~$100 but cloud-bound

and no local control; openhome mini adds privacy + a scriptable brain.

Budget swaps


4. Wiring

4a. MVP wiring (simple)

XVF3800 ── USB ─────────────▶ Pi 4 USB port         (mic in, processed)
MAX98357A  Vin → Pi 5V,  GND → Pi GND
           DIN → GPIO21,  BCLK → GPIO18,  LRCLK → GPIO19
Speaker  → MAX98357A screw terminals (4 Ω)
WS2812   DIN → GPIO10 (SPI MOSI) via 330 Ω,  5V → Pi 5V,  GND → Pi GND
Fan      → GPIO 5V / GND  (or a fan header)
Power    → USB-C 5.1V/3A

4b. AEC-correct wiring (matches Alexa "barge-in", recommended)

Route playback through the XVF3800 so its DSP has the echo reference:

Pi 4 ── USB ──▶ XVF3800  (USB soundcard: mic IN + speaker-reference OUT)
XVF3800 I2S OUT ──▶ MAX98357A ──▶ speaker

Now the array cancels your own music, so "Alexa, stop" works at volume. Zero extra parts —

just use the XVF3800's I2S output instead of the Pi's. (See §7 for why this matters.)


5. Software — step by step (self-contained build)

  1. Flash OS. Raspberry Pi Imager → Raspberry Pi OS (64-bit, Lite). Set hostname

openhome, enable SSH + Wi-Fi. Must be 64-bit (wake word/VAD won't run on 32-bit).

  1. Enable the I2S DAC. In /boot/firmware/config.txt:

```

dtparam=audio=off

dtoverlay=max98357a # or hifiberry-dac

dtparam=spi=on # for WS2812 over SPI

```

Reboot; confirm with aplay -l (playback) and arecord -L (XVF3800 shows as a capture device).

  1. Install Home Assistant (self-contained option): HA Container via Docker, or HA OS on a

second box for option B. Docs: https://www.home-assistant.io/installation/

  1. Wire up Assist (STT + TTS + wake word) — all local:
  1. Run the satellite on the Pi:

WebSocket API) — https://github.com/OHF-Voice/linux-voice-assistant

  1. Point wake word at alexa and set --mic-command to the XVF3800 capture device

(arecord -D plughw:CARD=...). It now answers to "Alexa."

  1. LEDs. Drive the ring from the satellite's peripheral API (linux-voice-assistant WebSocket)

or a small Python service using adafruit-circuitpython-neopixel-spi (SPI, GPIO10) — see §6.

  1. Music. Add Music Assistant (https://www.music-assistant.io/) → play to the satellite

media player (Spotify/local/DLNA).

  1. (Optional) smarter brain. Assist → Conversation agent → wire an LLM (Google Gemini,

OpenAI, or a local model via Ollama) for open-ended questions Alexa would punt on.


6. Light-ring language (WS2812 ×16, over SPI)

StateAnimationColor
Idleoff / faint breathingdim white 5%
Listening (post-wake)full ring onmint #3ddc97
Thinking (STT/intent)spinnermint → cyan
Speaking (TTS)soft pulsemint
Muted (HW mic switch)solidred #ff5a5a
Error / no networkdouble blinkamber #f0b429

Drive over SPI (GPIO10), not PWM — PWM's GPIO18 is taken by I2S BCLK (see audit).

adafruit-circuitpython-neopixel-spi needs no root and won't fight the audio clock.


7. Debug & design audit (the parts that bite people)

  1. GPIO clash: LEDs vs I2S. The common rpi_ws281x PWM path uses GPIO18 — which I2S

BCLK also uses. Two fixes, one chosen: drive WS2812 over SPI (GPIO10). Enabled with

dtparam=spi=on. Adjustment: BOM/wiring updated to SPI, not PWM.

  1. Barge-in / AEC reference. If audio goes out the Pi's I2S but the mic array is on USB, the

XVF3800 never sees what you're playing, so it can't cancel it — "Alexa, stop" fails over loud

music. Adjustment: recommend wiring 4b (playback through XVF3800) for true AEC. MVP wiring 4a

still works quietly; barge-in just degrades at high volume.

  1. Power budget. Pi 4 (~15 W) + XVF3800 (~2.5 W) + amp/speaker peaks (~3 W) + 16 LEDs

(up to ~0.9 A at full white). A 5.1 V/3 A supply is marginal if everything peaks. Adjustments:

cap LED brightness (≤30%) and never full-white all 16; for headroom use a 5 V/4–5 A supply or a

small separate 5 V buck for the LED ring + amp. Don't pull >1.5 A through the Pi's 5V pin.

  1. Whisper latency/heat on Pi 4. whisper-base-int8 ≈ 1.5–3 s and warms the SoC. Adjustments:

heatsink + fan (in BOM + enclosure vents); if too slow, move STT to option-B server.

  1. Enclosure acoustics. The speaker can vibrate the mic array and self-trigger. *Adjustments in

SCAD:* mic array mounts on the top plate, speaker chamber sealed below the grille, add a

foam gasket / rubber foot to decouple; keep the LED ring diffuser from rattling.

  1. Onboard-audio pop / wrong device. dtparam=audio=off kills the headphone-jack pop; verify

arecord -L and set the exact XVF3800 plughw: string in the satellite mic command.

  1. 32-bit trap. VAD/wake word need 64-bit OS. Flash the 64-bit Lite image.
  2. Wake-word false accepts. openWakeWord alexa threshold defaults can over-trigger near a TV.

Tune threshold / use microWakeWord for a lighter, tighter model.


8. Adjustments made vs the first mockup


9. Upgrade path

our build trades polish for a bigger speaker, bigger array, and a hackable brain.


10. All part links (flat list)

Software