|
|
View previous topic :: View next topic |
Author |
Message |
giberon Guest
|
my PWM problem |
Posted: Wed Mar 16, 2005 1:27 pm |
|
|
hi ,
im tryin to generate 50Hz PWM frequency with PIC16F876 at 4MHz clock frequency and after reading data sheet i calculated PR2 value at Timer prescaler value 1. Im gettin PR2 value more than 255 which i can't use to set the PWM frequency . can anybody help me please.
PR2 = (period/(4*Tosc* TMR2 Prescale)) - 1;
for my program PWM is 50Hz = 20msec;
TMR2 prescale= 1;
and Tosc = 4MHz;
PR2 = (0.002/(4*2.5 *0.0000001*1)-1 >>>255
how can i get PR2 value less than 255.
can i use this Timer2 to set the PWM to 50Hz and to get variable dutycycle.IS there anyother way to generate such a low frequency PWM on PIC16F876.Thanx 4 ur help. |
|
|
DragonPIC
Joined: 11 Nov 2003 Posts: 118
|
|
Posted: Wed Mar 16, 2005 2:14 pm |
|
|
setup_timer_2(T2_DIV_BY_2,0x2710,1);//period = 20ms
set_pwm2_duty(0x4E20); //.01/(2*(1/4Mhz))
change the duty cycle by changing the value in set_pwm2_duty() (sending a variable instead of a contant). _________________ -Matt |
|
|
mvaraujo
Joined: 20 Feb 2004 Posts: 59 Location: Brazil
|
|
Posted: Wed Mar 16, 2005 2:18 pm |
|
|
Hi!
I would calculate like this:
1) Consider the PWM period that you need, the Tosc and calculate the prescaler that goes near to the result (if there is one, it can happen to be impossible to meet the desired PWM period);
2) Return to the expression and calculate the PR2 for the prescaler you have chosen.
For the PWM period you mentioned you could consider using only a timer and interrupt. Search the forum for applications like this.
Other way is to decrease XTAL frequency until you reach a resonable result for your PWM but you're paying a price for that, right?
Marcus |
|
|
giberon Guest
|
MY PWM problem |
Posted: Wed Mar 16, 2005 3:47 pm |
|
|
hi DragonPIC,
Thanx for ur suggestion but i got a small problem could u please help me.
i wrote a simple program with ur suggestion and compiled and my error was Undefined identifier T2_DIV_BY_2 . i later checked my version of PIC compiler and realized that my compiler version was 3.6. I checked the ccs data sheet for the function set_timer_2 and it says that only three modes can be used are: Syntax: setup_timer_2 (mode, period, postscale)
mode • T2_DISABLED, T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
period is a int 0-255 that
my below program is for a DC servo motor in which the angle is given at fixed PWM frequency of 20ms and read by delay1 and converted into microseconds and given to value. then duty cycle is caluculated adn given to pwm function.
#include <16F876.h>
#device 16F876 ICD=TRUE
#use delay(clock=4000000)
#fuses XT,NOWDT, NOPROTECT, NOPUT, NOBROWNOUT
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK) // Jumpers: 8 to 11, 7 to 12
#define pin0 56
main() {
long value,duty;
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_2,0x2710,1);//period = 20ms
// The cycle time will be (1/clock)*4*t2div*(period+1)
// In this program clock=4000000
// For the three possible selections the cycle time is:
// (1/4000000)*4*2*10000 = 20ms
setup_port_a(ALL_ANALOG);
setup_adc(adc_clock_internal);
set_adc_channel( 0 );
while( TRUE ) {
delay1=read_adc();
value=(angle)*(1000/180);
duty= value/(2*(1/4*1000000))
printf("%2X\r",value);
set_pwm1_duty(duty); // duty= value/(t2div*(1/clock))
} |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 16, 2005 4:05 pm |
|
|
Quote: | setup_timer_2(T2_DIV_BY_2,0x2710,1);//period = 20ms
set_pwm2_duty(0x4E20); //.01/(2*(1/4Mhz)) |
Timer 2 is 8 bits. You can't set it to 0x2710.
To get a PWM frequency of 50 Hz, you have to use a software PWM.
There is an example at the end of this thread for 100 Hz. You should
be able to modify it to work at 50 by changing one constant.
http://www.ccsinfo.com/forum/viewtopic.php?t=20050
More info on PWM calculations:
http://www.ccsinfo.com/forum/viewtopic.php?t=17993 |
|
|
giberon Guest
|
My PWM problem |
Posted: Wed Mar 16, 2005 4:15 pm |
|
|
hi mvaraujo
thanx for ur suggestion.
I have gone through the forums for using interrupts and timers for PWM but ididn't find any for such a low frequency PWM. i wrote a program in turboC to control a servo motor at specific angle for 20ms pulse width in which i enabled timer0 interupt enable flag so when it overflows ($FF + 1) bit 2 of INTCON is raised (TMR0IF). the prescaler was set for timer 0 through option register .
TMR0 value = 256 – DelayCycles
the prescaler for 20ms was calculated
DelayCycles = (20ms)s * (4Mhz)s / 8
= 20 * (10‐3) * 4 * (106) / 8
= 20 * 4 * (103) / 8 = 80,000 / 8 = 10,000
In order to make this number smaller than 256, i divided it by two 6
consecutive times:
10,000÷2 = 5,000÷2 = 2,500÷2 = 1,250÷2 = 625÷2 = 312.5÷2 = 156.25
256 – 156.25 = 99.75 ≈ 100
TMR0Value was 100. From the calculation above, the prescaler
ratio was 1:64 . The power 6 is represented in binary by 110 assigned to bits PS2:PS0 of the OPTION_REG register.
interrupt procedure triggered by TMR0 by checking the value of bit INTCON .TMR0IF. when flagServo was signaling pulse was send to servo.
and the pulse width is formed by creating a delay in the main body before
clearing the servo pin again.
I tried to write this program in CCS compiler . i read the data sheet but i couldnt really set the prescaler for timer0 for generating interrupt. could u please help me generate the interrupt using timers. and also i tried to get the control of servo motor angle by using only delay_us function and without ant interrupts and timers but i was not getting the exact angle on servo motor. is there any way to get a exact pulse on servo motor without using interrupts and timers. help me please
thanx. |
|
|
DragonPIC
Joined: 11 Nov 2003 Posts: 118
|
|
Posted: Wed Mar 16, 2005 7:39 pm |
|
|
My bad, when I was at work I thought the datasheet said 16-bit. Either the one I have at work is wrong or I looked at timer 1 instead. _________________ -Matt |
|
|
mvaraujo
Joined: 20 Feb 2004 Posts: 59 Location: Brazil
|
|
Posted: Thu Mar 17, 2005 7:02 am |
|
|
Hi giberon,
Examples presented by PCM programmer represent very well what I mentioned. Study them and you'll get a way to generate software PWM. One example uses a 8bit (RTCC, TMR0) counter but it can be done using other timers.
I have a product with software PWM using PIC "compare module" so you can get a very reliable PWM.
In my case it's PWM that I can control ton and toff of the pulse:
Code: |
(...)
setup_ccp1 (CCP_COMPARE_INT);
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);
(...)
#INT_CCP1
void ccp1_isr (void)
{
if (flags1.estado_p)
{
output_low (IGBT_CMD);
CCP_1 += tempo_ton;
flags1.estado_p = 0;
}
else
{
output_high (IGBT_CMD);
CCP_1 += tempo_toff;
flags1.estado_p = 1;
}
restart_wdt();
}
|
Basically what you do to startup PWM is:
- setup ]tempo_ton and tempo_toff[;
Code: |
tempo_ton = 100; // 10us
tempo_toff = 2400; // 240us
|
- preload CCP1 for a next compare:
Code: |
prox_comp = get_timer1();
prox_comp += 2500;
CCP_1 = prox_comp;
|
- Enable interrupt:
Code: |
enable_interrupts (INT_CCP1);
|
Consider that times mentioned on the code is related to my oscillator (40MHz) on 18F452 |
|
|
|
|
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
|