We're going to make a WAV player! (If you're not familiar, a WAV is an uncompressed audio file). We're going to build it with an Arduino and the AD5330 breakout board, an 8-bit DAC. WAV files are uncompressed and the Arduino doesn't have too much internal ROM so we'll have to store the WAV files on an SD card. This means we'll also add the microSD shield to the project.
A DAC is a Digital to Analog Converter. Basically a DAC takes a digital value (think 1's and 0's) supplied by a microcontroller and turns it into a corresponding analog voltage. An 8-bit DAC means that the DAC has 8 pins on which to set the digital value. Remember, an 8 bit value can be any number between 0 and 255. We will power the DAC with 3.3 Volts. By using an Arduino with the DAC we will be able to create 256 distinct voltages between 0 and 3.3V by providing 8 bits via digital output pins on the Arduino. By creating different voltages on a set frequency we can create sound!
In this tutorial we'll cover how to attach the microSD shield to the Arduino platform, and how to connect the AD5330 breakout board to the shield. After connecting all of the pieces together we'll look at some code to get WAV files playing from the SD card.
Geez that's a whole lot of stuff we've got. Connecting all the pieces won't be very hard, but it will take some soldering! So what all do we need to do? Well for starters the microSD shield needs to go on top of the Arduino. Start by soldering the 6 and 8 pin stackable headers onto the shield. Make sure that the male ends are pointing down away from the components on the shield.
Now the shield can be placed on top of the Arduino.
Let's move on to the AD5330 breakout board. In order to connect this to the shield and the speaker we'll need to place the breakout board onto a breadboard, but first we'll have to solder some headers onto the breakout board. Solder breakaway male headers to the breakout board; make sure the pins are facing away from the components on top of the board.
Now you can put the AD5330 into the breadboard
Alright, with those two things taken care of we can get to wiring the project up. Things get a little messy here so use care while wiring all of these signals. You'll need 17 jumper wires to wire everything from the microSD shield to the AD5330 breakout board. The table below shows the pins that need to be connected. For each connection plug a jumper wire from the female header on the microSD shield to row on the breadboard that aligns with the specified pin name.
microSD Shield Pin Number
|AD5330 Pin Name
|An. In 0
|An. In 1
|An. In 2
|An. In 3
|An. In 4
Double check all of your wiring. With this many wires it's very easy to misplace one or two of them; if that happens the whole circuit may not work once you upload some code. Debugging the entire project then becomes an exercise in frustration. Trust me, it's better to just double check the wiring now and make sure you've wired the project up properly. Now that the microSD shield is wired up to the AD5330 breakout board we're almost finished. The whole point of the project, though, is to play some music. The missing piece is glaringly obvious; we still need to throw a speaker on there! You might be tempted to just attach the speaker to the VOUT pin of the AD5330, but unfortunately that won't cut it. In order to create sound the voltage must be AC coupled. It may sound complicated, but really all it means is that we need to put a capacitor between the VOUT pin and the speaker. Place the positive lead of a 10uF Capacitor in the VOUT row of the breadboard and put the other end of the capacitor onto the positive terminal of the speaker. Connect the negative terminal of the speaker to the GND pin of the AD5330 breakout board. (If your speaker didn't come with wires soldered onto the terminal you'll have to add them yourself.)
Now on to the fun stuff! Download the two zip files from the Code Downloads section at the top of the tutorial. The first zip file contains an Arduino Library for the AD5330. Unzip this in the \hardware\libraries directory of your Arduino directory. The library contains two example sketches: a tone sketch and a 'WAV files from SD' sketch. The first sketch just produces a single tone on the speaker while the second set will retrieve WAV files from the SD card and play them.
The second download, the C code, is actually the same program as the second Arduino sketch; however this code is written in plain old C. There are many things I love about Arduino, but sometimes you just need some extra speed and power and it's hard to get around this in the Arduino IDE. Using C gives you some extra room to push data a bit faster. We'll talk about this some more later.
Let's get started looking at the code. Open the first sketch, the AD5330_Tone sketch. After you've unzipped the folder in the Arduino directory open the Arduino IDE. Go to File->Examples->AD5330 and select AD5330_Tone. Check out the sketch a bit before you load it. It's simple enough to figure out without digging too much. After defining the pin locations we set all of the pins on the Arduino as outputs. I used the datasheet to find out how to configure all of the inputs to the AD5330. After setting the initial values of all of the pins we're off to the 'Loop' code. To create a tone we need to send a sound wave to the AD5330. To send a sound wave to the AD5330 all we need to do is set a value on the DB0-DB7 pins, clock them into the module and delay, then set the DB0-DB7 pins to zero, clock the new data in and delay again. If this procedure is repeated over and over again the tone that's generated will be directly related to the delay. The shorter the delay time, the higher the tone will be; the longer the delay the lower the tone will be. Check out the graphic representation below of how a digital wave is represented.
Set the board to Arduino Duemilanove w/ 328 and compile the code. After you load the code to your Arduino you should hear a sound coming out of the speaker. If you don't you need to go back and double check all of your wiring. Play with the FREQ and VOL values to see how they affect the tone and volume of the generated sound. If the code doesn't compile and gives you errors related to pre-existing files it may be because you already have a FAT library installed. If this is the case the FAT library will have to be temporarily removed while using this code.
That was neat, and produced a pretty nice sound, but we can do that with 1 pin very easily. I want to play some music on this thing! I decided I wanted to play 8 bit WAV files, pretty much because it would take the least amount of work. WAV file are uncompressed so the data manipulation wouldn't be a concern; and 8-bits, well, duh... For some reason the first thing I thought of after hearing 8-bit DAC was the theme song to Mario Bros. So I got on the Internets and started searching for some Mario WAV files. Wasn't too hard. The first files I grabbed happened to have a sampling rate of 22 kHz. So with this in mind I'd settled several issues: the sample width and the sample rate. Our WAV player is going to play 8 bit WAV files with a sampling rate of 22 kHz. If you put any other kind of formatted WAV file on this it may still play, but it won't sound very good!
Open the Arduino sketch from the AD5330 library named AD5330_SD_WAV_Playback. You'll see that several files are now included so the sketch can use FAT16. Some of the code at the beginning of the sketch will look familiar; the Setup section of the code is actually the same! But there's also some more advanced stuff going on. When playing audio files it's pretty important that we update the data at the correct rate; never faster or slower than our sample rate of 22 kHz. In order to do this an Interrupt Routine was created. The interrupt will stop the 'Loop' code no matter what it's doing and update the data on the AD5330. This means that we can be sure that we're sending sound consistently at 22 kHz. The code for the interrupt routine is inserted between the Setup and Loop sections of the code.
The 'Loop' section of the code is commented pretty well. Here's a basic run down of what's going on:
Sounds pretty easy huh? It's actually not that bad once you get used to using the FAT16 functions. By the way we didn't talk about why we actually need an SD card for this. Unfortunately the ATmega328 only has 2 kB of EEPROM. This isn't nearly enough to hold a WAV file, so we added the SD card for some external memory.
Once you read through the sketch go ahead and compile it. Make sure the Arduino Duemilanove w/ 328 is selected as your board and then load it up. Format your SD card for FAT16, then load some 8 bit WAV files onto the card. Any audio file can be converted into an 8bit WAV file; there are some instructions at the end of this tutorial on how to convert an audio file using iTunes. Once you've got the WAV files onto the SD card put the SD card into the shield. Reset the Arduino and the Arduino should start playing the files. If nothing happens there are a few things you need to check: first double check your wiring; then make sure you've loaded 8-bit WAV single channel 22kHz WAV files. Any other format could cause the project to be upset :(.
After the initial "Wow that's cool!" wears off, the first thing that will probably come to your mind is "huh, this sounds like crap." Well, yes, it does. There's a couple of things to consider:
Look, I'm the first to admit that I'm an Arduino junkie. I love how easy it is to set up, and that I know there's nothing wrong with the hardware. I really like how easy it is to get sensors up and running. But there are some shortfalls with the compilation process and I often find that I have to move over to C in order to really maximize the power of the ATmega328 microprocessor.
Download the second zip file to get the C code for this project. The code is actually exactly the same, but the digitalWrite functions are replaced with direct register access to make writing to the pins much faster. One of my favorite things about the Arduino platform is the serial bootloader. A not-so-little known secret about the Arduino hardware is the regular hex files (perhaps compiled using WinAVR) can be uploaded using the serial bootloader. See this tutorial for more help on the subject. What this means is that I can write better, more efficient code in C but still take advantage of the Arduino hardware platform. And that's exactly what's been done in the second zip file.
Once you've downloaded the zip file with the C code feel free to check out the source. You'll notice that it is strikingly familiar to the Arduino sketch that plays songs from the SD card. All that's left to do is load the hex file onto the Arduino. You should hear the difference between the 'C' version and the 'Sketch' version of the code immediately. It's still not high quality audio, but it's a much more clear and crisp sound.
Google '8-bit WAV converter' and bunch of free software applications will show up right away. You may even have your own program or script that will make this conversion for you. However since most people are at least familiar with iTunes we'll create a WAV file in that program that's compatible with our firmware.
I use Windows so I apologize to all you Mac and Linux users. Please help others with some recommendations inside the comments below the tutorial page. Start up the iTunes application; once it's opened up click on the Edit menu and select Preferences.
In the 'General' Tab of the Preferences Window click on 'Import Settings.' Select WAV Encoder from the 'Import Using' drop-down menu and then select 'Custom...' from the 'Setting' drop-down menu. In the WAV Encoder window, choose 22.050kHz Sample Rate, 8-bit Sample Size and Mono Channels. Click OK in the WAV Encoder window, the Import Settings window and the Preferences window to save your settings
Now whenever you import a song to your iTunes Library it will be imported with these settings. You can grab the imported file from the iTunes Library directory and put it on the SD card for your WAV player. Remember to change this setting back to the original format for your regularl music imports or you won't be impressed with the audio quality!
One way to double check the files attributes is to right click the WAV file in the directory and select 'properties.' In the summary tab all of the audio properties will be listed, just double check to make sure that the sample rate is 22 kHz, the sample size is 8-bit, it's a 1 channel file, and the audio format is PCM. As long as your WAV file has these properties it can be loaded onto the SD card and played by the WAV player.
And that's it! Hopefully you learned a bit from this tutorial. Feel free to comment on any errors you find and post any improvements you make. Good luck!