Instructables
Recently I've been posting a lot of projects that use an 8 bit resistor ladder digital to analog converter (DAC) and an Arduino to make sound.  (see the Arduino vocal effects box, the Arduino drum sampler, and my audio output tutorial).  The technique I've been using to make these DACs is very simple, it requires only a handful of 10k and 20k resistors wired together into a network.  But the convenience comes with a price, as these DACs end up a little noisier than I would like at times.  So I decided to buy a specialized IC that will be compatible with all the code I've already written for the resistor ladder DACs, but uses highly matched resistors to reduce noise.  When I looked on Digikey for such a DAC, I found the TLC7528, a dual output 8 bit DAC IC.  The dual output capability of the chip interested me a lot; while it is easy to set this chip up with one permanent output, it also gives you the option of  toggling between two isolated output pins, making it fairly straightforward to set up a 2 channel audio output with a relatively small amount of additional effort/hardware setup/Arduino data pins.

In this instructable I'll show you how to use the TLC7528 with the Arduino to output stereo audio.  Stereo audio means 2 independent channels of audio.  Stereo audio is especially fun when sent to headphones because you can achieve some interesting auditory effects since each ear is hearing its own independent channel of sound, some ideas include:

"3D audio" spatial effects- by adjusting the filtering, amplitude, and phase of two channels of audio you can simulate the experience of sound directionality, making a sound source seem to originate from a precise location in the space around you, here's a great example
binaural beats- by sending two sine waves of similar -but unequal- frequencies to headphones (one to each ear), you will hear a pulsating beatnote that is thought to induce relaxation and other meditative effects.  Here's an example.
panning- change the relative amplitude of a sound source in each channel of the stereo mix.  This effect is simple, but can be really cool sounding, a great example is in the bridge of Led Zeppelin's Whole Lotta Love (listen to it with headphones!)


Parts List:

(x1) TLC7528 Digikey 296-1871-5-ND
(x1) Arduino Uno Sparkfun DEV-11021


Other Materials:

22 gauge jumper wire
oscillosope
 
Remove these adsRemove these ads by Signing Up
1-40 of 41Next »
achand84 months ago

Amanda, I breadboarded the connection 4 times thinking that i did something wrong. I was getting 4 volts for 11111111. It's not the reference voltage. If I use the MDAC in current mode and a I to V converter, then would I get a 5v output?

amandaghassaei (author)  achand84 months ago
Some other people said that too, there might be something in the circuit that prevents it from behaving ideally, if you need it to get up to 5v (or higher) you can use an op amp to amplify it.
​It was because RFBA and RFBB were connected to VCC. Those are internal resistances built into the MDAC for the Transresistance amplifier when used in current mode. According to forums, current mode is more reliable and accurate but gives output in the range of 0 to -Vref so voltage mode is more convenient.
achand84 months ago

Multiplying DAC require a I to V converters at output. For Voltage operation mode is it necessary that we should connect RFBA and RFBB to Vcc? It's not specified in the datasheet. Isnt RFBA the feedback resistor for the opamp built into the chip? Sorry for the noob question. Thanks for the tutorial!

wizer11 months ago
Hey Amanda

I am a big fan of your work and, although new to electronics, have been slowly gathering parts to make up one of your 'Glitch Box' projects. I've just stumbled on this instructable and I'm wondering whether I should use one of these TLC7528 chips to improve the sound output? Would this be simple to adapt? Would I need to change or add any other parts? Appreciate any help you can give!
amandaghassaei (author)  wizer11 months ago
the rest of the circuit should stay the same
amandaghassaei (author)  wizer11 months ago
yes! you should definitely do that. I think it will sound better and it will be less stuff to solder.
It's already experimented or we have to experiment with that project?
amandaghassaei (author)  denimjohnson1 year ago
this is meant to be a resource for people to create new projects from. There is tons of experimentation that can be done from these concepts.
qazxvy1 year ago
Sorry this is a weird way to do it, but I couldn't get the replying working (something about the CAPTCHA I couldn't figure out) but here's what I would've replied!

Wow thanks! That still sounds a little bit fuzzier than I'd like for using samples though. Is there a way I could increase the quality some more? I'd like to use my instrument for recording, and possibly preforming. Also, could I just downgrade the quality to 8-bit using the one-bit audio? Might be cool
amandaghassaei (author)  qazxvy1 year ago
I'm a little confused by the last thing you said? For lower frequencies 8 bit can be ok if you apply some low pass filtering. I made that last recording with a simple resistor dac and I didn't do any resistor matching to make sure that I was getting a more high fidelity output, but I think something like the chip I used in this instructable would be much less noisy. not sure exactly how much though.
qazxvy1 year ago
So this says that you're using an 8-bit DAC, so does that mean you can only output 8-bit chipet-style sound? If not, what could you do to play higher quality sounds, like a piano sample?
amandaghassaei (author)  qazxvy1 year ago
chiptunes is actually 1 bit audio, 8 bit sounds much more organic (though a bit noisy). here's a sample:
https://soundcloud.com/amanda-ghassaei/over-the-rainbow
locost331 year ago
I'm using the output to lie to an ecu about throttle position, typical output 1.2 to 4.8v) Is there a way to configure the DAC correctly? It doesn't seem to be doing what is asked of it. I've put a post up on the ti forum hoping for an answer.
If possible can you please suggest a circuit to convert 0 to 4v back to a true 0 - 5v?
amandaghassaei (author)  locost331 year ago
have you used op amps before? you can set up a non-inverting amplifier like this:

