How much PWM resolution can be achived given a prescaler setting and clock speed.
Multiple Pulse Width Modulation from Scott Dattalo
Dan Michaels PIC/Scenix RAM Table based PWM
Vee (negative supply) from PIC PWM by David Covick
Analog Output with jumper settings for voltage and current ranges
Setting up a 16F87x for PWM output
Compinsating for ISR time loss in a time sensitve main code loop
Pulse Width: 3 instruction resolution and 19 bit range http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/~checkout~/examples/14bit/pulse_measure.asm?rev=1.1&content-type=text/plain&cvsroot=gpsim
See also:
Three Phase Sine Wave Generation using Bit-Bang
Super Bit-Bang PWM for 12-bit PIC
Questions:
Hi,I have a basic doubt.Why do we divide the clock frequency by 4.and how do we calculate the PWM duty cyle using the CCp1rl:CCP1CON registers in detail?
James Newton replies: We don't; the PIC processor does. 1 instruction per 4 clock cycles. See the datasheet for detailed instructions on the PWM setup via the control registers.
Nice catch, yep I did mean 50Hz! Thanks for affirming my suspicions and for suggesting the 32.768 watch crystal.. you did mean 32.768Khz? I am currently looking into that to see how it would affect the timing of the rest of the project. However, I was also thinking of using TMR0 since it allows for a larger prescaler, say 128 which would allow a minimum freq of: pwm_freq = 1E06 / (256 * 128) = 30.5 Hz I just want to know if it is practical to create your own duty cycle in code... Basically I am intending to run some servos off the chip. Thanks for your quick response!
Michael J Mansheim answers
Yes, it is quite practical to do your own pwm in code.Yes, I meant 32.768 KHz, but I wouldn't slow the chip down that much just to use the built-in pwm if you are able to do your own. However, all the calculations from that post apply to the built-in pwm - you have to take a different approach if you do your own.
The easiest way to do your own pwm is with an interrupt running from one of the timers. The frequency you run that timer at is a function of both the pwm frequency and the resolution you need. For example, assume timer2 (since it is presumably available if not using the built-in pwm), a 50 Hz pwm, and a 10 MHz clock. Your original post said 7.5% duty cycle - to get that, you'll need the pwm to be 200 "steps" long, so that you can leave it on for 15 of those steps. So:
200 x 50 Hz = 10 KHz timer2 freq = 2.5E06 / (PR2 + 1) * pre-scale * post-scale if PR2 = 249, pre-scale = post-scale = 1: timer2 freq = 10 KHzIt just so happens that 10 KHz is one of the frequencies you can hit exactly with a 10 MHz clock. I often want a 1 KHz interrupt (1 ms interval), which you can't hit exactly. Roman Black and Bob Ammerman (and undoubtedly others I'm not remembering) have posted techniques for getting exact time intervals by adjusting the timer each time the interrupt happens. You can't do that kind of manipulation when you're using the built-in pwm, but you can when you are doing your own. So anyway, this will cause an interrupt to occur every .1 ms, and you just need to keep track of whether your output needs to be high or low. For 7.5%: on for 15, off for 185, on for 15, ...
And, you are certainly not limited to doing just the pwm in the interrupt, but I always try to keep the code in the interrupt to a minimum. Then, it's just a question of whether the rest of your code can tolerate a short interruption every .1 ms. If you don't want the interruptions to occur as often, you can give up duty cycle resolution.
I'm just starting to experiment with the PIC16F877 using the HITECH C compiler. I am running the PIC at 10 Mhz and want a 50 MHz PWM period with a 7.5% duty cycle. However this means that I need the PR2 to be 3124 which is too large (max is 255 right?). Is there a way around this? am I doing something wrong? or do I have to use a 4MHz clock instead? or maybe create my own pulse using TIMER0 which would allow a prescalar of 256? Thanks in advance!
Michael J Mansheim answers
Are you sure you mean 50 MHz?? Running the pic at 10 Mhz, you can only execute instructions at 10/4 = 2.5 MHz, let alone run the built-in pwm. The formula for pwm frequency in this case is:pwm freq = 2.5E06 / ((PR2 + 1) * pre-scale)if PR2 = 1 and pre-scale = 1, your pwm freq = 1.25 MHz. However, you only have 1 bit of resolution! (off and 50%) The formula for resolution is:
bits of resolution = log(2.5E06/pwm freq) / log(2)which = 1 for pwm freq = 1.25 MHz This also shows why PR2 = 0 won't work: pwm freq theoretically = 2.5 MHz, but the resolution = 0 bits!
If PR2 = 3124 and the pre-scale = 16, the pwm freq = 50 Hz, so I'm guessing that is actually the speed you're looking for?? One problem with the built-in pwm is that there is a definite minimum speed. In this case, it is with PR2 = 255 (the max as you pointed out) and pre-scale = 16 (max available):
pwm freq = 2.5E06 / (256 * 16) = 610 HzSo you can't get to 50 Hz with this clock speed. If you switch to a 4 MHz clock, the minimum pwm freq is:
pwm_freq = 1E06 / (256 * 16) = 244 HzSo you're still not there!
The max clock you can run = 256 * 16 * 50 * 4 = 819.2 KHz So the ever popular 32.768 watch crystal would work, although you wouldn't be able to hit 50 **exactly** - you could get 49.95 Hz.
See:
Archive:
Interested:
Doug Says: " I'm interested in motor control and feedback in FPM "
Comments: