PIC Projects

Working with Pulse Width Modulation (PWM)

In this project we use two built-in features of PIC16F684: Analog to Digital Converter (ADC) and Pulse Width Modulation (PWM). The goal is to design a circuit that control the brightness of an LED. It turns out that by adding a motor interface the same program can control the motor rotation speed.

The PIC reads the voltage coming out of the pot, which is in the range 0..5V, and redirects it to a built-in ADC with a 10-bit resolution. The ADC value, which is in the range 0..1023, is used to set up the duty cycle ratio of the PWM running at 244Hz (the minimum frequency achievable by running the PIC @4MHz). The PWM resolution in this case is 1024, hence matching the one of the ADC. The PWM output is available at pin RC5 drives LED through a current-limiting resistor. This way effective voltage on the LED is proportional to the pulse width of the PWM, which affects its brightness.

Schematic Layout

The PWM runs in the single and active-high mode, thus coming out at pin PC5 by default and leaving 3 other PWM-related registers available for other usage. The PWM period 1μsec·16·256 = 4.096msec (which corresponds to approx. 244Hz frequency) is provided by setting PR2 with the value of 255 and using Timer2 1:16 prescaler. The program starts with a necessary setup of the control registers and then falls into an infinite loop. At each iteration of this loop the PIC reads the voltage at pic RA0, digitizes it and updates the duty cycle ratio of PWM. The 8 higher bits of the ADC are available in ADRESH register, while the two lower bits are in ADRESL. Those two bits are first shifted twice to the right to come to a proper place and then are ANDed with the other bits of the corresponding control register. After a 20msec delay this process repeats over and over. The oscillograms below show the output at pin RC5, corresponding to a dimmer and brighter LED, respectively.

PWM duty cycle ratio 1/4 (approx.) PWM duty cycle ratio 3/4 (approx.)
osc1 osc2

By adding a motor interface circuit L293D containing 4 buffers for building a full H-bridge, the same code can be used for controlling the motor rotation speed.

Schematic Layout

The code is as follows:

 TITLE  "pwm_led.asm"           	; PWM test with LCD
 List P=PIC16F684, R=DEC
 INCLUDE "p16f684.inc"

; data segment
 CBLOCK 0x20                   
 del  					; variable used for delay
 temp					; local temp variable	
 ENDC

; code segment
 PAGE
 __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & 
   _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
  org 0                      		; start program at the beginning of mem
	bcf	STATUS, RP0		; activate BANK 0
	clrf	PORTA			; initialize PORT A
	clrf	PORTC			; initialize PORT C
	movlw	0x07
	movwf	CMCON0			; comparators OFF
	bsf    	STATUS, RP0      	; change to BANK 1

 	; ADC and PWM configuration
	bsf	TRISA ^ 0x80, 0		; enable input on pin A0
	bsf	ANSEL ^ 0x80, 0		; configure A0 as analog input
	movlw 	b'01110000' 		; set ADC Frc clock
	movwf 	ADCON1 ^ 0x80
	movlw	0xFF	
	movwf	PR2 ^ 0x80		; PWM period 244Hz
	bcf	TRISC ^ 0x80, 5		; enable RC5 for output
	bcf    	STATUS, RP0        	; back to BANK 0

	bsf 	ADCON0, 0 		; Left justify, Vdd Vref, AN0, On	
	movlw	7
	movwf	T2CON			; enable Timer 2 with 1:16 prescaler
	movlw	0x0C			; enable single output PWM
	movwf	CCP1CON 	

loop
	movlw	20
	movwf	del
	call	delay			; 20 msec delay

	bsf	ADCON0, GO		; start ADC operation
	btfsc	ADCON0, GO		; and wait for its completion	
	goto 	$-1

	bsf    	STATUS, RP0      	; change to BANK 1
	movf	ADRESL ^ 0x80, w	; read 2 lower bits of ADC
	bcf	STATUS, RP0
	movwf	temp
	rrf	temp, f
	rrf 	temp, f
	movf	temp, w
	iorlw	b'11001111'
	andwf	CCP1CON, f		; setup the 2 lower bits of PWM
	movf	ADRESH, w		; get high 8 bits of ADC
	movwf	CCPR1L			; setup PWM duty cycle

  	goto 	loop			; endless loop


; procedures
delay					; a delay for del milliseconds
	movlw 	200
	
	sublw	1			; this loop takes 5us*200 = 1ms
	sublw	0			; for PIC16F684 @ 4 MHz
	btfss	STATUS, Z
	goto 	$-3

	decfsz	del, f
	goto 	delay
	return

 end

Download pwm_led.asm


Last modified:Mon, Jan 23, 2023.

14109