Pulse-width modulation (PWM), or pulse-duration modulation (PDM), is a commonly used technique for controlling power to inertial electrical devices, made practical by modern electronic power switches.
The average value of voltage (and current) fed to the load is controlled by turning the switch between supply and load on and off at a fast pace. The longer the switch is on compared to the off periods, the higher the power supplied to the load is.
The term duty cycle describes the proportion of 'on' time to the regular interval or 'period' of time; a low duty cycle corresponds to low power, because the power is off for most of the time. Duty cycle is expressed in percent, 100% being fully on.
The main advantage of PWM is that power loss in the switching devices is very low. When a switch is off there is practically no current, and when it is on, there is almost no voltage drop across the switch. Power loss, being the product of voltage and current, is thus in both cases close to zero. PWM also works well with digital controls, which, because of their on/off nature, can easily set the needed duty cycle.
PWM in AVR ATMEGA8:
This project is a simple PWM program that increases/decreases width 20% when switch SW1/SW2 is pressed. The current pulse duration is displayed in the LCD module.
The PWM output is taken through OC1A & OC1B pins of ATmega 8 MCU. The PWM mode is fast pwm WGM=6, non-inv mode.
Code:
//Fclkio=2MHz for FCPU=2MHz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
/*****************MACRO's DEFINITION*********************************/
#define BIT(x) (1 << (x)) //Set a particular bit mask
#define CHECKBIT(x,b) (x & BIT(b)) //Checks bit status
#define SETBIT(x,b) x|=BIT(b); //Sets the particular bit
#define CLEARBIT(x,b) x&=~BIT(b); //Sets the particular bit
#define TOGGLEBIT(x,b) x^=BIT(b); //Toggles the particular bit
#include "lcd.h"
void WaitMs(unsigned int ms);
#define PRT PIND
#define sw1 0
#define sw2 1
#define sw3 2
#define sw4 3
#define TIME 150
unsigned int button(unsigned char PIN);
unsigned int width_us = 204,w=200; //Default Pulse width in us.
void set_PWM(void);
int main()
{
unsigned int step=101;//19% of 512
DDRD=0xC0; PORTD=0xFF;//enable PD as i/p & enable pull-ups
//fast pwm WGM=6, non-inv mode
TCCR1A=0xA2;
TCCR1B=(1<<WGM12);
SETBIT(DDRB,1)//set OC1A as o/p
CLEARBIT(PORTB,1)//clear PB1/OC1A
SETBIT(DDRB,2)//set OC1B as o/p
CLEARBIT(PORTB,2)//clear PB1/OC1B
LCDInit(BBLINK);
WaitMs(200);
LCDWriteStringXY(0,0,"Switch= *");
LCDWriteStringXY(0,1," Width= us");
set_PWM();
SETBIT(TCCR1B,CS10)//start tim1 @ Fclkio
while(1)
{
TOGGLEBIT(PORTD,7)
if(button(sw1)) //If SW1 is pressed then..
{
width_us += step; //Set pulse width to 2ms
LCDShowValueXY(8,0,1);
set_PWM();
WaitMs(1000);
}
if(button(sw2)) //If SW2 is pressed then..
{
width_us -= step; //Set pulse width to 1.5ms
LCDShowValueXY(8,0,2);
set_PWM();
WaitMs(1000);
}
if(CHECKBIT(TIFR,TOV1)==1) TOGGLEBIT(PORTD,6)
}
return 0;
}
/* waits (pauses) for ms milliseconds */
void WaitMs(unsigned int ms)
{
unsigned int m;
for(m=0;m<=ms/10;m++)
{
_delay_ms(10);
}
}
void set_PWM(void) //Load appropriate value onto OCR1A & OCR1B Register according to option chosen.
{
OCR1B = w;
w=(width_us &0x01FF);
LCDWriteIntXY(8,1,w,3);
OCR1A = w;
}
/******** SWITCHES *******/
unsigned int button(unsigned char PIN)
{
if(CHECKBIT(PRT,PIN) == 0)
{
WaitMs(TIME);
if(CHECKBIT(PRT,PIN) == 0)
{
return 1;
}
else
return 0;
}
return 0;
}
Viewers comments are encouraged.
This helps us to much more.
Thank you!!!