Go Down

Topic: Arduino DDS Sinwave Generation: Help? (Read 2998 times) previous topic - next topic


Once, I used a chunk of code for an arduino project that involved analog sinewave generation via DDS. I've recently been wanting to do another project with the same code. Unfortunately, the site that I knew to host the code, no longer lists it. On the forum I've found many threads referencing the code, like this one:


But what I'm looking for is if anyone else has the original code any more. I've PM'd several people from threads involving that code. But seeing as all those posts are more than a year old, and a good portion of those users are in the single digit posts, I assume odds are that i won't get PM'd back. I've also managed to hunt down the original writer of the code's website, and email him. Any help would be great guys, thanks.


Funny thing, after searching for hours on end, I posted here. One last search after i posted it? FOUND THE CODE. I'm going to post this stuff here so you guys have it and don't have to hunt it down like I did.

Code: [Select]
#include "avr/pgmspace.h"

// table of 256 sine values / one sine period / stored in flash memory
PROGMEM  prog_uchar sine256[]  = {

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int ledPin = 13;                 // LED pin 7
int testPin = 7;
int t2Pin = 6;
byte bb;

double dfreq;
// const double refclk=31372.549;  // =16MHz / 510
const double refclk=31376.6;      // measured

// variables used inside interrupt service declared as voilatile
volatile byte icnt;              // var inside interrupt
volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile unsigned long phaccu;   // pahse accumulator
volatile unsigned long tword_m;  // dds tuning word m

void setup()
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  Serial.begin(115200);        // connect to the serial port
  Serial.println("DDS Test");

  pinMode(6, OUTPUT);      // sets the digital pin as output
  pinMode(7, OUTPUT);      // sets the digital pin as output
  pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output


  // disable interrupts to avoid timing distortion
  cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay() is now not available
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

  dfreq=1000.0;                    // initial output frequency = 1000.o Hz
  tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word

void loop()
  while(1) {
     if (c4ms > 250) {                 // timer / wait fou a full second
      dfreq=analogRead(0);             // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz

      cbi (TIMSK2,TOIE2);              // disble Timer2 Interrupt
      tword_m=pow(2,32)*dfreq/refclk;  // calulate DDS new tuning word
      sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

      Serial.print("  ");

   sbi(PORTD,6); // Test / set PORTD,7 high to observe timing with a scope
   cbi(PORTD,6); // Test /reset PORTD,7 high to observe timing with a scope
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2A1);

  sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);

// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {

  sbi(PORTD,7);          // Test / set PORTD,7 high to observe timing with a oscope

  phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
  icnt=phaccu >> 24;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  OCR2A=pgm_read_byte_near(sine256 + icnt);   

  if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds

cbi(PORTD,7);            // reset PORTD,7

here's the lowpass filter too.

Uploaded with ImageShack.us


Be quick it still is in Google Cache...

- http://webcache.googleusercontent.com/search?q=cache:7CEXBeQfCCwJ:interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/+http://interface.khm.de/index.php/labor/experimente/arduino-realtime-audio-processing/&cd=1&hl=nl&ct=clnk&gl=nl&client=firefox-a&source=www.google.nl

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)


I have a link to my version of the code (which uses it for 2kHz Resolver excitation) here:
There is also a circuit diagram for a combined active filter and power buffer (so you get 500mA of drive current) and I even have several spare shields available to mount the hardware available at cost price ($4) each.

Go Up