0

I am using the libraries provided by C18 compiler to open and set the duty cycle for PWM usage. I noticed that the max PWM frequency I can get with 100% duty-cycle is about 13.5 KHz. The lower the duty-cycle the higher the PWM frequency. How can I achieve a higher PWM frequency with still 100% duty-cycle? Is it possible to at least get more than 13.5 KHz? I just can't figure out what I missing, maybe someone can help here, and I am using PIC18F87J1.

Here is the C18 C Compiler Libraries

Here is PIC18F87J1 datasheet

Here is a snippet of the code I am using regarding PWM.

 TRISCbits.TRISC1 = 0;
 OpenTimer2(TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1);
 OpenPWM2(0x03ff);
 SetDCPWM2(255);

Your help is appreciated, thanks!

Ammar
  • 1,203
  • 5
  • 27
  • 64
  • 1
    That duty cycle and frame rate are linked seems surprising, perhaps you have the timers misconfigured. Speaking generally without looking at the details of your platform, check that the processor clock is running at its maximum rate, that any available PLL clock multiplier is in use, and that you do not have any system, peripheral, or counter **prescalar** active, as these would reduce the clock going into the counter. – Chris Stratton May 07 '14 at 16:50
  • The processor clock is running at 8 MHz and I don't think I have any other counter prescalar active that could effect the frequency. I did noticed that changing the prescalar value from 1:1 to 1:4 or higher gave me less pwm frequency. – Ammar May 07 '14 at 16:55
  • Is the Duty cycle and pwm frequency inversely proportional to each other? – Ammar May 07 '14 at 18:56
  • 1
    No, normally they are independent, with one timer (section) or mode generating the overall period and another generating the on-time. Are you sure the duty cycle is meaningfully changing, and that you aren't just varying the on-time, with the period being only trivially (one count or so) greater? – Chris Stratton May 07 '14 at 18:58
  • How can I get 1 KHz pwm frequency? Changing the open timer2 to the following gives me 490 Hz regardless what the duty cycle is. `OpenTimer2(TIMER_INT_OFF & T2_PS_1_16 & T2_POST_1_16);` So now I just need to increase the pwm freq to 1 KHz. By the way its normal that the pwm frequency doesn't change when changing the duty cycle changes, right? – Ammar May 07 '14 at 19:32
  • "PWM period =[(period ) + 1] x 4 x TOSC x TMR2 prescaler" So with 0x3ff (1023) you get a factor of 4096, while your 490Hz implies a factor of 16384, leaving a mystery factor of 4 since you seem not to use the prescalars? Anyway, if you make the period smaller you will get a higher frequency, though a more limited granularity of adjustment since the on-time can be no higher than the period. – Chris Stratton May 07 '14 at 19:49
  • 1
    Make sure that your setting of the OSCCON register is really giving you 8 MHz. Your chip also has an x4 PLL, if you start using that you will have a 32 MHz clock and increase your PWM timing or resolution. – Chris Stratton May 07 '14 at 19:57

1 Answers1

1

For a start, you have the parameters to the functions reversed. Open() takes a char value less than 256, and Set() takes a 10-bit number.

That said, you have chosen the largest value (255) which gives the lowest frequency. As the datasheet explains, the Open() function takes a value for the period as the parameter. A higher frequency is equivalent to a shorter period, and vice versa.

Lastly, why would you want a duty cycle of 100%? That is the same as having the pin always high. In that case, frequency doesn't matter at all. Just turn the pin on and don't use PWM at all.

You haven't said what you are driving with this PWM, but generally speaking, having the frequency too high can cause problems. It can produce radio interference, overheat, and so on.

Your question indicates you misunderstand the purpose of PWM and what the terms refers to, so here is a tl;dr.

PWM simulates a voltage between 0 and Vcc by rapidly turning a pin high and low. The simulated voltage is proportional to the time_high/(time_high + time_low). The percent of time the pin is at Vcc is called the duty cycle. (So 100% duty is always on, giving Vcc volts. 0% duty is always off, giving 0 V.)

The rate at which this on/off cycle repeats is called the PWM frequency. If the frequency is too small (the period too long) the load will see the pin voltage fluctuating. The goal is to run the PWM fast enough to smooth out the voltage the load sees, but not so fast as to cause other problems. The available frequencies are appropriate for most applications. Also note that setting the frequency high (period small) will also reduce the accuracy of the duty cycle. This is explained in the datasheet. The reason is basically that the duty cycle must ultimately be converted to clock ticks on versus clock ticks off. The faster the frequency, the fewer ways to divide the clock ticks in each cycle.

UncleO
  • 8,299
  • 21
  • 29
  • 490 Hz is a pretty low frame rate, wanting to go faster than that is normal - 13.5 Khz is not unreasonable - probably something that can be achieved from the 8 MHz clock and almost certainly from the 32 MHz PLL clock. An no, simulating a voltage is only one purpose of PWM. – Chris Stratton May 07 '14 at 20:33
  • 1
    @ChrisStratton I think you made an error in your earlier comment. Open() takes a char value, so 0x3ff is not a valid input. If it compiled, it would be read as 0xff, giving a different frequency than the one you calculated. – UncleO May 07 '14 at 20:41
  • Yes, but that only means the discrepancy between theory and observed result is 16x instead of 4x. Any idea where that extra factor over the formula in the data sheet is coming from? – Chris Stratton May 07 '14 at 20:49
  • 1
    @ChrisStratton I get 490 Hz from the formula. 8000000/(256*4*16) = 488. What is your question? – UncleO May 07 '14 at 21:43
  • What do you think causes the factor of 16? The 4 is built into the formula, but the poster seems to be setting all the prescalers to 1:1 - do you see a mistake in that? If that factor of 16 can be eliminated they will be closer to the goal, though to achieve it I think they will need the PLL to up the source clock (32M / 2 / 4 / 256 = 15.625 KHz meeting "at least get more than 13.5 KHz" – Chris Stratton May 07 '14 at 21:57
  • @ChrisStratton, in the original post I didn't use any prescalars, but in the comments above under my question where I was talking to you, I did use 1:16 prescalar and that gave me 490 Hz. I hope there is no confusion. Then I asked you how to raise it up to around 1 KHz. – Ammar May 07 '14 at 22:09
  • 1
    Hi Ammar. To set the frequency to 1 kHz, use the formula to set the period appropriately. The number use use in the open() function will depend on your prescalars. 1 kHz means a period of 1 millisecond or 1000 microseconds. Tosc is 0.125 microseconds. If you set the prescalar to 1:16, an input of 125 should give you the frequency you want. – UncleO May 07 '14 at 22:21
  • @UncleO, I understand your answer and the above post. I will change the period to 125 tomorrow then will confirm if everything is working as expected. In the meantime both of you guys deserve some thumbs ups. – Ammar May 08 '14 at 00:41
  • 1
    Oops! I forgot the +1 in the formula. The number you want to use is 124. Sorry. – UncleO May 08 '14 at 00:54
  • @UncleO the pwm frequency did indeed work by changing the period to 124. One more question, does that mean the duty-cycle has to be less than 124? So this function `SetDCPWM2(duty-cycle);`would be set to 124 or less right? The duty-cycle doesn't go above the period right? – Ammar May 08 '14 at 15:09
  • The documentation is confusing and contradictory, so you will have to experiment. My best guess is that there is an extra factor of 4, so that the duty cycle needs to be less than 500 = 125*4 (but maybe less than 496). Try 250 and see if the voltage on the pin measures as Vcc/2. – UncleO May 08 '14 at 18:14