Tuesday, October 14, 2008

Pulse Width Modulation



Description

Pulse Width Modulation allows microcontrollers to dim lights, control motor speeds, fan speeds and generate analog voltages. By changing the length of the pulse, the output can be controlled. The pulse occurs at a regular frequency, the modulation frequency. The length of the pulse ratio to period time is called the duty cycle.The larger the duty cycle the higher the output is.

The AVR microcontroller can be used to generate PWM signals. The PWM signals can be generated by hardware or by software. An microcontroller like the AT2313 has one hardware PWM on board of the chip. The output of the PWM signal is at the PortB.3(OC1) pin.

The hardware PWM can be programmed by setting the timer registers. The attiny2313 has three timer registers that you need to set to program the PWM:

  1. The Timer/Counter1 Control Register (TCCR1A) is to put the timer in PWM mode.
  2. The Timer/Counter1 registers (TCNT1H and TCNT1L) are used to set the modulation frequency.
  3. The Output Compare Register1 (OCR1A) is used to set the duty cycle.

PWM with the AVR-microcontroller is a matter of comparison. If the Timer/Counter1 is running and the value of the timer is matching the value that is put in the OCR1A register, the OC1 pin changes from high to low. By changing the value of the OCR1A register the lenght of the pulse can be changed.

Hardware

The PWM output can be used to fade a LED in and out. On the picture you can see the LED on a bread-board connected to the ISP-board with a flat-cable.

Software

The software is written with the AVR Studio 4 that uses assembler code. The software uses the hardware PWM of the AT2313 so first the registers of the PWM tiner needs to be set.


;***** PWM demonstration with LED ****
; Demonstrates how to set the PWM mde of the Timer/Counter1
; a LED @ the PWM output at PORTB.3 fades on and off.
; Author : www.laros-edu.net
; Target : AT2313
; Hardware : LED at PORTB.3
;*************************************
.include "2313def.inc"
.def Temp =r16 ; Temporary register
.def pw =r19 ;

;***** Initialization
INIT_SP:

ldi temp,RAMEND
out spl,temp

INIT_PORTB:
ser Temp
out DDRB,Temp ; Set PORTB to output
clr temp
out PORTB,temp ; Set PORTB to 0

INIT_TIMER:
ldi temp,0 ; Set Output Comp Reg H to 0
out OCR1AH,temp
ldi temp,0 ; Set pulse width
out OCR1AL,temp
ldi temp, 0b10000001 ; Set Timer/Counter1 as an 8-bit PWM
out TCCR1A, temp ;
ldi temp, 0b00001001 ; Start Timer/Counter1 , set PWM mode to clear OC1(PB3) at upcounting
out TCCR1B, temp


LOOP:

UP: out OCR1AL,pw ; Output to CompareRegister1 which will set the puls width
inc pw ; Increase the pulse width
rcall delay ; Delay of 0.01s
cpi pw,0xFF ; Check if pulse width is max
brne UP ;


DOWN: out OCR1AL,pw
dec pw
rcall delay
cpi pw,0x00
brne DOWN

rjmp delay05

rjmp LOOP


DELAY: ; delay of 0.01s @ 4Mhz
; =============================
; delay loop generator
ldi R17, $43
WGLOOP0: ldi R18, $C6
WGLOOP1: dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 1 cycle:
nop
; =============================
ret


1 comment:

satish dawan said...

If you use Button interface to increment and decrement the pulse width, it would be better. Any way good one!