Repurpose your Mycroft Mark II as a Home Assistant voice satellite — mark2-assist

If you have a Mycroft Mark II collecting dust after Mycroft AI shut down in 2023, here is a way to give it a second life as a proper Home Assistant voice satellite with touchscreen dashboard, LED feedback and multiroom audio.

Repo: GitHub - andlo/mark2-assist: Repurpose your Mycroft Mark II as a Home Assistant voice satellite, kiosk display, and multiroom audio endpoint — running on current Raspberry Pi OS. · GitHub


What it turns your Mark II into

  • Voice satellite for HA Assist — say your wake word, ask anything, control your home
  • Touchscreen kiosk — shows your HA dashboard on the built-in 4.3" display, touch to control
  • LED ring that reacts to voice states — pulses when listening, glows when speaking
  • Animated face overlay that reacts to voice and dances to music
  • MQTT sensors — Mark II appears in HA with CPU temp, voice state, audio playback state etc.
  • Multiroom audio via Snapcast or AirPlay (optional)
  • MPD music player that integrates with Music Assistant (optional)

Why this is interesting for HA users

The voice pipeline runs entirely through HA Assist — so you choose what powers each step. No cloud required if you don’t want it:

Step Options
Wake word Local on device (openWakeWord)
Speech to text Whisper locally, Nabu Casa, cloud
Conversation HA built-in, OpenAI, Google, local LLM
Text to speech Piper locally, Nabu Casa, cloud

Switch pipeline without touching the device. Same setup that works with your other HA voice satellites works with Mark II too.


Auto-login on the touchscreen

The touchscreen shows your HA dashboard automatically after boot — no keyboard needed. Uses HA’s trusted_networks auth provider so the specific Mark II IP gets passwordless access. Full setup instructions are in the docs.

Create a dedicated mark2 user in HA, set the Mark II dashboard as their default, and point the kiosk at your HA URL. The screen loads straight to your dashboard on boot.


Hardware

The Mark II has surprisingly good hardware for this:

  • XMOS XVF-3510 6-mic array with hardware noise cancellation and echo cancellation
  • TAS5806 23W stereo amplifier
  • NeoPixel LED ring (12 LEDs)
  • 4.3" 800×480 DSI touchscreen
  • Volume buttons and action button
  • PWM-controlled cooling fan (automatic thermal management via kernel)

All of it works on current Raspberry Pi OS (Trixie / Debian 13).


Installation

Flash Raspberry Pi OS Lite (64-bit, Trixie) to a USB stick, SSH in, clone the repo and run:

bash

git clone https://github.com/andlo/mark2-assist
cd mark2-assist
./install.sh

The installer asks all questions upfront, handles the hardware driver setup and reboot automatically, and resumes after reboot. Total time around 20–40 minutes.

A hardware test suite is included to verify all components before you proceed.


Mark II dashboard

A ready-to-paste Lovelace dashboard YAML optimised for the 800×480 touchscreen is included in docs/mark2-dashboard.yaml. Uses Mushroom Cards and layout-card (both HACS).

Shows clock, weather, media player with controls, quick action buttons and active timers.


Status

Working daily driver on my own Mark II. Still some rough edges and known issues documented in the repo. Contributions welcome — especially if you have a Mark II and want to help test and improve things.

Questions and feedback welcome here or on GitHub.

2 Likes

Awesome! I just happen to have my Mark II on my desk right now, trying to figure out what to do with it. Going to give this a try!

1 Like

Mostly working, but ran into a few issues so far. The script didn’t auto-install pipewire, which appears to be a dependency for lva. I tried installing it manually, but it’s giving me some errors and I think as a byproduct of that the lva systemd script isn’t being installed. I’m creating one manually to see if that let’s me start lva, but I keep getting some pipewire errors in my logs.

Got me a bit farther, but on reboot I’m still seeing lva failing:

  Services:
  ✗ Voice assistant (LVA)        failed
  ✓ SJ201 audio hardware         running
  ✓ Volume buttons               running
  ✗ Face / HUD events            inactive
  ✓ LED ring                     running
  ✓ MQTT sensors                 running
  ✗ AirPlay                      activating
  ✓ MPD music player             running

And the following error in my lva systemd output:

