IMG_0122 copy.jpg
Generate sound or output analog voltages with an Arduino.  This Instructable will show you how to set up a really basic digital to analog converter so you can start generating analog waves of all shapes and sizes from a few digital pins on an Arduino.  (This article is a companion to another Instructable I've written about sending audio into an Arduino, find that here)

Some ideas that come to mind:

sample based instrument- store samples on the Arduino or on an SD card and trigger playback with buttons or other types of controls.  Check out my Arduino drum sampler for an idea of how to get started.
digital synthesizer- make saw, sine, triangle, pulse, or arbitrary waveshapes- check out my waveform generator to get started
MIDI to control voltage module/ MIDI synthesizer- receive MIDI messages and translate them into a voltage so you can control an analog synthesizer with MIDI, or use the MIDI data to output audio of a certain frequency
analog output- you may find yourself needing to generate analog voltages from your Arduino at some point, maybe to communicate with an analog device
effects box/digital signal processing- in combination with a microphone/audio input you can perform all kinds of digital signal manipulations and send the processed audio out to speakers.  Check out my vocal effects box for an example. 
audio playback device- make your own ipod.  With the addition of an SD shield you could create your own Arduino mp3 player (check out the wave shield documentation for an idea of how to get started with the code).  The circuits and code provided here are compatible with SD shields that communicate via SPI.

Feel free to use any of the info here to put together an amazing project for the DIY Audio Contest!  We're giving away an HDTV, some DSLR cameras, and tons of other great stuff!  The contest closes Nov 26.

Parts List:

(x9) 1/4 Watt 20kOhm Resistors Digikey 0KQBK-ND
(x7) 1/4 Watt 10kOhm Resistors Digiikey CF14JT10K0CT-ND
(x2) TS922IN Digikey 497-3049-5-ND I like these because they can be powered off the Arduino's 5V supply (one 924 works too, but they don't seem to be available on digikey at the moment)
(x1) 10kOhm potentiometer linear Digikey 987-1308-ND
(x1) 0.01uF capacitor Digikey 445-5252-ND
(x1) 220uF capacitor Digikey P5183-ND
(x1) 0.1uF capacitor Digikey 445-5303-ND
(x1) 1/4 Watt 3kOhm Resistor Digikey CF14JT3K00CT-ND
(x1) 1/4 Watt 10Ohm Resistor Digikey CF14JT10R0CT-ND
(x1) Arduino Uno Sparkfun DEV-09950

Additional Materials:
22 Gauge Wire
solder
 
Remove these adsRemove these ads by Signing Up

Step 1: Digital to Analog Converter

IMG_0126 copy.jpg
r2r.jpg
schematic audio out arduino.jpg
DAC stands for "digital to analog converter."  Since the Arduino does not have analog out capabilities, we need to use a DAC to convert digital data (numbers/ints/bytes) to an analog waveform (oscillating voltage).  A simple, easy to program, and cheap way to do this is to use something called an R2R resistor ladder.  Essentially, it takes incoming digital bits (0V and 5V from Arduino), weights them, and sums them to produce a voltage between 0 and 5 volts (see the schematic in fig 2, taken from the Wikipedia resistor ladder page).  You can think of a resistor ladder as a multi-leveled voltage divider

The resistor ladder I'll be demonstrating in this tutorial is an 8-bit DAC, this means it can produce 256 (2^8) different voltage levels between 0 and 5v.  I connected each of digital pins 0-7 to each of the 8 junctions in my 8 bit DAC (shown in figs 1 and 3).

You can also use an external DAC chip to perform digital to analog conversion.  These chips receive digital serial data from the Arduino and output a voltage.  If you are short on digital I/O pins or if you want higher fidelity digital to analog conversion, a DAC chip may be a good solution for you.  I like to use the R2R ladder because it's easily sourced (you probably already have all the resistors), cheap, easy to address in the Arduino code, fast, and it does a surprisingly good job for what it is.  There seems to be kind of a misconception abut 8 bit audio- that it always has to sound like the sounds effects from a Mario game- but 8bit audio with this really basic DAC can actually replicate the sounds of people's voices and instruments really well, I'm always amazed at the quality of sound that can come from a bunch of resistors.
faziefazie says: Apr 14, 2013. 5:10 AM
can I using this mono jack instead of yours?
mono_jacks.jpg
amandaghassaei (author) in reply to faziefazieApr 14, 2013. 11:48 AM
sure
sparxxer says: Apr 6, 2013. 11:22 AM
Hi, thx for your awesome work! I have two questions: Shouldnt you refer to CS01 in the line TCCR0B |= (1 << CS11) when dealing with Timer/Counter0? And why does this code not work when im trying to use Timer 1 like this

TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 49;
TCCR1A |= (1 << WGM11);
TCCR1B |= (1 << CS11);
TIMSK1 |= (1 << OCIE1A);

and changing the ISR to ISR(TIMER1_COMPA_vect) ?

amandaghassaei (author) in reply to sparxxerApr 6, 2013. 1:54 PM
http://www.instructables.com/id/Arduino-Timer-Interrupts/
which code are you talking about? which step?
dcoutts says: Feb 26, 2013. 3:09 AM
Just breadboarded this. It's neat and easy!
amandaghassaei (author) in reply to dcouttsMar 28, 2013. 11:03 PM
awesome!
samurai_gui says: Jan 20, 2013. 9:34 PM
hello Amanda, how are you?
I want to use your project as a basis for my midi guitar. Where do i plug my oscilloscope probe to see if the signal is now digital?
amandaghassaei (author) in reply to samurai_guiFeb 4, 2013. 11:21 PM
hook up your oscilloscope to the opposite side of the 20k resistor attached to arduino pin 8.
gargoor says: Dec 19, 2012. 6:30 AM
if i use another DAC chip , will i be able to use arduino to program it ?
mtorquato says: Nov 5, 2012. 12:53 PM
As said in my last comment, i'm trying to do the input/output project together.
How can i do to play in the output (speaker) my voice with a delay?
Like a 3sec ou 5sec delay...
I don't know how to do it in arduino.
amandaghassaei (author) in reply to mtorquatoNov 5, 2012. 2:32 PM
you'll have to use an sd card for extra memory if you want to do a delay that long. The Arduino doesn't have too much memory unfortunately. This is a bit of an advanced project. I'd recommend starting with the no delay code here, getting that to work, and then moving on to sd card (probably with an sd card shield).
amandaghassaei (author) in reply to amandaghassaeiDec 6, 2012. 12:22 PM
check out the comment valcarrara left
valcarrara says: Dec 6, 2012. 11:25 AM
I had the same problem of mtorquato: to generate 2 to 3 seconds delay in the arduino with a sampling rate of 44100 Hz. This means roughly 120 kbytes for a 8 bit AD convertion or 240 kbytes if more than 8 bits was chosen. However a sd card is not a solution, as amandaghassaei suggests, since the large number of R/W cycles in the sd card blows it with no time. A RAM card should work if you manage to find someone that provides it. I didn’t.
amandaghassaei (author) in reply to valcarraraDec 6, 2012. 12:22 PM
thanks for the info, I did not know that.
Panichou says: Nov 9, 2012. 2:15 PM
Hi !
I want to do a digital low pass filtering before putting the signal in the DAC.
I am not quite sur how to handle it in arduino.

Since the most simple form of a low pass filter is
T*ds/dt+s(t)=K*e(t) e : signal to process
s : output signal
T : Time constant
K : Gain filter
I was thinking about doing something like :

