Corrupt Sinewave using a R2R DAC

So Yeah,

I'm using an 8bit R2R DAC on an Arduino Uno, I have it wired to pins 2-9, with a potentiometer wired as a resistor divider to A0 to act as a frequency control. I can write variable overflowCounter directly to the DAC and that gives me a perfect ramp wave on my oscilloscope with no problem. However when I use the same variable as a lookup for my sine_wave[] wavetable it outputs a bunch of noise with a whole cycle of the waveform pic behid the following link (https://dl.dropbox.com/u/19840532/IMG_20120730_101838.jpg)

//avr-libc library includes

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

#define LEDPIN 14

byte sine_wave[256] = {
0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96,
0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE,
0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4,
0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD5, 0xD8,
0xDA, 0xDC, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE8,
0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4,
0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC,
0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD,
0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6,
0xF5, 0xF4, 0xF3, 0xF1, 0xF0, 0xEF, 0xED, 0xEB,
0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC,
0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9,
0xC7, 0xC4, 0xC1, 0xBF, 0xBC, 0xB9, 0xB6, 0xB3,
0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C,
0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83,
0x80, 0x7D, 0x7A, 0x77, 0x74, 0x70, 0x6D, 0x6A,
0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52,
0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x3C,
0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28,
0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18,
0x16, 0x15, 0x13, 0x11, 0x10, 0x0F, 0x0D, 0x0C,
0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04,
0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03,
0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A,
0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15,
0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24,
0x26, 0x28, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37,
0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D,
0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64,
0x67, 0x6A, 0x6D, 0x70, 0x74, 0x77, 0x7A, 0x7D
};

volatile unsigned long overflowCounter =0; //using an unsigned long as I think eventually I'll need an absolutely huge variable to count the timer rollovers, needs to be volatile so the interrupt code can modify it...

void setup(){
pinMode(LEDPIN, OUTPUT);
//initialise Timer1
timerSetup();
portMappingSetup();
}

ISR(TIMER2_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));

DACwriter(sine_wave[overflowCounter]);
overflowCounter++;

}

void loop(){
OCR2A = map(analogRead(A5), 0, 1026, 1, 255);
}

//the following function contains all the gubbins to make the Compare Match Timer work
void timerSetup(){
cli(); // Disable interrupts while setting registers
TCCR2A = 0; // Reset control registers
TCCR2B = 0; // Reset control registers
TCCR2A |= (1 << WGM21); // Clear Timer2 on Compare Match (CTC) Mode
TCCR2B |= (1 << CS21); // Prescaler x8 for Timer2
OCR2A = 225
; // Set compared value
ASSR &= ~(1 << AS2); // Use system clock for Timer/Counter2
TIMSK2 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK2 |= (1 << OCIE2A); // Enable Output Compare Match A Interrupt
sei();
}

//setup port manipulation for DAC
void portMappingSetup(){
DDRD |= B11111100; //bit mask to get exclude the serial TX and RX
DDRB |= B00000111; //bit mask to exclude all but channels 8 and 9
}

void DACwriter(int x) {
int num = x; //store x into num to act as addres for location in wavetable
int numShiftD = num << 2; //shift num up by 2 to avoid serial pins on port D (this eats the 2 digits shifted off the end
PORTD = numShiftD; //send lowest significant digits to port D
int numShiftB = num >> 6; //shift num down by 6 to capture the two bits eaten by the above operation
PORTB = numShiftB; //send remaining two bits to port B and thence to the DAC
}

You've got a serious formatting problem with that post, have a look at it.

Apart from that, do you know the data is correct?


Rob

In the interrupt routine, you increment overflowCounter but you never reset it to zero when it reaches 256.
Add this after overflowCounter++;

  if(overflowCounter > 255)overflowCounter = 0;

Pete

thanks for spotting that, I had that in a previous version but obviously didn't transfer it across!! I have been scratching my head for days with that!

Matt H