Arduino Project 5: Digital audio player

Arduino Project 5: Digital audio player

 

So far in this series we’ve had a diverse look at how Arduino can interact with a range of real-world devices from servo motors to ultrasonic range finders TVs to humidity sensors. Now we’ll see if we could get the Arduino to make a few sounds. We’ll actually do a bit better than that – we’ll look at the importance of pulse width modulation (PWM) to microcontrollers by building our own digital audio player called Auduino.

 

The two versions of our Auduino audio player. The Ethernet shield version (bottom) gives better results with more flash cards.

What we’re building

A few months ago I stumbled across a simple single-button digital audio player based around a Raspberry Pi developed by a guy for his 90-year-old grandmother who needed something simple to use. All it had was a single button and an LED and it was programmed to play digital audiobooks. The button pressed quickly would pause and play while holding it down for more than four seconds would play the previous track.

 

A digital audiobook player using a Raspberry Pi.

I couldn’t help wondering if we could do something similar and simpler with an Arduino. Well you can. We’ve combined an Arduino Uno microcontroller a $1.50 SD card reader module from eBay computer speakers and some other components to create a simple single-button digital audio player. There’ll be a small amount of soldering involved.

Admittedly our player’s WAV file support is modest (mono 8-bit up to 19kHz) but the quality is still more than good enough to handle music and digital audiobooks. However don’t miss the bigger picture – an audio player we can digitally control opens up a world of possibilities.

 

Making the WAV files

If you’re wondering where you’ll find 19kHz/8-bit/mono WAV files we’ve got that covered. I’ve created an easy-to-use audio converter that integrates into Windows Explorer and converts any audio file into the required WAV format. You can even convert multiple files at the same time and it automatically turns those files into the 8.3 filenames our player requires. All you do then is copy the WAV files to the root of a FAT32-formatted Class 4 SDHC card (we’ve tested cards up to 8GB). Load the card into the player’s SD card reader module press the button and the first track will begin playing.

 

How it works

The ability to turn digital data – 1s and 0s – into a proportional analogue voltage is a fundamental tenement of digital audio and it’s where the digital-to-analogue converter (DAC) gets its most celebrated use. Audio DACs appear in every smartphone tablet MP3 player PC and laptop. They’re everywhere. DACs are also used to control motors and sensors LEDs and more – anywhere where you need to turn a digital number into a real-world analogue voltage. One of the simplest ways to do it is what makes microcontrollers so popular – it’s called Pulse Width Modulation (PWM).

The problem for all microcontrollers is that their standard digital outputs only have two positions: high and low. The output will either be at the supply rail (Arduino’s 5V) or ground (0V); there’s no in between. This is where PWM comes in. It starts with a clock signal output that runs at a much higher rate than we need; in our case beyond the 20kHz audio spectrum. That clock signal is a squarewave meaning it spends half the time at digital-1 and half at digital-0 in each clock cycle. In geek speak we say it has a duty cycle of 50%.

What PWM allows us to do is modulate that duty cycle so that when its pulse waveform output is fed and filtered through a particular device the waveform is averaged and becomes an analogue voltage that’s proportional to the duty cycle. So if the waveform signal varies between 0 and 5V and has a 10% duty cycle it’ll have an average analogue voltage of 0.5V. At 50% duty cycle it’ll be 2.5V; at 90% it’ll be 4.5V.

This is how the pulsating LED on your iPhone or iPad works. The LED will be fed with a PWM waveform that varies between 0 and 100% duty cycle at a high enough frequency so you can’t see the LED flashing.

Your typical music file is the result of the reverse process: turning a complex analogue voltage into a digital representation. Audio CDs capture two channels (stereo) at a 44.1kHz sample rate with 16-bit resolution. What that means is there are 216 or 65536 distinct voltage levels that can be captured every 22.6 milliseconds or so.

It’s called Pulse-Coded Modulation (PCM) and it’s the basic format used by Windows’ WAV file format. Look at a WAV file and you’ll see a long series of 16-bit numbers that represents the audio (one per sample and one per channel). Turning those digital samples back into an analogue voltage is what every audio player does.

One way of doing this happens to be PWM. Remember how we said before that a PWM signal is modulated to create a variable duty cycle waveform? Guess what we use to modulate the clock signal with? The digital audio samples from our WAV file. So what we end up with is a PWM waveform output whose duty cycle is proportional to the PCM audio data in the WAV file. We feed the output into an audio amplifier and hey presto! We hear that digital audio WAV file coming through the speakers.

 

PWM can create an analogue voltage that’s proportional to its duty cycle.

 

Arduino limitations

While we love Arduino this is where we run into its limitations – it only has an 8-bit bus and combined with its limited 16MHz clock speed and our audio code library we only have enough speed to handle WAV files with a 19kHz sample rate and 8-bit depth. That said I’ve worked on our simple audio converter to tweak the encoding so it produces good-sounding files with a better than AM radio frequency bandwidth which is good enough for music and certainly more than enough for digital audiobooks.

 

Convert any audio file into ‘Auduino’ format

01 Download Auduino

Download the ‘auduino.zip’ file from apcmag.com/arduino.htm and unzip it to the ‘C:Auduino’ folder on your C: drive. Launch the ‘InstallWavConverter.reg’ file. This installs a Shell registry key that adds a new menu entry to Windows Explorer’s context menu. (Open the REG file in Notepad and you can see how it works.) Click the ‘Yes’ button to confirm and then ‘OK’ when it’s completed (‘RemoveWavConverter.reg’ deletes the registry key if you wish).

 

02 Convert an audio file

Use Windows Explorer to find an audio file you wish to convert right-click the file and select ‘Convert to APC/Auduino format’. You’ll see a Command Prompt screen appear briefly and when it disappears you’ll have a new WAV file in the original file’s location. You can even select multiple files to encode all at once.

Looking for free downloadable digital audiobooks? Try LibriVox and Books Should Be Free. These are usually in MP3 or OGG format with books separated into chapter files. Our encoder can easily turn these into the necessary WAV format.

 

03 Transfer & play

Copy this file(s) to the root folder of a Class 4 FAT32-formatted SD card up to 8GB and transfer the card to the Auduino player. Files can be up to 2GB. Power up the player and press the button.

 

Building the Auduino

We’re building our prototype this month on the same breadboard we used for our LED dice and weather station projects as it makes it easier to troubleshoot and program the Arduino. You can see how it goes together from the circuit diagram the overlay diagram and the photos. The SD card module has two rows of pins and each pair is wired together so it can plug straight into the breadboard.

 

The circuit diagram for our digital audio player.

 

Voltage Level Translation

If there’s a tricky part of the circuit it’ll be the diodes connecting the Arduino to the SD card module. It may look like the diodes are facing the wrong way but they’re not. We’ve got a small problem in this project that the diodes are helping to fix for us. Basically the Arduino runs on a 5V logic level (that means the digital outputs swing from 0V to 5V) but SD cards only run on 3.3V. If we feed 5V into the data lines of the SD card module we risk blowing up the card.

The diodes therefore act as a voltage level translator. The SD card module has pull-up resistors on three of the four data lines which lightly connect these lines to the supply rail. When the Arduino digital output swings low the diodes are forward-biased by the current through the pull-up resistor and the SD module control line drops low to 0.6V. When the Arduino output rises up to 5V the diode becomes reverse-biased and no current flows from the Arduino to the SD module. The pull-up resistor lifts the data line to the 3.3V supply rail so we get our digital-1 at the required 3.3V instead of the Arduino’s 5V so everyone’s happy. (The SD module has a 3.3V voltage regulator on board that drives the pull-up resistors.)

Electrical engineers would argue that this is a dodgy fix and we should be using a dedicated level translator chip like a 74HC4050 and they’re right. The diode option does work although as we’ve discovered not reliably. We tested it with half a dozen different SD cards and found two of the six worked well one sort of worked and three didn’t work at all. Some SD cards expect to see digital signals that snap between 0V and 5V in no more than five nanoseconds while others are more tolerant and they’re the ones that work.

 

The layout diagram of our digital audio player using an 840-point breadboard.

 

Choosing SD cards

The SD card module talks to the Arduino over the SPI (Serial Peripheral Interconnect) bus but SPI is really just a 1-bit economy mode interface that’s easy to implement whereas SD cards normally communicate over a 4-bit wide bus. Combine our low-level translation circuitry with the fact that not all SD cards do SPI well and that unfortunately limits the cards we can use. We recommend Class 2 or Class 4 SD cards that are preferably 8GB or smaller. You can try larger Class 4 cards (we’ve used a 32GB card successfully) although you’ll need to make some changes to our Arduino code: change the cardType variable from oldCard to newCard . Basically the newer or larger the card the slower we need to run the SPI bus so doing this drops it back from 8MHz (half-speed) to 4MHz (quarter-speed). Any slower than 4MHz however and the data rate becomes too slow and you can hear the continual jitter in the sound output. We purchased new 4GB and 8GB Class 4 Verbatim cards. The 4GB card didn’t work but the 8GB card worked perfectly at the 8MHz/half-speed rate.

Our modified SD library still works with all existing Arduino programs (sketches) but adds a new instruction that allows us to adjust the Arduino’s SPI speed and allow more cards to work.

 

Alternative option

