Download Pulse Width Modulation

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Variable-frequency drive wikipedia , lookup

Transcript
Pulse Width Modulation (PWM): Introduction
Introduction
Pulse width Modulation or PWM is one of the powerful techniques used in control systems today. They
are not only employed in wide range of control application which includes: speed control, power
control, measurement and communication. This tutorial will take you through the PWM basics and
implementation of PWM on 8051 and AVR microcontrollers.
Basic Principal of PWM
Pulse-width Modulation is achieved with the help of a square wave whose duty cycle is changed to get a
varying voltage output as a result of average value of waveform. A mathematical explaination of this is
given below.
Consider a square wave shown in the figure above.
Ton is the time for which the output is high and Toff is time for which output is low. Let Ttotal be
time period of the wave such that,
Duty cycle of a square wave is defined as
The output voltage varies with duty cycle as...
So you can see from the final equation the output voltage can be directly varied by varying the
Ton value.
If Ton is 0, Vout is also 0.
if Ton is Ttotal then Vout is Vin or say maximum.
This was all about theory behind PWM. Now lets take a look at the practical implementation of PWM on
microcontrollers.
Idea behind Implementation
The basic idea behind PWM implementation on 8051 is using timers and switching port pin high/low at
defined intervals. As we have discussed in the introduction of PWM that by changing the Ton time, we
can vary the width of square wave keeping same time period of the square wave.
We will be using 8051 Timer0 in Mode 0. Values for high and low level will be loaded in such a way that
total delay remains same. If for high level we load a value X in TH0 then for low level TH0 will be loaded
with 255-X so that total remains as 255.
Assembly Code Example
Timer setup for PWM
PWMPIN EQU P1.0
; PWM output pin
PWM_SETUP:
MOV TMOD,#00H
; Timer0 in Mode 0
MOV R7, #160
; Set pulse width control
; The value loaded in R7 is value X as
; discussed above.
SETB EA
; Enable Interrupts
SETB ET0
; Enable Timer 0 Interrupt
SETB TR0
; Start Timer
RET
Interrupt Service Routine
TIMER_0_INTERRUPT:
JB F0, HIGH_DONE
; If F0 flag is set then we just finished
; the high section of the
LOW_DONE:
; cycle so Jump to HIGH_DONE
SETB F0
; Make F0=1 to indicate start of high section
SETB PWMPIN
; Make PWM output pin High
MOV TH0, R7
; Load high byte of timer with R7
; (pulse width control value)
CLR TF0
RETI
; Clear the Timer 0 interrupt flag
; Return from Interrupt to where
; the program came from
HIGH_DONE:
CLR F0
; Make F0=0 to indicate start of low section
CLR PWMPIN
; Make PWM output pin low
MOV A, #0FFH ; Move FFH (255) to A
CLR C
; Clear C (the carry bit) so it does
; not affect the subtraction
SUBB A, R7
; Subtract R7 from A. A = 255 - R7.
MOV TH0, A
; so the value loaded into TH0 + R7 = 255
CLR TF0
; Clear the Timer 0 interrupt flag
RETI
; Return from Interrupt to where
; the program came from
In your main program you need to call this PWM_SETUP routine and your controller will have a PWM
output. Timer Interrupt service routine will take care of PWM in the background. The width of PWM can
be changed by changing the value of R7 register. In above example I am using 160, you can choose any
value from 0 to 255. R7 = 0 will give you o/p 0V approx and R7 = 255 will give you 5V approx.
You can also make use of Timer1 if you want. And the output pin can be changed to whatever pin you
want.
C Code Example
Timer setup for PWM in C
//Global variables and definition
#define PWMPIN P1_0
unsigned char pwm_width;
bit pwm_flag = 0;
void pwm_setup(){
TMOD = 0;
pwm_width = 160;
EA = 1;
ET0 = 1;
TR0 = 1;
}
Interrupt Service Routine
void timer0() interrupt 1 {
if(!pwm_flag) { //Start of High level
pwm_flag = 1; //Set flag
PWMPIN = 1; //Set PWM o/p pin
TH0 = pwm_width;
//Load timer
TF0 = 0;
//Clear interrupt flag
return;
//Return
}
else { //Start of Low level
pwm_flag = 0; //Clear flag
PWMPIN = 0; //Clear PWM o/p pin
TH0 = 255 - pwm_width; //Load timer
TF0 = 0;
//Clear Interrupt flag
return;
//return
}
}