|
|
View previous topic :: View next topic |
Author |
Message |
danielz85
Joined: 22 Sep 2012 Posts: 37
|
Harmonic Distortion in PIC16F1783 |
Posted: Wed Jan 02, 2013 3:35 am |
|
|
Hi,
I'm trying to produce an 18kHz pure sine wave using an LUT and the PIC's DAC.
I first create an array which holds the the required LUT values, and then I setup timer2 to interrupt every 50cc @32Mhz (160kHz).
When I sample the output, besides seeing the desired 18kHz frequency I also witness 9Khz "harmonic" (harmonics are usually above the original frequency)
Any ideas why this happens and how I can fix this?
Thanks,
Daniel
Code: | #include <16F1783.h>
#byte DACCON1=getenv("SFR:DACCON1")
//#INCLUDE <stdlib.h>
#include "consts.c"
#fuses INTRC_IO, NOWDT, NOBROWNOUT, PUT,NOMCLR
#use delay(clock=32M)
#use rs232(baud=4800,xmit=pin_B7,rcv=pin_B6)
#define Ns 400
int16 index=0;
const int wave[Ns] = {128,205,235,224,......}
//-----------------------------------------------------------------------
#INT_TIMER2
void timer2_ISR()
{
dac_write(wave[index]);
//printf("%u,"wave[index]);
index++;
if (index==Ns)
index=0;
}
void main()
{
setup_timer_2(T2_DIV_BY_1,50,1);
enable_interrupts(INT_TIMER2);
setup_dac(DAC_VSS_FVR | DAC_OUTPUT1);
setup_vref(VREF_ON | VREF_COMP_DAC_2v048);
set_timer2(0);
enable_interrupts(GLOBAL);
while (1)
{
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Jan 02, 2013 3:59 am |
|
|
Seriously, you can't call an interrupt handler every fifty cycles.
It takes typically about 60 cycles to get into and out of an interrupt handler.... The lookup to read a value from the table will take about twenty+ cycles as well.
You are just running out of processor time.
Potentially, if you used int_global, rather than the generic interrupt handling code, you could get 'close', but it'd still be right at the limit for the chip.
Do the work in your main loop instead, but realise the chip won't be able to do anything else. So:
Code: |
#include <16F1783.h>
#include "consts.c"
#fuses INTRC_IO, NOWDT, NOBROWNOUT, PUT,NOMCLR
#use delay(clock=32M)
#use rs232(baud=4800,xmit=pin_B7,rcv=pin_B6)
#define Ns 400
int16 index=0;
const int wave[Ns] = {128,205,235,224,......}
void main(void) {
int8 val_from_table=128;
setup_timer_2(T2_DIV_BY_1,50,1);
enable_interrupts(INT_TIMER2);
setup_dac(DAC_VSS_FVR | DAC_OUTPUT1);
setup_vref(VREF_ON | VREF_COMP_DAC_2v048);
set_timer2(0);
while (TRUE) {
if (interrupt_active(INT_TIMER2) {
//interrupt has triggered
clear_interrupt(INT_TIMER2);
dac_write(val_from_table);
index++;
if (index==Ns)
index=0;
val_from_table=wave[index]; //get the next value
}
}
}
|
It is still going to be absolutely 'borderline'. Doing a lookup from a 400 element table, implies page switching. Since this is slow, I'm doing it after writing the DAC value, and hopefully this can be done before the interrupt triggers again.
Best Wishes |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jan 02, 2013 4:12 am |
|
|
No digital system can ever produce a "pure" sine wave. Sine waves are continuously varying and cannot be precisely reproduced by sampled systems, nor by quantised systems, and certainly not by sampled & quantised systems. All we can do is go for a close enough approximation to a sinusoidal wave. "Close enough" depending in the application.
The "harmonics" are an essential feature of the quantisation and sampling, and will be there no matter how small the quanta and how fast the sampling. In practice, for any given application, you may be able to find a quanta that's "small enough" and sample rate that's "fast enough" not to have any significant practical effect.
The standard solution is to use analogue filtering after the DAC to attenuate the sampling frequency and its harmonics, but you can never totally remove them. Commonly a low-pass filter designed to give adequate rejection at the sample frequency and above is the normal solution. What "adequate" means is dependant on your application. For example, the human ear is pretty good at detecting even low-level harmonics for fundamentals below a few KHz.
So, you probably need to do some analogue engineering.
RF Developer |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Jan 02, 2013 4:21 am |
|
|
Agreed.
However he is not seeing 'harmonics' at all (his naming is wrong), but sub frequency artifacts caused by the beating between what the processor can achieve, and the actual time allowed between interrupts.
Every few interrupts, one is getting skipped, since there simply isn't time to complete the task, hence the lower frequency beat.
Best Wishes |
|
|
danielz85
Joined: 22 Sep 2012 Posts: 37
|
|
Posted: Wed Jan 02, 2013 4:36 am |
|
|
sub frequency artifacts is the word I was looking for... that's why I put harmonics in quotes.
Thanks, again for the info, I knew it took some time switching to the ISR, I didn't think it was THAT long...
I'll give it a try, and as RF_Developer said, I will put an analogue LPF at the DAC's output.
see where this all gets me...
Thanks as always
Daniel |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|