We’ve also come up with a more reliable option which involves ditching the $1.50 SD card reader and replacing it with a $10 Ethernet Shield that includes a microSD card slot. You remove the components connected to pins 10 11 12 13 and change the sketch by setting the chipSelect variable to 4 (this is marked in the sketch code). You also need to set the cardType variable to oldCard . The Ethernet Shield has the proper level translation built in to reliably work with any microSD card. The Shield sits on top of the Arduino and you use the same I/O pins for the switch and audio out.

 

Solder the stereo socket

Our Auduino player doesn’t have a built-in amplifier yet so we need external speakers and a way of getting our audio signal to them. That’s what the 3.5mm stereo socket is for. We need to solder it up so to do this first grab a couple of Dupont wires. Cut them in half strip the insulation off tin them and solder them to the three tags on the socket. These give us connections to a 3.5mm plug’s tip ring and sleeve (TRS) connections. Given that we’re only using mono audio we feed the audio output to both channels so when you plug in the 3.5mm cable to your stereo amplifier you’ll hear sound coming out of both speakers.

 

Software libraries

We’ll need the ‘tmrpcm’ and a modified ‘SD’ card library. You’ll find these in the zip file you can download from apcmag.com/arduino.htm (look under the Project 5 heading). Copy the ‘SD’ and ‘tmrpcm’ folders to the ‘libraries’ folder in your Arduino IDE folder (yes overwrite the original ‘SD’ library) and restart the IDE if you’ve had it running already.

The ‘apc_05_audioplayer.ino’ file is our sketch which ties everything together. It boots up the Arduino turns on the SD module checks the card and waits for you to press the button. Press it for less than a second and it’ll load and play the first file. If you press the button again for less than a second it’ll pause playback; pressing it again resumes playback. Press it for more than a second and it’ll automatically skip forward to the next audio track and begin playback. There are no volume controls – you adjust this at your amplified speakers.

Unfortunately the ‘tmrpcm’ library creates a pop whenever a track stops or starts. A low-pass filter will help a little but it’s caused by the PWM signal turning on and off.

 

Parts List

The specific parts for this project should cost you less than $40 if you choose the SD card module option. The hardest thing to find will be the SD card module itself – we bought ours from eBay for just US$1.48 (including shipping) from Hong Kong. The rest of the parts can be picked up from your local Jaycar Electronics or most online electronics stores.

  A super-cheap SDHC card module for under $1.50 on eBay.

 

Give it a crack

A digital audio player we can control offers plenty of ideas. Just a few I can think of off the top of my head include a talking robot a voice-warning security system a talking weather station and I’m sure you can come up with a few of your own. By building this project you’ll learn more about digital audio and even be able to incorporate some of the techniques into your own Arduino projects.

 

Arduino parts list

