A few weeks ago I wrote about getting a Waveshare UGV Rover talking to a Steam Deck and ended with the line "give it a few weeks." Here we are.
The rover works. It drives, it steers, the B button still stops it dead. What's changed since April is everything around that core loop — and one of those changes is worth writing up properly because it took longer than it had any right to.
The Quiet Robot Problem
The rover has a small onboard speaker. Technically it produces sound. Practically it produces something closer to a polite suggestion of sound. In a quiet room you can hear it. In a room with six teenagers and a hard floor, it might as well not be there.
So I added a USB speaker. Plugged it in, expected things to Just Work, and of course they didn't. The Pi happily acknowledged the new device existed but kept routing audio to the onboard one anyway. This is one of those Linux audio situations where there are three different subsystems with overlapping responsibilities and the answer depends on which one is in charge today.
Three options, in increasing order of "this will survive a reboot":
~/.asoundrc— tell ALSA directly. Works, but feels brittle.- Environment variable in the script — point pygame at a specific ALSA card index. Works, but ties the fix to the script rather than the system.
pactl set-default-sink— set the default at the PulseAudio/Pipewire layer. Cleanest. The whole system respects it.
The two diagnostic commands that mattered:
aplay -l # which ALSA card is which
pactl list short sinks # what Pipewire actually thinks is available
I went with option three. It's the one that doesn't require remembering anything special when something else on the Pi wants to make noise later.
Why Bother Giving It a Voice At All
This is the bit I want to dwell on, because it's the difference between a remote-control car and something teenagers will actually engage with.
A robot that moves is interesting for about four minutes. A robot that moves and reacts, that says something when you drive it into a wall, or announces itself when it powers up, or has a personality the kids can argue with, is interesting for as long as you let them have it.
Voice is the cheapest possible way to add personality. You don't need facial servos or LED matrices. You just need it loud enough to hear over a room of twelve-year-olds, which is where the USB speaker comes in.
The TTS pipeline is already in place. Commands flow from the Steam Deck to the Pi alongside the movement instructions. Now they actually reach a speaker that can deliver them.
The Shed Project Confession
There's a thing I keep doing that I want to stop doing. When I talk about this project in any sort of professional context, LinkedIn, funder conversations, board updates, I have a reflex to frame it as Inclusive Bytes work. As if a personal evening-and-weekend project needs an organisational justification to count.
It doesn't.
I built this in my shed because I wanted to. The fact that it will end up serving Inclusive Bytes sessions is a happy downstream consequence, not the originating purpose. The distinction matters because the things you build for yourself, in your own time, with no remit and no deliverables, are often the most useful things you end up with. The ones built to a brief tend to come out shaped like the brief.
This is a shed project. It came out of curiosity and stubbornness and a Tuesday evening with nothing else on. That's the entire pedigree, and it doesn't need a better one.
What's Next
The rover is field-ready. Next is a session with actual young people, which is the only test that matters. I've got a list of small additions queued up, a low-battery announcement, a "stop and apologise" routine for when it bumps into things, eventually a camera stream to a second screen so a second kid can spot for the driver.
Each of those is a project a young person could lead on, which is the whole point. The rover isn't the lesson. The rover is the excuse to have the lesson.
Give it a few more weeks.