Pages: [1]   Go Down
Author Topic: 1khz Sine Wave Generator  (Read 10510 times)
0 Members and 2 Guests are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At  http://www.projects.cappels.org Mr. Cappels has many AVR based projects. I was interested in his latest, a  1khz sine wave generator. I ported his C version to the AVR and was able to achieve a nice digital sine wave with 6 bit resolution and a 1.007khz frequency. I used a 6 bit R2R DAC off of PORTD to make it easier. I used his basic schematic http://www.isarapix.org/pix95/1208149627.gif for the DAC. His project is at http://www.cappels.org/dproj/1_kHz_Signal_Source/1_KHz_Sine_Wave_Generator.html
Timer2 interrupts are used to cycle through the sine table at the frequency of interest.


 /*
  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)
   {

   }

}
Logged

New Jersey
Offline Offline
Full Member
***
Karma: 0
Posts: 193
Ard at work
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, just what I needed!
Logged

----------
Mathieu

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How did you know the value 455 would output 1khz? Is it possible to output lower frequencies?
Logged

Connecticut, US
Offline Offline
Edison Member
*
Karma: 2
Posts: 1036
Whatduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How did you know the value 455 would output 1khz? Is it possible to output lower frequencies?

Often, the fastest way is to try it yourself and see.  It won't harm anything to edit that number.  That number appears to be computed from the 32 samples for the sine table, and the desired sine wave duration (1/1000 second), measured in timer tick units.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I replaced it with a variable Val, and I tried decrementing it infinitely(Val--) in the void loop() function. The pitch changed, but their isnt much of a range at all. It was also strange because even though I was decrementing the value, the pitch only changed if I did a Serial.println(Val) in void loop().

Interrupts are tricky business, I'm beginning reading about them but so far I am totally confused.
Logged

Connecticut, US
Offline Offline
Edison Member
*
Karma: 2
Posts: 1036
Whatduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You'd need to do the whole cli()-timer_setup()-sti() sequence again if you want to change the interrupt rate on the fly.  Yes, the available frequencies are probably fairly granular, if the closest to 1KHz you can get is 1007Hz.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Richard Cappels explains how this work pretty well on the web site referenced at the beginning of my original post.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a great example, that I found more clear, at http://adrianfreed.com/content/arduino-sketch-high-frequency-precision-sine-wave-tone-sound-synthesis
Logged

Pages: [1]   Go Up
Jump to: