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 support@ccsinfo.com

Variable pulse-duty-cycle PWM
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

Variable pulse-duty-cycle PWM
PostPosted: Fri Jul 23, 2010 12:11 am     Reply with quote

Hello

I'm trying to implement a PWM at 4khz.
However, what I need mostly is to make each cycle of this pwm have a different duty cycle (in an attempt to generate a sine wave). Some people suggested that I use Timer 1 to generate interrupt every 4khz frequency and in the ISR I change the PWM duty cycle. I tried it but it is not working maybe because I did it wrong.

Can anybody suggest something or give me some code to do this. I'm using PIC16F877A. XT=8MHz (to get exact 4KHz PWM frequency).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 23, 2010 12:25 am     Reply with quote

Change the duty cycle of the PWM inside an #int_timer2 interrupt routine.
Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=41473&start=3

Get the duty cycle from a sine lookup table. Here are some CCS
example files that use sine lookup tables:
Quote:

c:\program files\picc\examples\ex_dtmf.c
c:\program files\picc\examples\ex_sine.c
c:\program files\picc\examples\ex_usb_scope.c
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Fri Jul 23, 2010 3:24 am     Reply with quote

It doesn't look that this is what i needed so to be more specific, here is a link on what i'm trying to do

www.pu.edu.pk/ceet/Pages/Prospectus.pdf

please PCM Programmer help me implement the idea in this article.

what i'm trying to do first is to generate the variable PWM duty cycle for the sine wave shownin the figure page 2 figure 3.
can this kind of figure be implemented in MCU

Thanks in Advance
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 23, 2010 9:43 pm     Reply with quote

I don't want to write your program for you. I suggest that you use
Google to search for code using these search terms:
Quote:

pwm "sine wave" void main


Or you can search for CCS code with this:
Quote:

pwm "sine wave" "#use delay"

But not all of the code will be certain to work correctly. You will have to test it.
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Sat Jul 24, 2010 12:30 am     Reply with quote

Ok PCM Programmer I wasn't really looking for someone to write me the code all I needed is some help and ideas. Anyway I re-arranged the code that you supplied and it is working fine for me now.

But I need to ask you two more questions

First is about the pwm resolution and what does it mean exactly.
What I understood it that it represents how many value of the duty cycle you can put in one period. However, when programming, I noticed that even if I have a 10-bit resolution, I can't go anywhere above the value of the PR2 register. For example, if I have a 10-bit resolution, I can choose one from the 65536 values of the duty cycle. However, if the PR2 is 126, say, any value above the 126 will result in a 100% duty cycle. So please explain it to me.

Second question is, do you only spend all your time in programming, as I see that you reply to all people in all domains, day and night. Really!!.
How come you have that passion and that time to do that man, knowing that I congratulate you and appreciate the enormous help you are providing, but I have the curiosity to ask you.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 24, 2010 3:10 pm     Reply with quote

Quote:
First is about the pwm resolution and what does it mean exactly.

Read this section of the 16F-series Reference Manual:
http://ww1.microchip.com/downloads/en/devicedoc/31014a.pdf

2nd question:
6 hrs. sleep/day.
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 1:48 am     Reply with quote

OK PCM Programmer, one more problem

here is my new problem

I'm using a crystal oscillator at 8MHz, and i wish to get a 4KHz pwm frequency. according to the wizard in CCS, it generated a code with PR2=124 and timer2 prescaler=4. at these frequencies, according to the resolution formula, i can get a 10-bit resolution. However, any value that i insert which is greater than the PR2 value results in a fault.

please explain this for me and how to manage the relationships between xt value and PWM frequency and resolution all together.

i tried 10000000000000 of examples that i did changing some value each time for the pr2, the PWM frequency and the prescaler.

All gave the same confusion

will you please remove the confusion and help me
Ttelmah



Joined: 11 Mar 2010
Posts: 19388

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 1:56 am     Reply with quote

The maximum available PWM value, is always:

((PR2+1)*4)-1

So with PR2 at it's largest possible value (255), you get:

((255+1)*4)-1 = 1023

With your PR2 value (124), you will get 499. Just under 9 bits, not 10 bits.

Remember also, that the value fed into the set PWM duty function, _must_ be a 'long' integer, not a default 8bit integer, or you will lose two bits from the bottom of the allowable values.

