CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

question regarding DAC and TIMER2 in PIC16F1783

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
danielz85



Joined: 22 Sep 2012
Posts: 37

View user's profile Send private message

question regarding DAC and TIMER2 in PIC16F1783
PostPosted: Wed Dec 12, 2012 7:28 am     Reply with quote

Hi!

I'm trying to output a sine wave (a sum of sine waves, to be precise) using a DAC peripheral in PIC16F1783.

I'm using timer2 interrupt routine so that the timing is precise.
each 25usec (200/8M) I'm doing some calculations and then perform write_dac(new_val), the dac output then drives a loudspeaker (I've limited the current sourced from the pic to around 20mA using a resistor) and the the speaker is then sampled into a scope. When analyzing the frequency of the wave, instead of it being around 18KHz it appears to be around 4KHz.

assuming the issue has nothing to do with the values themselves, but with the timings, what may be cause the problem?

THANK YOU VERY MUCH IN ADVANCE,
Daniel

Code:

#include <16F1783.h>
#include "consts.c"
#fuses INTRC_IO, NOWDT, NOBROWNOUT, PUT,NOMCLR
#use delay(clock=32000000)
#use rs232(baud=4800,xmit=pin_B7,rcv=pin_B6)



int16 i=0;
int1 word[freqNum]={};
int16 index[freqNum]={};




void setWord(int decVal)
{
 
  word[7]=(decVal & 0b00000001);
  word[6]=(decVal & 0b00000010)/2;
  word[5]=(decVal & 0b00000100)/4;
  word[4]=(decVal & 0b00001000)/8;
  word[3]=(decVal & 0b00010000)/16;
  word[2]=(decVal & 0b00100000)/32;
  word[1]=(decVal & 0b01000000)/64;
  word[0]=(decVal & 0b10000000)/128;

}


#INT_TIMER2

void generateSignal()
{
 
  int i;
  int16 sum=0;
  int normVal=0;
  for (i=0;i<8;i++)
  if (word[i])
     sum+=(long)sine[index[i]];
   
   
   int fcnt=word[0]+word[1]+word[2]+word[3]+word[4]+word[5]+word[6]+word[7];
   switch (fcnt)
   {
   case 1:
      normVal=sum;
      break;
   case 2:
      normVal=sum/2;
      break;
   case 3:
      normVal=(sum*77)/256;
      break;
   case 4:
      normVal=sum/4;
      break;
   case 5:
      normVal=(sum*52)/256;
      break;
   case 6:
      normVal=(sum*42)/256;
      break;
   case 7:
      normVal=(sum*36)/256;
      break;
   case 8:
      normVal=sum/8;
      break;
   }
   
   for (i=0;i <8 ; i++)
    {
      index[i]+=inc[i];
      if (index[i]>=Ns)
         index[i]-=Ns;
    }
    dac_write(normVal);
    //printf("%u ",normVal);
}







void main()
{
 
 
  setWord(128);
  setup_timer_2(T2_DIV_BY_1,200,1);
  enable_interrupts(INT_TIMER2);
  setup_dac(DAC_VSS_FVR | DAC_OUTPUT1);
  setup_vref(VREF_ON | VREF_COMP_DAC_1v024);
  set_timer2(0);
  enable_interrupts(GLOBAL);
   
 
  while (1)
  {
     
  }

}
andyfraser



Joined: 04 May 2004
Posts: 47
Location: UK

View user's profile Send private message

question regarding DAC and TIMER2 in PIC16F1783
PostPosted: Wed Dec 12, 2012 7:37 am     Reply with quote

How long do you think it will take to execute all that code in the ISR - less that 25us ?

I think you need to look at pre-computing your values and putting them into a lookup table if you have any chance of reaching your desired frequency.

Andy
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 8:15 am     Reply with quote

Then some general programming advice:
- Don't use global and local variables with the same name, see 'i'. This will bite you sooner or later.
- Use meaningful variable names. 'word' is not telling me what the purpose of this variable is. Besides, 'word' is a reserved name in many compilers, and even worse: it isn't even a 'word' but a 'byte'.
- In setWord() you are reversing the bit order. You can skip this step when you reverse the sequence of your index[] array. Note, again, that 'index' isn't a very helpful name.
danielz85



Joined: 22 Sep 2012
Posts: 37

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 8:51 am     Reply with quote

ckielstra, thanks for the general advice, I made the changes you've offered. andyfraser, when I change the line "write_dac(normVal)" to "printf(normVal)" and then analyze the values, I get the frequencies as expected. That means that the calculations are done in time... sot the problem must be different... right?

besides, I'm working using 32MHz clock, and generate a 18KHz signal. There are more than 3 orders of magnitude of difference and all the calculations done are simply add/sub/mult (and some divisions by 2,4,8,...) on integers, and some branches... so, as far as I understand, that PIC should easily handle all of those.

Am I missing something here?
Thanks
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 10:36 am     Reply with quote

So, what does the line "write_dac(normVal)" involve?

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 11:58 am     Reply with quote

It should only be a matter of writing the value to the DAC register...
I'd try not using the CCS function, and just doing:
Code:

#byte DACCON1=getenv("SFR:DACCON1")

DACCON1=NormVal;


Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Dec 12, 2012 3:12 pm     Reply with quote

danielz85 wrote:
besides, I'm working using 32MHz clock, and generate a 18KHz signal. There are more than 3 orders of magnitude of difference and all the calculations done are simply add/sub/mult (and some divisions by 2,4,8,...) on integers, and some branches... so, as far as I understand, that PIC should easily handle all of those.
First impression is that you should be safe, but just to give you an impression about the performance margin you have:

The PIC is executing code at 1/4 the clock frequency: 32MHz / 4 = 8MHz == 8 instructions per microsecond.

Entering and leaving the interrupt routine has an overhead close to 30 instructions.

In the MPLAB simulator I've used the Stopwatch function to clock your interrupt routine, taking 968 instructions from start to end.
Total: 968 + 30 = 998 instructions

With 8 instructions per us, that gives a total execution time of: 998 / 8 = 124us
Maximum frequency you can get = 1 / 0.000124 = 8064Hz.

Oops.... your code is too slow.
danielz85



Joined: 22 Sep 2012
Posts: 37

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 7:25 am     Reply with quote

Thank you very much for all the info guys.
I've changed the code so that the array is created in advance and the only thing done in the ISR is the DACCON1=NormVal; operation.
But still no luck.
I'm starting to suspect that the issue is electrical. All I'm doing is connecting an 8ohm speaker to VSS on the one side, and to DACOUT (RA2) through a 35ohm resistor on the other side. The DAC is configured such that it outputs values between VSS to 1.024v.

But when I analyze the results I still see are different for what I expect for some reason...

any further suggestions?
thanks again in advance,
Daniel
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 7:49 am     Reply with quote

It's a DAC. Not an amplifier. The individual resistors are around 600R. On the lowest step, a resistance of about 150KR to +ve, Even on the highest step, you still have 600R to +ve. You are not going to get much/anything into 8R (about 12mV max). You need a buffer amplifier.....

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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