|
|
View previous topic :: View next topic |
Author |
Message |
rashworth
Joined: 23 Jan 2004 Posts: 4 Location: Silverstone UK
|
PWM Not working Correctly |
Posted: Fri Oct 02, 2009 9:12 am |
|
|
I am having a few problems getting the right PWM duty cycle. Frequency is being calculated OK.
Compiler version is 4.013
PIC is 18F4550 with 10-bit PWM resolution.
I want 0-30% duty cycle, but I don't get that. It also changes each time I adjust the TMR2 Offset value to change the frequency (to get optimum MOSFET switching time).
I have included my code - I suspect user error [me] as I am not an expert, however this is an F1 Application, so any help would be appreciated.
Code: | #include <18F4550.h>
//~~~ 48MHZ OSCILLATOR CONFIGS ~~~//
//#fuses EC,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL12,CPUDIV1,VREGEN,NOMCLR//Oscillator is EC 48MHz
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOMCLR//Oscillator is HS 20MHz
//#fuses INTRC,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL2,CPUDIV1,VREGEN,NOMCLR//Oscillator is Internal 8MHz
#device ADC=10;
#use delay(clock=48000000)
#use fast_io(A)
//Defines - Buttons and LED's
#define TOGGLE output_toggle(PIN_C1); //LED to indicate function
#define LED_OFF output_low(PIN_C1);
// Global Variables defines here
unsigned int16 ms1,ms2; //Millisecond timer values (1, 2 & 3)
// Timer 3 is the main interrupt - driven from the system oscillator it will
// Generate an interrupt every 0.2mS
#int_timer3
void isr_timer3(void) {
set_timer3(63135);//to get a 200uS pulse = 65535 - 0.0001*[48e6/(4x2)] =65535-2400= 64335
ms1++; //ms1 is used for main PWM control loop
ms2++; //ms2 is used for house keeping (flashing LED)
}
void main(void)
{
unsigned int16 ADCVal,PWMVal,Enable;
unsigned int1 ON;
//Initialization Here
setup_timer_3(T3_INTERNAL | T3_DIV_BY_2);//Use to generate a 200uS Tick
enable_interrupts(INT_TIMER3);
enable_interrupts(GLOBAL); //enable all interrupts (Else timer3 wont happen)
setup_adc(ADC_CLOCK_DIV_64); //Use the Internal Clock ADC_CLOCK_INTERNAL)
setup_adc_ports(AN0_TO_AN4 | VREF_VREF);//VREF_VREF //Configure for Analog
set_adc_channel(0); //Select the first channel AN0
set_tris_a(0xff); //Ensure all of port A is input
set_tris_c(0b11111111); //Set PWM Pin directions - all inouts so as not to blow MOSFETS
set_tris_d(0b11111111); //Port D PWM Pin directions - all input so as not to blow MOSFETS
port_b_pullups(TRUE);
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_2(T2_DIV_BY_16, 74, 1); // [24KHz is 127 div4], so [15KHz is 199 div4], [10KHz is is 75 div 16]
set_pwm1_duty(0);
ADCVal=0;
PWMVal=0;//PWM Duty cycle
set_tris_c(0b11111001); //Port C PWM Pin directions
set_tris_d(0b00011111); //Port D PWM Pin directions
setup_ccp1(CCP_PWM_FULL_BRIDGE_REV | CCP_PWM_H_H);// Configure the PWM Module - QUAD (H-Bridge)
while (TRUE)
{
if(ms1>=10) //1 tick is 200uS so 10 is 500Hz
{
ms1=0;
set_adc_channel(0);
delay_us(10);
ADCVal=Read_ADC();
delay_us(5);
set_adc_channel(4);
delay_us(10);
Enable=Read_ADC();
//Implement this before plugging into the VC
if(Enable<491 || Enable>532)//Between 2.4, and 2.6 volts to enable on AN4
{
set_pwm1_duty(0);//Motor off
ON=0;
}
//This will make the motor go forwards or backwards
//Implement this before plugging into the VC
if(Enable>491 && Enable<532)//Between 2.4, and 2.6 volts to enable on AN4
{
ON=1;
//Go Forwards
if(ADCVal>=512)//More than 2.5V so go forwards
{
setup_ccp1(CCP_PWM_FULL_BRIDGE | CCP_PWM_H_H);
PWMVal=(ADCVal-512)*0.18;//*0.3;//Restrict to 30%//was 0.48 for 15KHz
set_pwm1_duty(PWMVal);
}
//Go Backwards
if(ADCVal<512)//Less than 2.5V so go backwards
{
setup_ccp1(CCP_PWM_FULL_BRIDGE_REV | CCP_PWM_H_H);
PWMVal=(511-ADCVal)*0.18;//*0.3;//Restrict to 30% Maximum was 511
set_pwm1_duty(PWMVal);
}
}
}
//Housekeeping Items
if(ms2>=250)
{
if(ON)TOGGLE;
if(!ON)LED_OFF;
ms2=0;
}
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 02, 2009 2:08 pm |
|
|
Quote: | I want 0-30% duty cycle, but I don't get that |
Get rid of about 90% of your code and try a simple test program,
as shown in this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=29565&start=1
Try adjusting the value in set_pwm1_duty() to get a 30% duty cycle on
your oscilloscope.
Quote: |
It also changes each time I adjust the TMR2 Offset value to change the
frequency.
|
That's normal. The Timer2 settings control the period of the PWM signal.
The middle value of the setup_timer_2() function (PR2) sets the upper
limit for the duty cycle value. (If the duty cycle number is greater than
the PR2 number, you will get 100% duty cycle). So if you change the PR2
value, but leave the duty cycle number the same, the percentage will
change. If you change the PR2 value, you also have to change the duty
cycle value, if you want to keep the 30% duty cycle. |
|
|
|
|
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
|