Creating sine waves with an Arduino

Has anyone successfully interfaced an Arduino to a DAC or any other circuitry to create sine waves?

I have an application where I would like to produce two sine waves and was looking for suggestions and ideas of how to accomplish this with an arduino.

thanks

Did you see this
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208192843 ?

Use a look up table and output the result to the PWM outputs. Then use an RC filter to recover the sin wave.

Thanks for the ideas guys!

I will have to try the 1kHz code and play around with how to change this to the frequencies that I am interested in creating.

best regards!

I have a few questions:

What frequencies are you looking to create?
How accurate do they have to be, frequency wise?
Will the AVR being doing anything else other than the sine waves?

Regards,

Mike

Ultimately, I would like to be able to have two variable frequencies under 4 kHz
but to start, I would like to be able to rpocude two sinewaves in the 100 Hz to 500 Hz range
with some pretty good accuracy ( +1 Hz)

Is this doable with an Arduino ?

just pop over and look at this:-
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1208192843

with some pretty good accuracy ( +1 Hz)

I think you are pushing it. Also if you need the frequency to be that accurate how accurate do you want the Sin wave (how many bits of resolution)?

Ultimately, I would like to be able to have two variable frequencies under 4 kHz
but to start, I would like to be able to rpocude two sinewaves in the 100 Hz to 500 Hz range
with some pretty good accuracy ( +1 Hz)

OK - I was just musing on ways it could be done with more analog circuitry.

If it were fixed frequencies a 1 or 2 bit dac and a decent bandpass filter may have been suitable.

Regards,

Mike

I like Grumpy Mike's suggestion to use a ramp table and output to the PWM outputs.

Can the Arduino produce more than one of these frequencies at one time?

Looking at the link that BroHogan mentions in his post, the example there (as shown below) uses a table and
outputs this to the Port D lines which are connected to a DAC. Also it appears that the frequency is based upon
a value placed in the timer TCNT2.

/*
Copyright 2007 Richard Cappels used with his permission
www.projects.cappels.org
This assumes an R/2R DAC (or other DAC) connected to PORTD, and
Arduino 16mhz clock
The frequency measured at the output of the DAC is 1.007 kHz.
ported to arduino by hotcarrier
output to pd7-pd2 with 6 bits- needs high order pd7 to work
correctly
*/

#include <avr/interrupt.h>
#include <stdlib.h>

char sinetable [32];
int i ;

void ioinit (void)
{
//Initialize output ports
PORTD = B11111111;
DDRD = B11111111;

}

void timer_setup(){
TCCR2A = 0;
TCNT2=455; //455 outputs 1.007khz
TCCR2B = B00000010;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
}
void setup(){

ioinit();
arraysetup();
cli();
timer_setup();
i = 0;
sei();

}

ISR(TIMER2_OVF_vect) {

PORTD=(sinetable[i++]);
TCNT2=455;
if(i==32){
i=0;
}

}
void arraysetup(void){
sinetable[0]=127; // Put 32 step 8 bit sine table into array.
sinetable[1]=152;
sinetable[2]=176;
sinetable[3]=198;
sinetable[4]=217;
sinetable[5]=233;
sinetable[6]=245;
sinetable[7]=252;
sinetable[8]=254;
sinetable[9]=252;
sinetable[10]=245;
sinetable[11]=233;
sinetable[12]=217;
sinetable[13]=198;
sinetable[14]=176;
sinetable[15]=152;
sinetable[16]=128;
sinetable[17]=103;
sinetable[18]=79;
sinetable[19]=57;
sinetable[20]=38;
sinetable[21]=22;
sinetable[22]=10;
sinetable[23]=3;
sinetable[24]=0;
sinetable[25]=3;
sinetable[26]=10;
sinetable[27]=22;
sinetable[28]=38;
sinetable[29]=57;
sinetable[30]=79;
sinetable[31]=103;
}
void loop()
{

while (1)
{

}

}

Is there more than one timer available where I could potenitally send out more than one frequency onto seperate PWM outputs?

Where can I learn more on how to do this?

thanks

I think you are missing the point about the PWM. It does not matter what frequency it runs at, only the rate you feed it updates from the look up table. This can be changed in tow ways:-

  1. Changing the time between changing the PWM ratio.
  2. Changing the rate you step through the table. You can even do this fractionally by incrementing a 16 bit value (integer) and only using the most significant byte to act as the index to the table.

In that way you can have as many different frequencies as you PWM outputs.

Thanks Grumpy Mike.

Not sure if I understand you correctly, so your patience ia appreciated...

Would I create a PWM output with a 50% duty cycle and determine the
frequency by how often I turn the PWM output on and off?

thanks

Would I create a PWM output with a 50% duty cycle and determine the
frequency by how often I turn the PWM output on and off?

No the PWM duty cycle is set by the value in the look up table. This in effect sets an analogue level after the PWM has been passed through a filter. At the next sample time you fetch the next entry in the table and set the PWM duty cycle with that.
Think of the PWM duty cycle as being an analogue output (which it is).
So set the sample time at your basic rate say every 100uS. This will give you a maximum frequency of 5KHz.
Then at each sample time you increment the pointer into the lookup table by some value. This value determines the final frequency. As you only have a look up table of 32 entries you only need 5 bits to address this. Therefore use the top 5 bits of your pointer to actually address the look up table and output (set the duty cycle) the value.
For a second frequency output use a different pointer a different increment, different PWM output but the same look up table.

Would I create a PWM output with a 50% duty cycle and determine the
frequency by how often I turn the PWM output on and off?

No the PWM duty cycle is set by the value in the look up table. This in effect sets an analogue level after the PWM has been passed through a filter. At the next sample time you fetch the next entry in the table and set the PWM duty cycle with that.
Think of the PWM duty cycle as being an analogue output (which it is).
So set the sample time at your basic rate say every 100uS. This will give you a maximum frequency of 5KHz.
Then at each sample time you increment the pointer into the lookup table by some value. This value determines the final frequency. As you only have a look up table of 32 entries you only need 5 bits to address this. Therefore use the top 5 bits of your pointer to actually address the look up table and output (set the duty cycle) the value.
For a second frequency output use a different pointer a different increment, different PWM output but the same look up table.

Thanks Grumpy Mike -

This is great information!

I will read up on how to do this.

If I also wanted to have a variable frequency ttl level square wave output, couldn't I just
turn one of the output lines on and off and change the frequency & duty cycle
by how often that I change either of these states on that line?

I suspect that might be easy to do with a timer to control the timing of this?

couldn't I just turn one of the output lines on and off and change the frequency & duty cycle

Yes you can but to get the accuracy you need you will probably have to go to an interrupt driven routine. If you are just interested in the audio then don't bother with the duty cycle changes as all it does is affect the harmonic contents of the sound.