A pocket Navidrome player on a XIAO ESP32-C3
I wanted a music player I could pick up, press one button on, and hear something from my own library. No phone, no app, no account. The result is a box about the size of a large ice cube that streams from my home Navidrome server over Wi-Fi.


The parts
- Seeed XIAO ESP32-C3. Wi-Fi and enough RAM to stream and decode MP3s on the chip.
- TI PCM5102A DAC. Takes I²S audio from the XIAO and turns it into a line-level signal for headphones.
- Adafruit 128×64 SSD1306 OLED. Shows the song title and album over I²C.
- Two Omron B3F buttons. Play/Pause and Next.
- A 450 mAh LiPo with a slide switch. The XIAO charges it over USB-C.
How it works
The firmware is plain C on ESP-IDF. On boot it joins Wi-Fi, logs in to Navidrome, and asks it for a random song. Then it streams the MP3 through a 24 KiB network buffer, decodes it on the chip with the Helix MP3 decoder, and sends the samples out over I²S to the DAC. When a song ends it picks another one. Next cancels the current song and does the same thing straight away.
The screen uses a tiny 5×7 font, 21 characters across and eight rows deep. Song titles word-wrap so you can read the whole thing, and only a title too long for the screen scrolls.

The bug that made the screen go black
After one replug the screen stayed black, but the music kept playing. The serial log showed why: the firmware had checked for the screen once at boot, got no answer, and turned the display off for the rest of the session. The OLED has its own power-on reset circuit, and it most likely just wasn't ready yet.
The fix makes the firmware look for the screen again every two seconds. Every five seconds it also resends all of the screen's settings and redraws the page, so a screen that resets itself after a power dip comes back by itself. If an I²C transfer fails, it resets the bus and starts over.
What's left
I'm calling this one done, but it isn't perfect:
- The Play/Pause button is stuck. Its line reads as pressed from the moment the board boots, so presses never register. That's a wiring fault, probably a short to ground, not a firmware bug. Next works fine.
- Audio only comes out of the left side of my headphones. I haven't tracked down why yet.
Both are fixable with a soldering iron and some patience, and both are good reasons for the next version to be a proper circuit board instead of hand-wired modules.