openclaw@raspberrypi:~$ systemctl --user status lva
× lva.service - Linux Voice Assistant
     Loaded: loaded (/home/openclaw/.config/systemd/user/lva.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Sun 2026-04-19 04:38:24 BST; 24s ago
   Duration: 2min 1.735s
 Invocation: 293a83da816e4528869281f28131723d
    Process: 1102 ExecStart=/home/openclaw/lva/.venv/bin/python3 -m linux_voice_assistant --name Nabu-1 --wake-model okay_nabu --audio-input-device SJ201 ASR (VF_ASR_L) --audio-output-device pipew>
   Main PID: 1102 (code=exited, status=1/FAILURE)
        CPU: 1.088s

Apr 19 04:38:24 raspberrypi python3[1102]:     from soundcard.pulseaudio import *
Apr 19 04:38:24 raspberrypi python3[1102]:   File "/home/openclaw/lva/.venv/lib/python3.13/site-packages/soundcard/pulseaudio.py", line 290, in <module>
Apr 19 04:38:24 raspberrypi python3[1102]:     _pulse = _PulseAudio()
Apr 19 04:38:24 raspberrypi python3[1102]:   File "/home/openclaw/lva/.venv/lib/python3.13/site-packages/soundcard/pulseaudio.py", line 101, in __init__
Apr 19 04:38:24 raspberrypi python3[1102]:     assert self._pa_context_get_state(self.context)==_pa.PA_CONTEXT_READY
Apr 19 04:38:24 raspberrypi python3[1102]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Apr 19 04:38:24 raspberrypi python3[1102]: AssertionError
Apr 19 04:38:24 raspberrypi systemd[957]: lva.service: Main process exited, code=exited, status=1/FAILURE
Apr 19 04:38:24 raspberrypi systemd[957]: lva.service: Failed with result 'exit-code'.
Apr 19 04:38:24 raspberrypi systemd[957]: lva.service: Consumed 1.088s CPU time.

I’ll try again tomorrow on a clean install of Raspberry Pi Os Lite as this one has been used for a few other things.

Similar (same?) issues after a clean install. I manually installed pipewire again then ran the installer:

[WARN] Satellite setup failed — check /home/mycroft/.config/mark2/install.log

I see this in the mentioned log:

Collecting soundcard<1 (from linux-voice-assistant==0.0.0)
  Using cached https://www.piwheels.org/simple/soundcard/soundcard-0.4.6-py3-none-any.whl (43 kB)
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))': /simple/numpy/

This is what I see after installation:

       Installation progress:
         ✓ hardware
         ✗ satellite (failed)
         ✓ homeassistant
         ✓ ui
         ✓ mqtt-sensors
         - snapcast (skipped)
         - airplay (skipped)
         - mpd (skipped)
         - kdeconnect (skipped)
         - usb-audio (skipped)

I tried to run mark2-satellite-setup.sh by itself, and I get the following:

[OK] Linux Voice Assistant installed

=== Installing PipeWire virtual source for SJ201 ASR ===
[OK] PipeWire SJ201 ASR source + Speaker sink installed
[OK] PipeWire wait script installed: /usr/local/bin/mark2-wait-pipewire
[OK] Waiting for SJ201 virtual devices in PipeWire...

But pipewire and wireplumber seem to still not want to start. Tracking that down it seems to be a missing .asoundrc file that I think the VocalFusionDriver is supposed to create as part of it’s install? Not sure, but that’s where I’m at.

Great. Sorry but ran out of time to do fun stuff. Will get back at it again and do more reflashing and tests.

Feel free to open issues on githubthe repo

Thanks for the detailed bug reports — you nailed both issues!

You found two real bugs that would affect anyone on a clean install:

  1. PipeWire not installed in timeinstall_lva() was copying PipeWire configs and restarting PipeWire services before the packages were actually installed (that only happened later in install_kiosk_packages()). PipeWire is now installed up front in install_dependencies() before anything else touches it.

  2. Missing .asoundrc — the scripts relied on ~/.asoundrc mapping ALSA’s default device to the XVF-3510’s dedicated ASR channel (VF_ASR_L), but that file was never actually created. Without it, ALSA falls back to raw 48kHz stereo from the XMOS chip which gives an RMS of ~20 — way too low for openWakeWord. The file is now created during hardware setup.

