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

Issue with PWM DAC using built-in PWM Module of PIC16F690

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



Joined: 04 Jan 2010
Posts: 9

View user's profile Send private message Yahoo Messenger

Issue with PWM DAC using built-in PWM Module of PIC16F690
PostPosted: Tue Aug 19, 2014 11:50 am     Reply with quote

I have searched out this help forum extensively, many of my queries regarding PWM & built-in PWM module of PIC Micro-controller have been addressed through this search, but here is an issue for which I am unable to find solution through search of this help forum.

I am trying build a simple DAC with PIC16F690 using its built-in PWM module. The PWM module is working at my desired frequency but the issue I am facing is that when I try to generate Sawtooth waveform, the PWM output stays high at 100% duty cycle for a long span of time and then starts again from zero & proceeds to upward count.

Here is my code:
Code:

#include <16F690.h>

#FUSES NOWDT     //No Watch Dog Timer
#FUSES PUT //Power Up Timer ON
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal switch over mode ON
#FUSES FCMEN //Fail safe clock monitor enabled
#FUSES NOCPD //No code protection from EE
#FUSES NOPROTECT //No code read protection
#fuses HS,

#use delay(crystal=20MHz)

#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5)
 
#define Upper_Limit 1000
 
unsigned int16 PWM_DC_Val = 0;

#int_TIMER2
void TIMER2_isr(void)
{
   // left blank for future use
}

void main()
{
   
   setup_timer_2(T2_DIV_BY_1,79,1);
   // The cycle time will be (1/clock)*4*t2div*(period+1) = 62.5khz is       
   //required
   
   setup_ccp1(CCP_PWM);
   enable_interrupts(GLOBAL);
   enable_interrupts(int_TIMER2);
   setup_comparator(NC_NC_NC_NC);
     
   printf("\r\nGeneration of Sawtooth Waveform using PWM Module\n\r");
     
   while(TRUE)
   {
      //TODO: User Code
     
      set_pwm1_duty(PWM_DC_Val);
           
      if( PWM_DC_Val > Upper_Limit )
          PWM_DC_Val = 0;
      else
          PWM_DC_Val++;
         
   }
   
}



To implement 10-bit mode of PWM Module, I have declared the PWM Duty Cycle variable PWM_DC_Val as 16-bit unsigned so that PWM module may be set to operate in 10-bit mode through set_pwm1_duty(PWM_DC_Val) function.
As far as I have been able to understand from help files of CCS compiler, in set_pwm1_duty(PWM_DC_Val) function

0L = (unsigned int16)0=0% duty cycle
1000L =(unsigned int16)1000 =100% duty cycle

so

set_pwm1_duty((unsigned int)0) means 0% duty cycle

set_pwm1_duty((unsigned int)1000) means 100% duty cycle


I know PWM topic has been discussed in many posts on this help forum but despite thoroughly searching the forum, as much as I could, I am unable to find the solution to this issue.

The web-link to screenshot of Proteus Simulation of this code is given below:

http://www.4shared.com/download/HU3WkIbyba/pwm_q-1.jpg?lgfp=3000

In this image PWM waveform is shown in blue color at bottom, while resulting Sawtooth Waveform is shown in yellow color at the top.

regards
m.yasir
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 19, 2014 12:32 pm     Reply with quote

Quote:
0L = (unsigned int16)0=0% duty cycle
1000L =(unsigned int16)1000 =100% duty cycle

That's not true. The pwm duty cycle is calculated from a formula which
is based on the middle parameter (PR2) in the setup_timer_2() function.

This thread has the formula for 10-bit PWM duty cycle:
http://www.ccsinfo.com/forum/viewtopic.php?t=42417&start=1
yasir9909



Joined: 04 Jan 2010
Posts: 9

View user's profile Send private message Yahoo Messenger

@ PCM programmer
PostPosted: Tue Aug 19, 2014 3:28 pm     Reply with quote

PCM programmer thank you for your reply. I have been able to deduce following the formulas from the post whose link you have shared :

1. PWM Period = 1/(Clock Frequency)*4*t2div*(Period+1)

or

PWM Frequency = (Clock Frequency)/( 4*t2div*(Period+1) )

where in function setup_timer_2(T2_DIV_BY_1,79,1);

t2div = 1,Period = 79

or

Code:

                                      Crystal Frequency
       PWM Freq  =  ------------------------------------------
                             (PR2 + 1) * (Timer2 Prescaler) * 4   

     

