I have bread boarded the following proteus proffessional project:
The idea is that the rotary switch controls the speed of the 2 DC fans, the high option results in 100% duty cycle, Med 75%, and Low is 50%. The tutorial I followed to configure the PWM module of the PIC16F877A gives this image taken from the IC's manual about how the PWM mode of the MCU basically works:
PWM Signal Generation: Once the PWM is configured and Timer2 is enabled, TMR2 starts incrementing depending on the prescalar. Once the TMR2 value is equal to dutyCycle(CCPR1L+CCP1CON<5:4>) the PWM pin will be pulled LOW. The timer still continues to increment till it matches with the period PR2. After which the PWM pin will be pulled HIGH and TMR2 is reset for next cycle. Source
And so I wrote some code in mikroC where I configure both CCP modules since I need a PWM signal to control the speed of two fans. Here is the snippet of code which is supposed to configure the PWM mode of these CCP registers:
TRISC.RC1 = 0;
TRISC.RC2 = 0;
CCP1CON = 0x0F; // Select the PWM mode.
CCP2CON = 0x0F;
TMR2ON = 1;
PR2 = 100; // Set the Cycle time to 100 for varying the duty cycle from 0-100
CCPR1L = 0; // By default set the dutyCycle to 0
CCPR2L = 0;
When I run the simulation it works in proteus. When I try to upload it to the MCU using my Pick kit 3 I am not getting a PWM signal on PORTC1-2. I have checked that the switch is working using a multimeter and have probed the crystal and found that it is oscillating. The switching mechanism doesn't seem to have a notable effect on the signals on PORTC1-2 apart from maybe some slight glitch when the switch position changes.
Here is a screenshot of what the signal looks like where I am supposed to be getting a PWM wave (PORTC1).
PORTC2 looks the same. Like I said I have monitored the switching mechanism, probed the crystal and the PWM ports. I can't think why this won't work when it does in simulation. Maybe somebody could help me debug this. The rest of the C code is shown here:
int solenoid_state = 0;
void main()
{
//TRISB = 0x0F; // Configure PORTB
TRISB.RB0 = 1;
TRISB.RB1 = 1;
TRISB.RB2 = 1;
TRISB.RB3 = 1;
TRISD.RD0 = 0;
TRISD.RD1 = 0;
TRISC.RC1 = 0;
TRISC.RC2 = 0;
CCP1CON = 0x0F; // Select the PWM mode.
CCP2CON = 0x0F;
TMR2ON = 1;
PR2 = 100; // Set the Cycle time to 100 for varying the duty
cycle from 0-100
CCPR1L = 0; // By default set the dutyCycle to 0
CCPR2L = 0;
//solenoid_state = 0;
while(1){
if(RB0_bit == 0) // Off state
{
delay_ms(300);
if(RB0_bit == 0)
{
CCPR1L = 0;
CCPR2L = 0;
RD0_bit = 0;
RD1_bit = 0;
}
while(RB0_bit == 0) //Do nothing until switch status changes
{
}
}
else
{
solenoid_state = 1;
//RD0_bit = 1;
//RD1_bit = 1;
}
while(solenoid_state == 1)
{
if(RB1_bit == 0) // Low state
{
delay_ms(300);
if(RB1_bit == 0)
{
CCPR1L = 50;
CCPR2L = 50;
}
while(RB1_bit == 0) //Do nothing until switch status changes
{
}
}
else if(RB2_bit == 0) // Med state
{
delay_ms(300);
if(RB2_bit == 0)
{
CCPR1L = 75;
CCPR2L = 75;
}
while(RB2_bit == 0) //Do nothing until switch status changes
{
}
}
else if(RB3_bit == 0) // High state
{
delay_ms(300);
if(RB3_bit == 0)
{
CCPR1L = 100;
CCPR2L = 100;
}
while(RB2_bit == 0) //Do nothing until switch status changes
{
}
}
else
{
//RD0_bit = 0;
//RD1_bit = 0;
solenoid_state = 0;
}
}
}
}
Any tips/hints appreciated,
Simon.
CCPR1L
andCCPR2L
assignments and stick them in an area without conditions (such as right before your while loop) and comment everything else out to make sure the PWM itself is working. Then you know if you have a logic error or truly a PWM problem. \$\endgroup\$