DAC is short for Digital to Analog Converter. In this article we play around the code Michael Smith created for a PWM based DAC. I modified his code so that other DAC options could be tried. I compare the 8-Bit PWM DAC with the R2R DAC at various numbers of bits. You might be surprised at how well a 4-bit DAC sounds. This article includes several sound samples for the various DAC options and demonstrates some software abstraction that allows for multiple DAC options.
This article is part of the series on Arduino Sound Generation. I decided to drop the Part 1, 2, 3 distinction as much of the content is not dependent on the previous articles.
- Using PWM to do sound Link
- Using timer interrupts Link
- Playing a Melody Link
- Getting ready for sound projects Link
- Creating sound, what are the options? Link
Of all the various methods of sound generation the DAC method seems most versatile to me. As mentioned before DAC is a common short name for Digital to Analog Converter. Basically a binary/digital value is converted to an analog/voltage value. An 8-Bit DAC would convert a binary value in the range of 0 to 255 into an analog voltage from 0 to 5V. The exact voltage range of the conversion is dependent on the DAC configuration but for most things we will play with, 0 to 5V will work.
DAC Biasing for +/- swing
Since analog signals, especially sound, needs to swing plus and minus around 0V we often bias the DAC so that mid scale is considered 0V. If the DAC outputs from 0 to 5V then we usually bias the signals so that 2.5V is translated to 0V. If we generate our output signals so that half scale is 2.5V then we can AC couple the output to get a +/- 2.5V swing.
The half scale biasing may be a bit confusing but really it’s easy once you get the general idea. We just call 1/2 scale zero so that any numbers above 1/2 are positive and below are negative. For an 8 bit converter we can use the MSB as a sign bit to make this happen. Consider that decimal 128 is 10000000 in binary. Note that the MSB is set and this is basically half scale of the possible 0-255 range. Think of the MSB as a sign bit, it’s one for positive values and 0 or negative.
Using this 1/2 scale bias we can convert any digital number that might represent sound data into a value to load into a DAC. The first step is to convert the number into the range of +/-127 and add 128 to it. In this example that will make the analog version swing from 0 to 5V with the original zero point set at 2.5V. We can remove that 2.5V bias in the hardware with a simple series capacitor.
The series capacitor is not even needed in most applications. For example I use my sound card line input to do these experiments. This input has a series capacitor. The series capacitor is used to provide A/C coupling. This just means that the signal swings evenly around 0V. The +/- voltage swing is enforced about the average DC level by the capacitor. Of course there is a frequency response for the series capacitor but the value of the capacitor is usually high enough so that it will not be a problem for audio frequency ranges.
Filtering the DAC output
This diagram shows the circuit I used between the various DAC outputs and my PC sound card input. The series resistor and capacitor to ground form a simple filter to knock off the high frequency noise caused by the DAC switching instantly between the voltage values. It removes the high frequency components. The 100K variable resistor (POT) lets me adjust the output voltage level for each DAC. A line input should be kept in the 1V Peak to Peak range or +0.5 to -0.5 range. Since the sound card has A/C coupling I only need to adjust the amplitude using this POT as a voltage divider. Also note that I connected both the right and left side inputs to the filtered output.
There is no additional parts required to implement the PWM sound output. Michael Smith’s PWM code generates PWM at about 60KHz. This high frequency is easily filtered with the filter described above. You really don’t even have to have this filter as the sound card has input filters. Even if you wanted to drive a speaker, you would not need to filter this as the speaker would filter it. It simply can not respond to the 60KHz.
The fact that very little to no external circuitry is needed for PWM sound generation makes this a very good option for microcontroller projects. PWM sound is also called PCM or pulse code modulation. PCM has the added benefit of being very easy to make powerful amplifiers for it. You should be able to generate high quality sound at high volumes using a simple class C audio amplifier and some simple filtering. I hope to demonstrate this in a future article.
Here is a sample of Michael Smith’s PWM sound output from an Arduino. The first file is with the filter circuit described above. The second is unfiltered except for what the sound card does on it’s line input. Compare this with the 6-Bit R2R DAC described later. The graphic shows the wave shape captured with Audacity.
Michael Smith’s sound program uses a sound sample that is very broad spectrum. This makes it very good for testing DAC configurations and playing with sampling rates. The graphic below shows the spectrum plot for the sound file above. This plot was also done in Audacity using the unfiltered 6-Bit R2R DAC sample.
R2R DAC Output
Wikipedia has a great article about R2R ladders so I don’t need to cover it in a lot of detail. The diagram here shows my 6-Bit R2R DAC circuit. As you can see I chose 10K as my R value making the 2R 20K. The basic idea is that the R2R ladder is a voltage divider where each resistor either pulls up or down on the output resistor. DAC chips use a similar method with current sources internally to do the digital to analog conversion.
Remember that this type of DAC has an output impedance of 10K or the value of R for the R2R network. This means it can not drive loads. For these experiments, driving the sound card link input, did not require a buffer.
I modified Michael’s code so that I could try out other DAC configurations. I created a SetDAC(int value) method that would be called in the sample output ISR routine. This way I could simply change that function to use a different DAC.
With the new SetDAC function called from the ISR I created two versions, one that used the PWM and one that used the 6-Bit R2R DAC. I actually set up the ISR to call both SetDAC methods so I could easily switch between the two and hear the differences. I also tried several different bit configurations. Listen to the sound samples below for 6, 4, 2, and even 1 bit resolution. I was surprised at how well the 4-bit DAC sounded. Even with a single bit DAC you can hear the sound. I wonder how well a sampled voice would sound with a single bit.
These sample include both a filtered and unfiltered version. If you look at the waveform in Audacity or other sound editor program you will see the flat sample points for the lower resolution DAC configurations.
This plot below shows the 4-Bit R2R DAC waveform in Audacity. Note the downward slope you see on each flat section where the DAC value stayed constant for a brief time. This is actually caused by the A/C coupling of the line input. These areas are flat on a regular oscilloscope.
As a test I placed the 8-Bit PWM and 6-Bit R2R DAC outputs on my O-Scope and set one to invert and add. The two waveforms were nearly identical. I think the two sound the same as well.
I want to do some stereo sound experiments and I think the 4-Bit DAC might be good enough for most of my experiments. Two 4-Bit DAC channels can be done with a single 8 bit port which leaves other I/O pins available for control.
After all these experiments I believe it’s safe to say that we can do sound generation on the Arduino. I plan to show some sampling techniques in the next article which will provide nice audio tones we can use to play music.
Source Code: SpeakerPCM.zip
- Interfacing the dual 8-Bit DAC from my AVR O-Scope Clock.
- Generating a pure sin wave output from a sin table.
- Using a phase accumulator method to control the output sample rate.
- Using the phase accumulator method to play music.
- Playing notes via MIDI commands.
- Using the phase accumulator method to change the frequency of sampled sounds.
- Trying sampled sounds that include spoken words.
- Stereo outputs.
- Doing phase/delay experiments with the Stereo outputs.
- Building a simple power amp output for the PWM output.
- Did I miss something about the R2R or PWM DAC options?
- An experiment to try?
- Suggestions for future articles?
- How would you use sound output in a project?
- Errors or typos?