Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

pic pwm duty is inaccurate

Status
Not open for further replies.

mugheesnawaz

Member level 1
Joined
May 1, 2013
Messages
39
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,605
i am using a code which takes frequency and dutycycle and give the pulse.frequency works fine (accurate) but duty doesnt always give correct output. i.e if a enter 50 as duty cycle then it will give accurate duty cycle and when i choose 80,it will give 80% duty but when i want 10,20 or 25 then it gives wrong duty but accurate frequency.pwm is the part which i cant figure so far.i know the equations but when i write them it gives errors.i am attaching the code,kindly have a look at it.i will be very thankful.the trouble lies in PWM_Set_Duty function which i am unable to figure out.or kindly give me a pwm function for fixed 25khz frequency and variable duty cycle.i will be very thankful

Code:
Code:
#include <pic.h>
#include <htc.h>
#define _XTAL_FREQ 20000000 
void PWM_Init(float frequency,unsigned char timer_prescalar);
void PWM_Set_Duty(unsigned char duty_cycle,unsigned char timer_presclar);
void PWM_Stop();

unsigned char i=0;
unsigned char flag = 0;
unsigned int value;
void main()
{
unsigned short duty1=20;
unsigned char TimerPrescalar=4;
PWM_Init(25000,TimerPrescalar);
PWM_Set_Duty(20,TimerPrescalar);
while(1)
{
}
}

void PWM_Init(float frequency,unsigned char timer_prescalar)
{

float temp;
TRISC2 = 0;

temp = _XTAL_FREQ/frequency;
temp = temp/4;
temp = temp/timer_prescalar;
PR2 = (unsigned char)(temp);
PR2 = PR2-1;
CCPR1L = 0x00;
CCP1CON = 0x0C; //Set Zero Percent Duty Cycle Initially
TRISC2 = 0; 
if(timer_prescalar == 1)
{
T2CON = 0b00000100; 
}
else if(timer_prescalar == 4)
{
T2CON = 0b00000101; 
}
else if(timer_prescalar == 16)
{
T2CON = 0b00000111; 
}
}
void PWM_Set_Duty(unsigned char duty_cycle,unsigned char timer_prescalar)
{
unsigned int register_value;
float frequency;

frequency = (_XTAL_FREQ/4);
frequency = (frequency/timer_prescalar);
frequency = (frequency/(PR2+1)); //Frequency of PWM Signal

frequency = (frequency*100)/(duty_cycle);

register_value = (_XTAL_FREQ)/(unsigned int)frequency;
register_value = (register_value/timer_prescalar);

CCPR1L = (register_value>>2);
register_value = register_value & 0x03;
CCP1CON = CCP1CON | (register_value<<4);
}
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,478
Helped
14,046
Reputation
28,347
Reaction score
12,700
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,115
You neither mentioned the PIC type nor the compiler version which makes it hard to give specific help.
 

mugheesnawaz

Member level 1
Joined
May 1, 2013
Messages
39
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,605
i am using mplab 8 and pic 16f877a pic microcontroller.soory i forgot to in hurry.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,478
Helped
14,046
Reputation
28,347
Reaction score
12,700
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,115
The problem is that frequency is greater than unsigned int range in this line
Code:
register_value = (_XTAL_FREQ)/(unsigned int)frequency;
- - - Updated - - -

Your code is rather long winded, the problem can be solved much more easily.

Code:
void PWM_Set_Duty(unsigned char duty_cycle)
{
unsigned int register_value;
register_value = (long)(PR2+1)*duty_cycle/25; 
CCPR1L = (register_value>>2);
CCP1CON = CCP1CON & 0xf | (register_value & 3)<<4;
}
 

mugheesnawaz

Member level 1
Joined
May 1, 2013
Messages
39
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,605
Thankyou so much sir,helped me alot :)
its working on proteus and will try on hardware.a big thank you.

it would be a great help if you can provide a general and much simpler code which takes frequency and duty cycle.i want 25khz frequency and 0-100% duty cycle.it would help me avoiding mistakes which was in my code.
 

milan.rajik

Banned
Joined
Apr 1, 2013
Messages
2,528
Helped
540
Reputation
1,078
Reaction score
523
Trophy points
1,393
Activity points
0
Try the attached project. Use a Frequency counter to check the PWM frequency. It should be near or equal to 25 KHz. ADC value varies from 0 to 1023 and PWM duty depends upon adc value. PWM duty can be 0 to 100 %. adcValue is scaled and mapped to pwm duty.

 

Attachments


FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,478
Helped
14,046
Reputation
28,347
Reaction score
12,700
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,115
The attached project doesn't answer the question because it uses (I guess mikroC) built-in functions to operate the PWM unit instead of genuine C code.
 

milan.rajik

Banned
Joined
Apr 1, 2013
Messages
2,528
Helped
540
Reputation
1,078
Reaction score
523
Trophy points
1,393
Activity points
0
Yes. I know but I can only help with mikroC code.
 

mugheesnawaz

Member level 1
Joined
May 1, 2013
Messages
39
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,605
i am using mplab to code my project.anyways you people are a great help :)
thank you so much for your kind replies.appreciate it :)
 

Status
Not open for further replies.
Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top