Best Wishes
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 2:15 am     Reply with quote

Now this is something useful.

Thanks Ttelmah, but this means that there is something wrong with the formulas in the datasheets, or they are missing something. Would you mind writing the right ones for me. And if you may, please post some code that gives me the best resolution for a 4khz frequency of pwm, no matter what the xtal frequency is (you choose it).

Thanks in advance
Ttelmah



Joined: 11 Mar 2010
Posts: 19388

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 3:13 am     Reply with quote

No, the formulae in the data sheet are exactly right. I think you are misinterpreting them....

If you look at table 8.3 for example, you will see that the 'bit length' of the available range, is the bit length of the PR2 value, plus two bits. So it is only 10 bits, when PR2 contains a value 'filling' the 8bit range (0xFF). Anything less and the value drops.

Remember 'Fosc' feeding the PWM, is _after_ the prescaler.
In your case, Fosc, is 2MHz. So the formula gives:

log(2000000/4000)/log(2) = 8.96

Just under 9 bits.

Best Wishes
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 4:27 am     Reply with quote

Thanks Ttelmah this really explains what I was missing.

However, I need your help now in my program.

I'm trying to generate sine wave using pwm. This is the code I'm using. You will see that there is some time at the end of the cycle where the duty cycle suddenly becomes 100% (I think) and then falls back to zero and goes on correctly. Can you please take a look at it in Proteus and tell me what am I doing wrong.
Code:

#include "D:\Projects\CCS C Software projects\Sine Wave Oscillator\Sine Wave Oscillator.h"

#define MAX_DUTY  501
int i=0;
long duty_cycle[21]={0,39,78,117,155,192,227,262,294,325,354,381,405,427,446,463,476,487,495,499,501};

#int_TIMER2
void  TIMER2_isr(void)
{
   static int8 increment = TRUE;

   if(increment)
   {
      i++;
      if(duty_cycle[i] == MAX_DUTY)
      increment = FALSE;
   }
   else
   {
      i--;;   
      if(duty_cycle[i] == 0)
      increment = TRUE;
   }
   set_pwm1_duty(duty_cycle[i]);
}

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_4,124,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(0);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   clear_interrupt(INT_TIMER2);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);

   duty_cycle = 0;
   output_high(PIN_C0);
   output_low(PIN_C1);
   while(1);

}

The header file above include these:
Code:

#include <16F877A.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT                      //Power Up Timer
#FUSES PROTECT                  //Code protected from reads
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=8000000)
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

PostPosted: Tue Jul 27, 2010 6:53 am     Reply with quote

Having done sound semi-successfully myself (see above link), can I suggest that you instead use timer0 for your frequency interrupt, to seperate it out from timer2 which effects your sample resolution?

Change timer2 so you get the resolution you need for your PWM, and let timer0 take care of when you index through your array.
You also want the frequency of the PWM to be much higher than that of your actual sound, otherwise you'll get a heap of ugly aliasing artefacts etc.


As an aside, your "increment" variable is a boolean, so only needs to be int1, not int8. And you've got double ";" after "i--"
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

12f683 problem
PostPosted: Mon Aug 09, 2010 4:22 am     Reply with quote

Ok after trying everything with PIC16F877A (as it was available to me), everything worked fine. Now I switched to PIC12F683 with the same program (of course I made the necessary changes). The results are totally wrong. My program is listed above. Can anybody try it on PIC12F683 and tell what's wrong.
GOBER



Joined: 22 Jul 2010
Posts: 41

View user's profile Send private message

PostPosted: Mon Aug 09, 2010 5:24 am     Reply with quote

I also made this small test program.
Code:

void main()
{
   int i;
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_4,124,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(0);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_8MHZ);

   for(i=0;i<100;i++)
   {
      set_pwm1_duty(i);
      delay_ms(100);
   }

}

It is not working. The pwm duty cycle won't change.
I used the wizard to start my project.

ccs version is 4.104
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 09, 2010 11:38 am     Reply with quote

Here are some programs that show changing the PWM duty cycle:
http://www.ccsinfo.com/forum/viewtopic.php?t=42499&start=7
http://www.ccsinfo.com/forum/viewtopic.php?t=40007&start=1
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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