View previous topic :: View next topic |
Author |
Message |
Dan Guest
|
16C765 and PWM smallest frequency ? |
Posted: Thu Jan 08, 2004 12:02 pm |
|
|
Hello,
I know this is another question on PWMs and that this subject has been much covered; yet, after having read the documentation + posts, it is still not clear to me what smallest PWM frequency I can expect to get with my 16C765 running at 4x6MHz (24MHz)...
Can anyone give me a simple explanation?
Thanks in advance,
Dan |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 08, 2004 5:13 pm |
|
|
The frequency calculation goes like this:
Code: |
Crystal Frequency
PWM Freq = -----------------------------------------
(PR2 + 1) * (Timer2 Prescaler) * 4 |
The Timer2 prescaler can have values of 1, 4, or 16.
PR2 can have a value from 0 to 255.
So the lowest PWM frequency for your application would be:
Code: |
24 MHz 24,000,000
----------------------- = --------------- = 1465 Hz
(255 + 1) * 16 * 4 16,384 |
Here is a test program for this:
(I don't have a 16c745 to test, so I'm putting in the
likely fuse values that I think you would use).
Code: | #include <16c745.h>
#fuses H4, NOWDT, NOPROTECT, PUT // H4 = use x4 PLL mode
#use Delay(clock=24000000)
main()
{
output_low(PIN_C2); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_16, 255, 1); // Setup for 1465 Hz
set_pwm1_duty(128); // 50% duty cycle
while(1); // Prevent PIC from going to sleep
} |
|
|
|
Guest
|
|
Posted: Fri Jan 09, 2004 5:03 am |
|
|
Thanks for your thorough and clear reply.
Ouch.... that's what I feared.
I tested it and I (indeed) get 1477Hz or so.
Is there any trick to go down to 50Hz? It would be a shame to have to use a low speed Microcontroller just to be able to get a low speed PWM...
One of the aims of the application is to drive a Hobby servo with this PWM. It requires a 50-100Hz frequency PWM with pulses width going from 1 to 2ms.
I also use this controller to do other things that require more processing power, hence the 24MHz.
Thanks again in advance for any help.
Dan. |
|
|
Ttelmah Guest
|
|
Posted: Fri Jan 09, 2004 5:58 am |
|
|
Anonymous wrote: | Thanks for your thourough and clear reply.
Ouch.... that's what I feared.
I tested it and I (indeed) get 1477Hz or so.
Is there any trick to go down to 50Hz? It would be a shame to have to use a low speed Microcontroller just to be able to get a low speed PWM...
One of the aims of the application is to drive a Hobbty servo with this PWM. It requires a 50-100Hz frequency PWM with pulses width going from 1 to 2ms.
I also use this controller to do other things that require more processing power, hence the 24MHz.
Thanks again in advance for any help.
Dan. |
The PWM controller, is designed to allow high frequencies to be generated, without needing the processor to do any work. At low frequencies, there are a number of choices available:
1) Treat the PWM source as a frequency source (by changing PR2), and feed the output into an external 'down' counter, which stops at 0. Then use an interrupt on the processor, to reset the counter, and set the PWM frequency (which will then determine the pulse width).
2) Generate a 'software' PWM, using an interrupt programmed at (say) 1mSec intervals. The interrupt code needs only decrement two counters, one for the PWM repeat rate, and one to clear the pulse. So if (for instance), you program Timer0, to use /16, and generate an interrupt, it will interrupt (using the internal clock), every 1/1464 sec.
Then code like:
Code: |
global int8 width=0;
#define LOOPCNT (30);
#INT_RTCC
void tick_interrupt(void) {
static int8 loop=LOOPCNT;
static int8 pulse;
if (--loop == 0) {
loop=LOOPCNT;
pulse=width;
}
if (width) {
output_high(YOUR_PIN);
--width;
}
else output_low(YOUR_PIN);
}
|
This is suprisingly efficient (more so if 'fast_io' is used), and in the main code, you can set 'width' to a value from 0 to 29, to determine the width of pulse to be generated.
This will run at 48.8Hz.
Best Wishes |
|
|
Guest
|
|
Posted: Fri Jan 09, 2004 7:45 am |
|
|
OK... Although I am not 100% sure how your code works (what is the use of "pulse"?) I am getting some insight on the use of PWMs and other means to reach my goal. God bless you.
Dan. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Jan 09, 2004 8:05 am |
|
|
Maybe a typo. I think he meant this:
Code: |
global int8 width=0;
#define LOOPCNT (30);
#INT_RTCC
void tick_interrupt(void) {
static int8 loop=LOOPCNT;
static int8 pulse;
if (--loop == 0) {
loop=LOOPCNT;
pulse=width;
}
if (pulse) {
output_high(YOUR_PIN);
--pulse;
}
else output_low(YOUR_PIN);
}
|
|
|
|
Ttelmah Guest
|
|
Posted: Fri Jan 09, 2004 11:05 am |
|
|
Mark wrote: | Maybe a typo. I think he meant this:
Code: |
global int8 width=0;
#define LOOPCNT (30);
#INT_RTCC
void tick_interrupt(void) {
static int8 loop=LOOPCNT;
static int8 pulse;
if (--loop == 0) {
loop=LOOPCNT;
pulse=width;
}
if (pulse) {
output_high(YOUR_PIN);
--pulse;
}
else output_low(YOUR_PIN);
}
|
|
It was a typo. As you correctly worked out I meant to count with 'pulse'. The point of the two variables, is that 'width' can be set in the main code, and doesn't get changed in the interrupt. Pulse contains a copy of this, set on the rising 'edge' of the PWM, that is then counted down to determine when the pulse should stop. :-)
Best Wishes |
|
|
sokrates
Joined: 14 Mar 2007 Posts: 12
|
Postscaler ? |
Posted: Fri Mar 16, 2007 9:01 pm |
|
|
I think noone mentioned the postscaler option of PIC timer2.
Is it because it's not applicable here? Or everyone misses it?
Postscale can (supposedly) scale the final frequency by a factor of 16
So at any rate, the initial frequency can be arranged to the 16 times ( 50 Hz ) or so...
However, I have problems in testing this "postscale" function.
Can anyone look at this*
Thanks �
Sokrates |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
diogoc
Joined: 12 Feb 2008 Posts: 19
|
|
Posted: Wed Mar 18, 2009 12:14 pm |
|
|
do you have already tested with PR2=0 ?
i get a constant 5v :S
so max freq i can get is FOSC/8
im doing something wrong? |
|
|
|