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 CCS Technical Support

my PWM problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
giberon
Guest







my PWM problem
PostPosted: Wed Mar 16, 2005 1:27 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 2:14 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 2:18 pm     Reply with quote

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
PostPosted: Wed Mar 16, 2005 3:47 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 4:05 pm     Reply with quote

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
PostPosted: Wed Mar 16, 2005 4:15 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 7:39 pm     Reply with quote

PCM programmer wrote:
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


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

View user's profile Send private message

PostPosted: Thu Mar 17, 2005 7:02 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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