Dear All;
I would like to produce different analog Waveforms (Sinewave, Triangle, Squarewave ...) with different frequencies through a Arduino Duemilanove. I would like to have the waveforms on three different ports.
I have found a simple code in a webpage which seems to be a good start point. I have edited and debugged this code and used it for my application.
This method is based on "DIRECT DIGITAL SYNTHESIZER (DDS)" method. In order to have proper output we need to have a R2R resistor ladder connected to Arduino. infact this R2R resistor ladder converts digital outputs to analog signals.please take a look at: http://didier.longueville.free.fr/arduinoos/?p=64 and http://didier.longueville.free.fr/arduinoos/?p=111
In order to have three different waveforms on three ports I need to use "Compare interrupts" of TIMER0, TIMER1 and TIMER2.
To test the performance of this method, I first wrote a simple code, I have included my code below for your review. Now, Here is the problem:
I can successfully generate signals with desired frequencies on the ports which are being updated by TIMER1 and TIMER2 Interrupts, but the frequnecy of the signal which is being generated by TIMER0 interrupt is 1/3 (One third) of the two other signals (generated by the TIMER1 and TIMER2 interrupts). For example when I have 250Hz signal on PortB and PortD, There is a 80Hz signal on PortC!!!
The strange thing here is when I remove TIMER1 Interrupt from this code, the signal frequency on PortC which is being updated by TIMER0 becomes 250Hz!!!!
Can anyone please tell me what is the probelm?
int vWaveData[256];
long int i;
unsigned long int tuningWordM;
int upperCountingValue, desiredfreq;
double refFrequency;
long int phaseAccumulator0,phaseAccumulator1,phaseAccumulator2;
void generateWaveData(); // Generate wave data in global vector
void setup()
{
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 << CS20); // Prescaler x1 for Timer2
OCR2A = 255; // 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
TCCR1A = 0; // Reset control registers
TCCR1B = 0; // Reset control registers
TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
TCCR1B |= (1 << CS10); // Prescaler x1
OCR1A = 255; // Set compared value
TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK1 |= (1 << OCIE1A); // Enable Output Compare Match A Interrupt */
TCCR0A = 0; // Reset control registers
TCCR0B = 0; // Reset control registers
TCCR0A |= (1 << WGM01); // Clear Timer on Compare Match (CTC) Mode
TCCR0B |= (1 << CS00); // Prescaler x1
OCR0A = 199; // Set compared value
TIMSK0 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK0 |= (1 << OCIE0A); // Enable Output Compare Match A Interrupt
generateWaveData(); // Create Sinewave look-up table
upperCountingValue = 255;
desiredfreq=250;
refFrequency = 16000000/(upperCountingValue+1);
tuningWordM = ((pow(2, 32) * desiredfreq) / refFrequency);
DDRB = B11111111; //Set PORTB as output
DDRC = B11111111; //Set PORTC as output
DDRD = B11111111; //Set PORTD as output
sei(); // Enable interrupts once registers have been update
}
void loop()
{
}
void generateWaveData() //Generate a Sawtooth Wave
{
for (int i=0; i < 256; i++)
vWaveData = (i*63)/256;
*} *
ISR(TIMER2_COMPA_vect) // Interrupt service run when Timer/Counter2 reaches OCR2A
*{ *
phaseAccumulator2 += tuningWordM;
byte phaseAccumulatorMSB2 = (phaseAccumulator2 >> 24);
PORTB = vWaveData[phaseAccumulatorMSB2];
}
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
*{ *
phaseAccumulator1 += tuningWordM;
byte phaseAccumulatorMSB1 = (phaseAccumulator1 >> 24);
PORTD = vWaveData[phaseAccumulatorMSB1];
}
ISR(TIMER0_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
phaseAccumulator0 += tuningWordM;
byte phaseAccumulatorMSB0 = (phaseAccumulator0 >> 24);
PORTC = vWaveData[phaseAccumulatorMSB0];
}
-------------------------------------------------------------
Steps per cycle is 256 (table length) and max dac counts are 2^6 - 1 = 63, where 6 is the number of bits of the R2R ladder DAC.
Thanx in advanced