http://en.wikipedia.org/wiki/Operational_amplifier#Non-inverting_amplifier

if you choose your resistors correctly, you can amplify the signal back up to 0-5V. I think it is something like R1 = 4*R2, but you should double check. does that make sense?
locost331 year ago
Using the DAC in this configuration the output is scaled to 4/5 the input (i.e. 255 = 4v). Feeding OUTA / OUTB from a 6.25v regulated supply gives a true 0-5v output. Why is this necessary? Anyone?
amandaghassaei (author)  locost331 year ago
good point, since the arduino only outputs 5V, I'd recommend using an amplifier in a voltage follower configuration to get the full 0-5V. what are you using it for?
locost331 year ago
Hi. Hopefully someone can help: I've built the circuit as shown in this build and found that rather than a full 5v output I only get 4v given a 5v reference. The diagram from the 'scope above also shows 4v (at 2v per division). I've pm'd Amanda but had no response as yet
manuel1231 year ago
First, I want to thank you for all of these wonderful instructables covering audio with the Arduino and also for your earlier help with my project. I've managed to set up a TLC7528 and use your sine wave code to get a nice clean output. I'm currently trying to understand your code in order to modify it to my own purposes. Essentially, I need to read a signal through the A0 pin, process it, and then output it through the DAC. It would also help if I could use the value of the PORTB register to determine how I process the signal. It seems to me that the actual audio output is done inside the ISR macro which looks to me like some kind of loop but I'm not sure. Should I just add a switch statement controlled by PORTB, read A0 and do the calculations in the individual switches, and output the final value to something like PORTD = output;? Would using this switch statement reduce the quality of the signal too much? If so, is there a better way? Thanks for all the help again.
Here's the code I'm using: I'm getting a sound out of it but it's very fuzzy. What might be wrong?



int output;

void setup()
{

for (byte i=0;i<8;i++){
pinMode(i, OUTPUT);//set digital pins 0-7 as outputs
}

//set up continuous sampling of analog pin 0

//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;

ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only

ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements

cli();//stop interrupts

//set timer1 interrupt at ~44.1kHz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 361;// = (16*10^6) / (44100*1) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 bit for 1 prescaler
TCCR1B |= (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);

sei();//enable interrupts


}

ISR(TIMER1_COMPA_vect) //timer1 interrupt ~44.1kHz to send audio data (it is really 44.199kHz)
{
output = ADCH; //read the value from A0
PORTD = output; //send the output value to the DAC through digital pins 0-7
}

void loop(){}
amandaghassaei (author)  manuel1231 year ago
this looks good, it would be better to set the audio output frequency at the same frequency that you are reading data from a0 (~38.5khz). try this:

int incomingAudio;//store incoming audio data

void setup(){

  cli();//disable interrupts
 
  //set up continuous sampling of analog pin 0
 
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;
 
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
 
  ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
 
  sei();//enable interrupts

  //if you want to add other things to setup(), do it here

}

ISR(ADC_vect) {//when new ADC value ready
  incomingAudio = ADCH;//update the variable incomingAudio with new value from A0 (between 0 and 255)
  PORTD = incomingAudio;//send out audio
}

void loop(){
//do other stuff here
}
No, that's even worse, now it just makes popping sounds.
I set up 8 LEDs which tell me what bits of the DAC are HIGH and which are LOW. According to them there's barely any output with the new code.
amandaghassaei (author)  manuel1231 year ago
sorry, I forgot to set pins 0-7 as outputs, try adding that piece back in.
Still all fuzzy, should I post my circuit? Might the problem be in the electronics?
Granted, the fuzz is a neat effect but I want to put the effects in myself instead of having them caused by a problem in the system.
(removed by author or community request)
(removed by author or community request)
(removed by author or community request)
(removed by author or community request)
It seems I forgot a capacitor, It's still fuzzy, but the bias is right now.
(removed by author or community request)
Ok, I'm really sorry about all of these posts, I added the capacitor that was missing and it really cleaned up the signal. However, it's still a bit fuzzy, what might be the problem?
amandaghassaei (author)  manuel1231 year ago
are you still having trouble? what is your dac setup like? can you make a recording of the output?
amandaghassaei (author)  manuel1231 year ago
the isr function is a timer interrupt:
http://www.instructables.com/id/Arduino-Timer-Interrupts/
it gets called at a constant frequency to send out audio data- basically it takes care of sending out audio at a certain sampling rate.
reading A0 and sending out data should both be handled with interrupts. all the code for reading from portb should happen in your main loop. check out my vocal effects box for an example of this.
let me know if you have more questions!
amanda
mielke111 year ago
i have the same headphones :P
privatier1 year ago
Nice project.
For those who need a 10-bit solution, please have a look at http://sourceforge.net/projects/lxardoscope/files/accuracyInvestigation/ where the Arduino Uno drives a MAX503.
Edgar1 year ago
Great Project, I'm hearing Binaurals right now, but on my PC. A link went to my Gizmo blog:
http://faz-voce-mesmo.blogspot.pt/2012/11/instructables-sofa-de-paletes-stereo.html
amandaghassaei (author)  Edgar1 year ago
cool, thanks!
Yes, I try to promote empowering stuff.
1-40 of 41Next »