Audio Output using an Arduino
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.
(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
22 Gauge Wire
Step 1: Digital to Analog Converter
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 theWikipedia 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.
Step 2: Set up DAC and Test
I constructed my DAC on a breadboard (figs 1-3). The schematic is given in fig 8. Below are a few pieces of sample code that generate the waveforms shown in figs 4-7. In the following pieces of code I send a value between 0 and 255 to “PORTD” when I want to send data to the DAC, it looks like this:
PORTD = 125;//send data to DAC
This is called addressing the port directly. On the Arduino, digital pins 0-7 are all on port d of the Atmel328 chip. The PORTD command lets us tells pins 0-7 to go HIGH or LOW in one line (instead of having to use digitalWrite() eight times). Not only is this easier to code, it’s much faster for the Arduino to process and it causes the pins to all change simultaneously instead of one by one (you can only talk to one pin at a time with digitalWrite()). Since port d has eight pins on it (digital pins 0-7) we can send it one of 2^8 = 256 possible values (0-255) to control the pins. For example, if we wrote the following line:
PORTD = 0;
it would set pins 0-7 LOW. With the DAC set up on pins 0-7 this will output 0V. if we sent the following:
PORTD = 255;
it would set pins 0-7 HIGH. This will cause the DAC to output 5V. We can also send combinations of LOW and HIGH states to output a voltage between 0 and 5V from the DAC. For example:
PORTD = 125;
125 = 01111101 in binary. This sets pin 7 low (the msb is 0), pins 6-2 high (the next five bits are 1), pin 1 low (the next bit is 0), and pin 0 high (the lsb is 1). You can read more about how this workshere. To calculate the voltage that this will output from the DAC, we use the following equation:
voltage output from DAC = [ (value sent to PORTD) / 255 ] * 5V
so for PORTD = 125:
voltage output from DAC = ( 125 / 255 ) * 5V = 2.45V
The code below sends out several voltages between 0 and 5V and holds each for a short time to demonstrate the concepts I’ve described above. In the main loop() function I’ve written:
PORTD = 0;//send (0/255)*5 = 0V out DAC
PORTD = 127;//send (127/255)*5 = 2.5V out DAC
PORTD = 51;//send (51/255)*5 = 1V out DAC
PORTD = 255;//send (255/255)*5 = 5V out DAC
The output is shown on an oscilloscope in fig 4. The center horizontal line across the oscilloscope represents 0V and each horizontal line represents a voltage increase/decrease of 2V. The image notes on fig 4 show the output of each of the lines of code above, click on the image to view the image notes.
For more detail: Audio Output using an Arduino
This Post / Project can also be found using search terms:
- arduino audio output
- arduino sound output