Part Cost per unit Source
Arduino Uno R3 US$14 eBay
LC Studio SD card module US$1.48 eBay
Push-button momentary switch $1.25 Jaycar
1N4148 signal diode $0.40 Jaycar
5mm red LED $0.25 Jaycar
100uF/16VW electrolytic capacitor $0.36 Jaycar
0.1uF MKT capacitor $0.40 Jaycar
0.0015uF MKT capacitor $0.35 Jaycar
1kΩ/0.25W metal-film resistor $0.46 Jaycar
4.7kΩ/0.25W metal-film resistor $0.46 Jaycar
10kΩ/0.25W metal-film resistor $0.46 Jaycar
47kΩ/0.25W metal-film resistor $0.46 Jaycar
4GB Class 4 Verbatim SDHC card $6.75 Various retailers (including Officeworks)
3.5mm stereo socket $1.35 Jaycar
3.5mm male-to-male cable $4.95 Jaycar
Dupont wires US$3.66 eBay
Ethernet Shield (alternative) US$9.62 eBay

 

  • Tom Steyer

    hi, thanks for this compete article, your solution is a good option to listen music, i have a question about the voltage for SDHC card module, you use 5v, why you don’t use directly 3,3v? i have the same module and i use 3,3v to make it works. thanks

    • http://darrenyates.com.au Darren Yates

      Hi Tom,
      The card module has a 3.3V voltage regulator on board, so the card runs at 3.3V. However, the Arduino, running out 5V, has its outputs hitting that 5V mark. Feeding 5V outputs into a 3.3V-expecting input on the SDHC card normally doesn’t do the card any good.
      Cheers,
      Darren.

      • dunedon

        I think his issue was that the Uno HAS a 3.3V output (it’s right above the 5V output) … so why are you not just using that directly?

        • http://darrenyates.com.au Darren Yates

          Dunedon, you’re missing the point – it’s not just the voltage level of the card module. The card module has to interface with the Arduino board. The board runs at 5V; the card at 3.3V. Feeding the module with 3.3V from the Arduino doesn’t change the fact that the Arduino I/O logic levels swing between 0V and 5V while the card is only 0V to 3.3V. This doesn’t change simply because you supply 3.3V from the Arduino.
          Cheers,
          Darren.

  • javier

    does the sketch need to be modified?

  • http://darrenyates.com.au Darren Yates

    Modified for what?

  • muhammad zulqarnain

    hi, i’m sorry for asking, how do we generated the pwm like the picture
    you show using the coding on arduino. the changealbe duty cycle. sorry
    if i’m asking to much. because if the normal one i think i can do it. tq

  • Sidney

    Is there a circuit diagram for the network version? I am finding it hard to follow from the picture

    • http://darrenyates.com.au Darren Yates

      Use the circuit diagram shown, but ignore everything in the box ‘not required if using the ethernet shield instead’.
      Cheers,
      Darren.

      • Sidney

        Sorry, this is my first project so I may be a little slow on the uptake. I meant the other kind of drawing, where I can see how its plugged in on the breadboard.

        Also, is there a way to make a box for this project? Maybe something custom printed to the right sizes or is there a site with off the shelf ones (as in your example?)

        Thank you,

        Sidney

  • willi

    I hve installed InstallWavConverter.reg but it dosn’t work.
    The Command Prompt screen appears and disappears but nothing else happend.
    Me OS ist Windows 7 prof. 64 bit.

    • http://darrenyates.com.au Darren Yates

      Have you followed the instructions eg. copied the folder to your C: drive? You need to copy the inner folder to the root of your C: drive. What’s happening sounds like the ffmpeg converter cannot be found, likely because of this.
      Cheers,
      Darren.

      • willi

        That was the reason. now it works.
        Thank you!

  • willi

    Sorry for another question:
    The Soft- and Hardware works now, but the sound is chopped.
    Do you know a reason?

    • willi

      The Sound is overlaid with rattle, interrupted.
      plaese excuse my bad english.

      • http://darrenyates.com.au Darren Yates

        Been a while since I wrote the software but check to see if there is a option to encode with a lower sample rate or bit rate. If you’ve built the basic circuit, you can only use 8-bit audio.

        • willi

          Iam using the hardware above: Arduino Uno and an Ethernetshield with an 8GB-SynDisc SD-Card

          • willi

            Plese give me your mail-adress and I send you a short WMA-File with the sound.

  • http://darrenyates.com.au Darren Yates

    Not sure what you mean – can you be more specific?

    • willi

      Another fact: the D13-LED is flickering, is this correct?

      • http://darrenyates.com.au Darren Yates

        IIRC, it flickers when retrieving data from the card.

  • Saúl Valencia

    i’m a bit confused, i used the first method with the diodes and the 2$ shield, then i changed the diodes for a buffer a resistors, but either way it didn’t work, nothing happened, evend e red led didn’t turn n at all, i’ve checked more than twice and i don’t see my error, is it possible that the sd shield is defective?, i just bought it today and i haven’t tested it before, do you know how?, by the way, i was using a 74hc244 as buffer instead of the 4050, because it’s all i had, but the buffer is tested.

    • Saúl Valencia

      hi again, well i went to my local store and found a 74hc4050, it worked just fine instead of the diodes, but there is a problem, the volume level is very very low, i had to use a pair of cheap headphones and still very low, when i used a speaker, it barely sound, but in both cases it was without noise.
      Later, i added a amp circuit based on the lm386, i have tested it many time and works as it shoul, but when i connect it to you proyect there is noise when no playing any file, really awfull, i can’t find the problem, could you help?, bye

      • http://darrenyates.com.au Darren Yates

        Well, the reason the output is low is because the output isn’t designed to drive a speaker. Just because there’s an audio output doesn’t mean you can connect it straight to a speaker. That output is what’s called ‘high impedance’ – it is a low-power, low-signal-level output. It’s designed to be fed to an audio amplifier. (This was mentioned in the story – please re-read. Thanks).
        Cheers,
        Darren.

  • http://www.angelsys.com.br Marcos Kotona

    dear sirs.
    Step 2 is not working with me.
    i did all you explain, but
    You’ll see a Command Prompt screen appear briefly and when it disappears you’ll have a new WAV file in the original file’s location. You can even select multiple files to encode all at once.
    but the NEW WAV file looks the same, seens nothing happened. I run ino program, but erro msg about wav file is showed

    please help me

  • http://www.angelsys.com.br Marcos Kotona

    Sirs,
    is there a WAY to Know whem the play WAV filnish? when the music stoped???
    i want to make a LOOP, one unique music playing all the time
    could you help me?
    regards

  • Gonzalo Muñoz Rojas

    Hi, I´m using arduino mega + shield ethernet also i use your libraries but the circuit does not work…. please give advice about this problem

    PD: Sorry for my bad english

  • Harrison Walker

    How do you connect it to a circuit that when the button is pressed, an LED turns on?