int incoming;
void setup(){}
void loop()
{ e = analogRead(A0);
for (byte j=0; j { s[j+Δt] = K*e[j]*Δt/T + s[j](1-Δt/T) }
}

Δt is the sampling rate
But how can I define the upper limit ( N ), since the arduino is constantly reading value from A0 ?

Thanks
amandaghassaei (author) in reply to PanichouNov 9, 2012. 5:38 PM
hmm, I'm not sure I'm totally following you. can you explain the equation a little more? have you tried this code and looked at it on an oscilloscope? low pass filtering is essentially lowering the slew rate of your signal, so it seems like a good strategy might be to scale down the change in voltage per unit time, and make it so that large changes in voltage over short periods of time are dampened more than small changes. That would have the effect of rounding out sharp corners, which is essentially what low pass filtering is.

this is what I'm thinking:

lastOutput = output;//record the last thing you output
incoming = analogRead(A0);//get new value
output = lastOutput + (1-c*(abs(incoming-lastOutput))*(incoming-lastOutput);//where 0<=c*(abs(incoming-lastOutput))<1
PORTD = output;//send to DAC

not sure if this is quite it, just an idea off the top of my head, but some really interesting ideas here, I may have to experiments with it a little myself... let me know how it works out!
Panichou in reply to amandaghassaeiNov 10, 2012. 4:28 PM
I will try but I would also want to get what the code is about : )
I don't understand the line :
output = lastOutput + (1-c*(abs(incoming-lastOutput))*(incoming-lastOutput) ;
How did you come up with it ?
And how is this changing the slew rate ?
Panichou in reply to amandaghassaeiNov 10, 2012. 4:10 PM
Explain the equation ? Like how i get to the differential equation to the code or the differential equation itself ?
amandaghassaei (author) in reply to PanichouNov 11, 2012. 12:32 PM
I thought about it a little more, I think what I wrote before is overly complicated, so I'll propose something new. Here is an article on wikipedia that talks about algorithmic implementation of lp filters:
http://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation
basically you would have:

lastOutput = output;//record the last thing you output
incoming = analogRead(A0);//get new value
output = lastOutput + c*(incoming-lastOutput);//where 0PORTD = output;//send to DAC

does it make sense how I got this from the wiki article? specifically from this part:
"for i from 1 to n
y[i] := y[i-1] + α * (x[i] - y[i-1])"

as for the slew rate stuff, the slew rate is the maximum change in voltage over time of a component. So if you put a pulse signal into a component, you can measure the slew by looking at how long it took the component to output the change in voltage. low pass filtering relates to slew rate because the effect of a low pass filter is to slow down the rate of change of a signal (dv/dt). it;s a little different than slew bc slew often only effects the max dv/dt, anything under this max is unaffected, but filter effects all dV/dt, but dampens higher dv/dt more. does that make sense?

this pic might help:
http://en.wikipedia.org/w/index.php?title=File:Slew-rate.svg&page=1
this is the effect of low slew rate on a pulse, with lp filtering the output would follow the same general shape, but will have exponential curves in its transitions:
http://en.wikipedia.org/wiki/File:Raised-cosine-filter.png
Panichou in reply to amandaghassaeiNov 13, 2012. 8:55 AM
Okay. I am still trying to figure out the whole "slew rate" thing ( I'll ask my teacher to explain to me ) but I get the code. Actually what I wroted was shaped around the same idea, but it makes it a lost simpler to use the constant α !
I'll try the code within the next couple of weeks. I will keep you in the loop !

Thank you SO much again.
amandaghassaei (author) in reply to PanichouNov 13, 2012. 10:08 AM
basically there are two ways of thinking about low pass filters:

-frequency response- they cut out the higher frequency components of a signal- this is a much more analytical approach, but it is very hard to implement in code, as it requires an fft of the signal
-waveshaping- they smooth out large changes in dv/dt. This way of thinking about low pass filtering makes them much simpler to implement in your code because you only need to store two data points and do some simple math to get the slope

yes I'm really interested to hear the result, definitely keep me posted!
good luck!
amandaghassaei (author) in reply to amandaghassaeiNov 11, 2012. 12:37 PM
sorry the formatting got screwed up, it should read:

lastOutput = output;//record the last thing you output
incoming = analogRead(A0);//get new value
output = lastOutput + c*(incoming-lastOutput);//where c is between 1 and 0
PORTD = output;//send to DAC
mtorquato says: Oct 31, 2012. 4:21 PM
I have some doubts about this Instructable: 1 - I can't find tu buy a 20K resistor. Is there any problem if i use a 22K resistor in R2R resistor ladder? Can i solve this with another way? 2 - I'm new with Arduino, so i don't know how to code it to output my voice (Digital->Analog)
PS: I'm trying to do the Input and output Instructables togheter, in other words: Talk on the mic->ADC->DAC->Speakers.

Can someone help-me with this?

Thanks
amandaghassaei (author) in reply to mtorquatoOct 31, 2012. 4:36 PM
here's a digikey link for 20k resistors.
22k will be ok for testing purposes, but when you solder this together I'd recommend getting the 20k. If you read my Arduino Audio Input tutorial you can get some info about how to set up the mic input circuit.  The code for mic->ADC->DAC->speakers is at the bottom of step 6 of my audio input tutorial: here.

hope that helps you get started!
skrubol says: Oct 5, 2012. 10:49 AM
You should really use 1% tolerance or better resistors. Effectively you've only got 5-6 bits of precision with 5%, and about 7 bits with 1%.
amandaghassaei (author) in reply to skrubolOct 5, 2012. 11:06 AM
thanks, this is a good point that I forgot to address in my post, as you increase the number of bits in your R2R DAC, the tolerance of your resistors becomes important. If you are very concerned with getting true 8 bit out of this DAC then you should definitely get 1% tolerance and you might even think about hand matching them.
Personally, I never really bother with this, I guess the 8-bit R2R DAC is fun for me because it's such a lo-fi solution for generating audio, so I don't worry too much about making it perfect. I kind of accept that each one just ends up with its own unique idiosyncrasies. If I wanted to make a better 8 bit DAC I'd probably opt for a dedicated IC rather than bother with matching resistors. There are plenty of 8 bit parallel input DACs available that would work great with this tutorial and code.
thanks for the comment, that was really helpful!
cefn says: Oct 5, 2012. 8:13 AM
Can anyone help guide me to select a cheap quad op-amp suitable for this project from Tayda? This page is a good place to start, but I may have made too narrow a search...
http://www.taydaelectronics.com/catalogsearch/result/?q=operational+amplifier+quad+pdip

The aim is to replace the TS924IN, which I'm getting quoted at about £1.59

I'm running a project to 'standardise' a breadboard and stripboard layout for use in an educational context, and audio output (especially with a resistor ladder) would be a brilliant project. However, the one Op-Amp IC you've chosen almost doubles the cost of this as a kit!

Finding something which would be adequate from Tayda's stock would be really handy. Hope someone knows more about reading data sheets than I do.
amandaghassaei (author) in reply to cefnOct 5, 2012. 8:27 AM
tl074/084 are fine for the buffer circuits, but they won't be able to source enough current to drive any kind of load, and you'll need and +V and -V supply for these instead of just +5. You'll need something with higher output current to drive speakers directly.
cefn in reply to amandaghassaeiOct 5, 2012. 9:27 AM
I wondered if the component at...
http://www.taydaelectronics.com/tlc274-quad-operational-amplifier-precision-pdip-14-tlc274cn.html
with datasheet...
http://pdf1.alldatasheet.com/datasheet-pdf/view/28886/TI/TLC274CN.html
...might be able to cope, although the need for a negative rail I'm not totally clear on. I appreciate it's more limited at 45mA total (30mA per channel) but more in the ballpark.

Do you think it's possible to set up a circuit with a TLC274CN across 6V (4xAA) giving -3V and +3V which seems a good enough voltage to drive an ATMEGA328-PU as well. Would certainly be quiet, but maybe good enough for a short sample to be played as part of an electronic game, and could add a battery-boosted speaker.

Does this make any sense?
jstarkmuth says: Oct 4, 2012. 6:49 AM
The misconception regarding "8-bit audio" is due to the fact that the term "8-bit sound" or "8-bit music" refers to music created by computers of the 8-bit era, which does not necessarily mean that the audio of those computers had 8-bit resolution. "8-bit" just refers to the CPU architecture of that time. Computer sound of that era often was more or less "1-bit", i.e. just rectangle wave beeps created by turning the output on and off perdiodically. The SID chip of the Commodore 64 (which is the peak of the "8-bit sound" era), changed that by providing real wave forms and filters.
carlmal in reply to jstarkmuthOct 4, 2012. 10:14 PM
Correction: 8 bit audio has a sample width of 8 bits. 12 bit audio is 12 bits, 24 bit audio is 24 bit samples.

Higher sample rates allow more resolution in regards to amplitude which directly translates into more dynamic range. Let's not confuse things here.

If Amanda is synth'ing/decoding 8 bit samples, it is 8 bit audio period. 8 bit gave digital audio a bad name in the early days account its grainy sound. 16 bit/44.1kHz is red book CD quality. Most modern audio interfaces allow 24 bit with 44.1-96kHz sample rates.

Most DSP is done internally at 32 bit allowing additional headroom and reducing the artifacts caused by floating point rounding errors
jstarkmuth in reply to carlmalOct 5, 2012. 12:16 AM
carlmal, everything you wrote is correct, but not a contradiction to my comment. I was just pointing out that the term "8-bit" in a musical context not always refers to 8-bit audio as you explained it, but sometimes to music from the "8-bit era" in general. That kind of music (which sounds like Nintendo etc.) is also referred to as "chiptunes". And that association might erroneously contribute to the bad reputation of 8-bit audio, besides the fact that, of course, 8-bit audio is audibly worse than CD quality (but not as worse as some people think).
amandaghassaei (author) in reply to jstarkmuthOct 5, 2012. 1:42 AM
yes I agree, the kind of stuff that people usually give the label "8-bit" is really 1-bit.
amandaghassaei (author) in reply to jstarkmuthOct 4, 2012. 9:31 AM
you're right, thanks for that explanation
treefingers 10 says: Oct 4, 2012. 8:04 AM
Well explained and well presented! Brings me back to EE classes with op amps and DACs that seemed impractical at the time. Thanks!
Insonicbloom says: Oct 4, 2012. 6:38 AM
nice instructable - I've got a cool stereo amplifier stripboard layout that would compliment this HERE it is quite loud though
Tomdf says: Oct 2, 2012. 8:05 PM
I'm just now delving into audio circuits and these have been a great introduction, ty :D
sfool says: Oct 2, 2012. 4:57 AM
:) , realy nice tut good job
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!