Both fixes are in main as of today. If you want to retry, flash a fresh image and it should work end to end.

Tracked as issues #13 and #14 if you want to follow along.

1 Like

Awesome, thanks I’ll give it another go!

Got through the install w/out issues this time!

Wake word doesn’t seem to be working, but I’ll spend some time trying to figure out why, it’s showing up in HA now though and the UI is online (wasn’t before) so that’s progress. Thanks again! I’ll let you know if I run into any more issues.

1 Like

Yah I am working - when something seems to work, there are others that dosnt…
Ill hope to get wakeword workint (again)
tonight…

Great progress! The UI and HA integration working is the hard part — wake word is a known issue we’re actively working on right now.

The problem is in the audio pipeline between the XVF3510 microphone DSP and PipeWire. The hardware itself works fine (we can confirm with raw ALSA recording), but we’re still sorting out the correct PipeWire routing so the wake word engine receives the right signal. We’ve tracked it down and expect a fix soon.

In the meantime, you can check if your microphone is working at all by running from SSH:

bash

systemctl --user stop lva
arecord -D hw:sj201,1 -r 16000 -c 2 -f S16_LE -d 3 /tmp/test.wav
# say something during the 3 seconds
aplay /tmp/test.wav
systemctl --user start lva

If you hear yourself played back, the hardware is fine and it’s purely a routing issue that will be fixed in the next update.

1 Like

Update — May 2026: Microphone fix + major simplification

Good news for everyone who ran into issues — the last few weeks have been very productive.

Root cause found: XVF-3510 microphone was always silent after boot

The real issue turned out to be a clock frequency problem. sj201.dtbo sets MCLK (the master clock for the XVF-3510 chip) to 24.576 MHz. The chip actually requires exactly 12.288 MHz to start its internal DSP pipeline. With the wrong clock, the chip boots, accepts the SPI firmware, and responds on I2C — but produces no audio. This explains all the reports of inconsistent microphone behaviour.

The fix is a new mark2-audio-init.service that runs on every boot and sets the correct clock before flashing the XVF-3510 firmware. Result: sustained microphone signal from cold boot, RMS ~0.10 consistently. Wake word detection is now actually testable.

Full technical writeup in docs/XVF3510_HARDWARE.md.

Installation is now zero-config

Based on feedback here and elsewhere, the installer has been significantly simplified:

  • No prompts at install time — just run ./install.sh and it handles everything
  • Kiosk now opens Home Assistant directly (homeassistant.local) — no local proxy, no iframe
  • Face animation runs as a transparent always-on-top overlay window
  • Satellite name, wake word, volume and mic settings are all configurable from HA UI via ESPHome entities
  • Screensaver timeout via config file (HA UI control planned)
  • whiptail removed entirely — works over SSH without a TTY

PipeWire routing simplified

LVA now uses the PipeWire node name Built-in Audio (bcm2835-i2s-dir-hifi dir-hifi-1) directly, rather than the old SJ201 ASR (VF_ASR_L) device that required a custom PipeWire module. The pipewire-alsa package handles routing. No more .asoundrc needed.

For @gabeguz and others who had issues: a fresh flash with the current dev branch should work end-to-end now. The old PipeWire virtual source approach (which caused the AssertionError in soundcard) is gone. Happy to help if you run into anything.

1 Like

Thanks, installer is much simpler now! I did run into a few hardware errors this time that I didn't see before:

=== 1. SJ201 Service ===
  ✗ FAIL  sj201.service — not active (status: inactive)
  Waiting for XMOS XVF-3510 and vocalfusion module (up to 15 seconds)...
  ✓ PASS  XVF3510 firmware file
  ✗ FAIL  vocalfusion kernel module — not loaded after 15s — check dmesg for errors

I'll do some debugging on my side (this is from a clean install of rasppi os and install of mark2-assist following the instructions in the README.

But I do see the device automatically in HA and was able to configure it there. Audio does seem to be working when I push it from HA (testing the voice assistant, I hear the "hello, how can I assist" on the Mark II's speakers, but the microphones don't seem to be working (I guess that's what the failing hardware tests above are pointing to).

The display seems to be working, though I don't see a dashboard, just a blank white screen.

Thanks again for all the work on this, great to see my MarkII brought back to life!