where in function setup_timer_2(T2_DIV_BY_1,79,1);

Timer2 Prescaler = t2div = 1, PR2=Period = 79

Here Clock Frequency=Cystal Frequency = Master Clock Frequency
of Micro-controller either internal or external

2. According to Ttelmah in the following post :
http://www.ccsinfo.com/forum/viewtopic.php?t=42417&start=1
Duty Cycle Value for the function set_pwm1_duty(Value); is given by :

Value = (%age of Duty Cycle/100) *(Period+1) *4 -1

For 50% duty cycle and Period=middle value=255 in above formula
Value will be :

Value = (50/100)*[(255+1)*4]-1 = 511

=> for 0% duty cycle Value = 0
=> for 100% Duty cycle Value = 1023

Value can't be bigger than the ((middle value+1) *4)-1.
So for a middle value of 255, maximum value is 256*4 = 1024 -1 =
1023. The '10 bit' maximum for the chip.
3. %age of Duty Cycle =[ (Value+1) /( (Period+1) *4 ) ] *100
4. So in my case with following configurations of this function:
Code:

     setup_timer_2(T2_DIV_BY_1,79,1);
   

I have following parameters:
Period or middle value = 79,t2div = Timer2 Prescaler =1,
maxium value = ((middle value+1) *4)-1
maxium value = ((79+1) *4)-1 = 319

=>

set_pwm1_duty(0L); = 0% Duty cycle
set_pwm1_duty(319L); = 100% Duty cycle


In the above posted code I have set maximum value equal to 319 by define statement as
Code:
#define Upper_Limit 319


This has resolved the issue of PWM duty cycle being stuck at 100% for a big span of time

I think my concepts have become clear now.
I have worked on AVR, PIC seems quite complex to me as compared with AVR. Datasheet of AVR also provides C code snippets along with assembly code that makes that task of programming different modules of AVR quite easy while Microchip provides only assembly code.

any ways thanks for your help


Last edited by yasir9909 on Wed Aug 20, 2014 9:08 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Wed Aug 20, 2014 8:05 am     Reply with quote

Value = (%age of Duty Cycle/100) *(Period+1) *4 -1

You are missing one critical thing.
You are setting the Period value (PR2), to 79.

Try the formula again, with this, and understand what PCM_Programmer is telling you.
yasir9909



Joined: 04 Jan 2010
Posts: 9

View user's profile Send private message Yahoo Messenger

@Ttelmah
PostPosted: Wed Aug 20, 2014 9:21 am     Reply with quote

I think,I have mentioned in summary of my findings regarding PWM and Timer2 settings that

PR2=Period=Middle Value = 79

Ok let me revisit the links provided by PCM Prgrammer.

Actually,I need to read analog signal through input pin of built-in analog-to-digital converter and then after mapping it to some other values saved in lookup table,I shall output it as analogue output through PWM Module and low pass filter.

Thanks for your help

regards
m.yasir
Ttelmah



Joined: 11 Mar 2010
Posts: 19505

View user's profile Send private message

PostPosted: Wed Aug 20, 2014 10:46 am     Reply with quote

I'm trying to make a point about the way you are thinking.

Key to understand is that you are dealing with _embedded_ languages. You have the 'core' C functions, and then dozens of other parts that deal directly with hardware.
As such, it is the _hardware_ data that you need to look at.

Now the formula from me, that you found, is copied directly from the chip data sheet. If you look at the 16F690 data sheet, go to section 11, and look at Equation 11-2, and 11-3, you get the formulae for the pulse width, and the duty cycle. Then even a nice little table giving example periods, and how the resolution decreases as the PR2 value drops (table 11-2).

Then step back and realise that the CCS functions only set the hardware. Nothing else. If you look again at the data sheet, you see that the time for the PWM, is set by timer2. Look at timer2, and you see it has a 'prescale' setting, a period setting, and a postscale setting. Then look at the setup_timer_2 function, and the three values this takes, set the prescale, period, and postscale - the same!....

The problem is that you are working with hardware, and as such it is the hardware data you need to start with.

I posted some time ago, in another thread, the sources of data that you needed to look at when working with CCS, and a PIC. The 'C programming language' (K&R), was there, but the chip data sheet came _above_ it in the list.

Though these languages have as their core, 'C', it is an understanding of what the hardware abilities are, that has to 'lead' your use of the functions, and where you look for answers.
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