Pulse Width Modulation (PWM) is a technique where digital input is used to control the amount of power transferred to a load. This can be used to control motor speed, LED brightness etc.
Modulating the duty cycle varies average DC value of the signal can be varied. The energy delivered depends on the ratio of ON and OFF time as well as the frequency of the pulses.
Pulse Width: refers to the amount of time the signal is high.
Duty Cycle: refers to the ratio of ON time to the total time period. It is expressed in Percent, 0% means signal is OFF, 50% means equal ON and OFF time, 100% means signal is high. Other values can be calculated by:
(Percent / 100) * 255 (for 8 bit Resolution)
for e.g to have a 75% duty cycle, (75/100) *255 = 192
PWM is done with the CCP Module in PIC Microcontrollers. CCP stands for Compare Capture Pulse Width Modulation.
MikroC has a rich set of Library Functions to perform this task easily.
MikroC PWM Functions:
- PWMx_Init
- PWMx_Start
- PWMx_Set_Duty
- PWMx_Stop
You can read more about this library functions from MikroC help file.
** Before Using this functions make sure that PWM is checked in the Library manager.
*** Remember to check your datasheet to know the port pin associated with each pwm module
MikroC Code:
/**********************************
Project Name :
Push Button & PWM with 16F877A
Author : Promise
Description :
This project demonstrate using of push button to vary the duty cycle of PWM on CCP1 (PORTC Bit2)
Test configuration:
MCU: PIC 16F877A
Oscillator: XT 8.0000 MHz, 8.0000 MHz Crystal
***********************************/
unsigned short current_duty;
void Init() {
CMCON = 0x07; // turn off Comparator
ADCON1 = 0x06; // digital input
PORTA = 0;
TRISA = 255; // configure PORTA pins as input
PORTC = 0; // set PORTC to 0
TRISC = 0; // PORTC pins as output
PWM1_Init(5000); // Initialize PWM1 module at 5KHz
}
void main() {
Init();
current_duty = 200; // current_duty initial value
PWM1_Start(); // start PWM1
PWM1_Set_Duty(current_duty); // Set current_duty for PWM1
do { // endless loop
if (PORTA.B0==1) { // button on RA0 pressed
Delay_ms(20); // Switch debounce
if (PORTA.B0==1){
current_duty++; // increment current_duty PWM1_Set_Duty(current_duty); // Set duty to Current Duty delay_ms(10); }
} if (PORTA.B1==1) { // button on RA1 is pressed Delay_ms(20); if (PORTA.B1==1) {
current_duty--; // decrement current_duty PWM1_Set_Duty(current_duty); delay_ms(10); } } if(current_duty==255){ current_duty = 200; PWM1_Set_Duty(current_duty); Delay_ms(5); // slow down } } } while (1); }
Proteus Schematic :
current_duty++; // increment current_duty PWM1_Set_Duty(current_duty); // Set duty to Current Duty delay_ms(10); }
} if (PORTA.B1==1) { // button on RA1 is pressed Delay_ms(20); if (PORTA.B1==1) {
current_duty--; // decrement current_duty PWM1_Set_Duty(current_duty); delay_ms(10); } } if(current_duty==255){ current_duty = 200; PWM1_Set_Duty(current_duty); Delay_ms(5); // slow down } } } while (1); }
Proteus Schematic :
No comments:
Post a Comment