top of page

Making Your Arduino Ding

  • Writer: Philippe Chretien
    Philippe Chretien
  • Apr 19
  • 4 min read

There's a moment in every hardware project where you think "this should be simple" — and then you spend an evening down a rabbit hole of SPI buses, voltage dividers, and audio formats you've never heard of. Adding WAV playback to my Arduino quiz buzzer was exactly that kind of evening. But it worked, and it was genuinely satisfying. Here's how it went.


The Project That Needed a Voice

I'd been building a two-team quiz buzzer system for a while — buttons, LEDs, interrupt logic, the whole thing. It uses an MCP23017 I/O expander to handle eight buttons and eight LEDs across two teams. The first team to press their button wins the round, the LED lights up, the host hits a reset button, and you go again. Functionally solid. But silent. Dead silent.


That felt wrong. A quiz buzzer needs a sound. Team A gets a cheerful little "ding", Team B gets a buzzer. That's the whole vibe. So I went looking for the simplest possible way to get audio out of an Arduino Uno.


The answer, it turns out, is a passive SD card module and the TMRpcm library. Total cost: a couple of euros for the SD module and a handful of resistors I already had in a drawer.



The SD Card Module and the SPI Bus

The SD card module connects to the Arduino's SPI bus — pins 11 (MOSI), 12 (MISO), and 13 (SCK) — plus a chip select pin, which I put on pin 10. The module runs at 3.3V logic, but the Arduino talks at 5V. That's the catch.


The "proper" solution is a logic level shifter. I didn't have one. What I did have was a pile of 1KΩ resistors and the knowledge that a voltage divider works just as well for slow SPI signals.


The idea is simple: you put two resistors in series between the Arduino's 5V output and ground, and tap the middle point to get a lower voltage. For the MOSI and SCK lines (Arduino → SD card), a 1KΩ and 2KΩ divider gives you a clean 3.3V output from a 5V input. I didn't have any 2KΩ resistors, so I used two 1KΩ resistors in series to make 2KΩ. Works identically — same math, just two physical components instead of one.


The MISO line (SD card → Arduino) doesn't need the voltage divider. The SD card outputs 3.3V, and the Arduino's digital inputs are happy to read that as a HIGH signal. So MISO connects straight through.



It feels a little hacky, but it's electrically sound. The SPI communication with the SD library worked first try, which was a pleasant surprise.


TMRpcm and the Speaker

For audio playback, I used the TMRpcm library. It does asynchronous WAV playback using the Arduino's Timer1, outputting a PWM signal on pin 9. The audio isn't hi-fi — it's 8-bit, mono, sampled at 16KHz — but for a quiz buzzer sound effect, that's more than enough.


The speaker I had on hand was a CEM 1203 (42) — one of those tiny, round, piezo-adjacent speakers you find in cheap toys and alarm clocks. It's rated for about 78dB, which sounds modest but is actually plenty loud for a small room. More importantly, it has a 42Ω impedance, which keeps the current draw manageable directly from the Arduino pin.


Connecting it was straightforward: one leg to pin 9, the other to ground. No amplifier, no coupling capacitor. TMRpcm handles the PWM magic, and the speaker just... vibrates.


audio.speakerPin = 9;
SD.begin(10);

That's genuinely all the setup code needed. Then whenever a team buzzes in:


audio.play("ding.wav");   // Team A
audio.play("buzz.wav");   // Team B


The WAV files themselves need to be in a specific format to work with TMRpcm: 8-bit, mono, unsigned PCM. The library supports 16KHz and 8KHz sample rates, and I started with 16KHz thinking higher quality would be better. That turned out to be a mistake — on an Arduino Uno, 16KHz proved unreliable. Sometimes the sound would play garbled and unrecognizable, other times playback simply wouldn't stop. Not great when your quiz buzzer is stuck on a loop emitting a distorted buzz.


Dropping to 8KHz fixed it completely. The Uno just doesn't have enough headroom to stream 16KHz audio reliably from an SD card while also handling SPI, PWM output, and the rest of the sketch. At 8KHz the sound effects are slightly lower fidelity, but for a ding and a buzz, nobody notices. I used ffmpeg to convert:


ffmpeg -i input.mp3 -ar 8000 -ac 1 -acodec pcm_u8 ding.wav

Drop those files in the root of a FAT32-formatted SD card, slot it in, and you're done.


What's next?

The CEM 1203 is simply not loud enough — even in a quiet room you're straining to hear it. A proper amplifier is the fix, and honestly it's an excuse to finally build one. A simple LM386 circuit would do the job nicely. That's next.


I'd also swap the resistor voltage divider for proper level shifters. It works, but it's the kind of wiring that looks baffling six months later.


But as a quick addition to an existing project? This whole audio subsystem — SD module, resistors, speaker, WAV files — probably took two hours start to finish, most of which was the ffmpeg conversion rabbit hole and the wiring mistake. The actual integration into the quiz buzzer sketch was trivial.


If you're building anything that could benefit from a little sound feedback, this approach is worth knowing. It's cheap, it's simple, and there's something genuinely delightful about a piece of hardware that talks back.


The Code

You can find the code for the Quiz Buzzer with sound on Gighub.

 
 
 

Comments


  • Facebook
  • Twitter
  • LinkedIn

©2022 by Basbrun. Proudly created with Wix.com

bottom of page