ON 20050107@4:23:37 PM at page: http://www.piclist.org/techref/member/HB-operamail-885/index.htm# Helge Buen[HB-operamail-885] edited the page. Difference: http://www.piclist.org/techref/diff.asp?url=H:\techref\member\HB-operamail-885\index.htm&version=7 ON 20050114@4:35:57 PM at page: http://www.piclist.org/techref/member/HB-operamail-885/index.htm#38366.6916203704 James Newton[JMN-EFP-786] Code:
;---===>>> Version 27/8-2004 

; PWM generator inside same chip! Improved sorting procedure (some register names are not descriptive because of this).

; This program runs on a PIC16C57 and creates the six PWM signals necessary to drive a power transistor bridge including
; dead time generation. Of course a hardware interface is required between the PIC and the power transistors.
; I have tested the code driving a 1.1Kw tree phase motor (without load), and it seems to work just fine.
; Maximum PWM frequency would be X-tal.freq/4/256 resoulution/4 inst.loop = 20MHz/4/256/4= 4.88KHz

; The software PWM loop code is located at the end and works as the main program. It outputs the transistor gate 
; data to PORTB, loops the delay time, and also has a third role calling the sine generator subroutine at the right
; time. In other words the PWM is using values calculated during the previous PWM period. Because of this, a copy of
; all necessary register values are passed to a second set of registers each period. It similar to interrupt handling,
; but since the PWM period is a known value it can be triggered from the main program, ie the PWM loop.

; Initially, during the first PWM period, the PORTB outputs are switched off until the generator has run once.

; There is no proper speed control implemented yet, just some simple test code (a button acc/dec control part)
; I used for testing purposes.

; NOTE: I previously mentioned that data values passed to the output bridge containing the values 111 was not
; necessary to drive the bridge, but It's wrong. The motor windings create returning currents
; immediately after each PWM pulse, and this current must be passed back to the motor during the time no PWM
; pulses are on. This is similar to the flyback diodes used when driving DC motors in PWM, and without this
; current return path, the motor might not run very well.

; The code listed here includes the necessary flyback states.

; Please send me an email if you find errors or other problems with this program.



	list p=16c57

	; Include file, change directory if needed
	include "p16c5x.inc"

zero	EQU H'0008'
temp	EQU H'0009'
angle	EQU H'000A'
gain    EQU H'000B'
volt1	EQU H'000C'
volt2	EQU H'000D'
volt3	EQU H'000E'
speed	EQU H'000F'
lsbpos  EQU H'0010'
delay1	EQU H'0011'
delay2	EQU H'0012'
delay3	EQU H'0013'
delay4	EQU H'0014'
data1	EQU H'0015'
dataX	EQU H'0016'
data2	EQU H'0017'

pwm_o2  EQU H'0018'
pwm_o3  EQU H'0019'
pwm_o4	EQU H'001A'
del_o2  EQU H'001B'
del_o3  EQU H'001C'
del_o4  EQU H'001D'
exe_o	EQU H'001E'
exeproc	EQU H'001F'




	; Start at the reset vector
	org	0x000

	GOTO	init

sinetbl:
	addwf	PCL,f
	retlw	000h
	retlw	003h
	retlw	006h
	retlw	009h
	retlw	00Ch
	retlw	010h
	retlw	013h
	retlw	016h
	retlw	019h
	retlw	01Ch
	retlw	01Fh
	retlw	022h
	retlw	025h
	retlw	028h
	retlw	02Bh
	retlw	02Eh
	retlw	031h
	retlw	033h
	retlw	036h
	retlw	039h
	retlw	03Ch
	retlw	03Fh
	retlw	041h
	retlw	044h
	retlw	047h
	retlw	049h
	retlw	04Ch
	retlw	04Eh
	retlw	051h
	retlw	053h
	retlw	055h
	retlw	058h
	retlw	05Ah
	retlw	05Ch
	retlw	05Eh
	retlw	060h
	retlw	062h
	retlw	064h
	retlw	066h
	retlw	068h
	retlw	06Ah
	retlw	06Bh
	retlw	06Dh
	retlw	06Fh
	retlw	070h
	retlw	071h
	retlw	073h
	retlw	074h
	retlw	075h
	retlw	076h
	retlw	078h
	retlw	079h
	retlw	07Ah
	retlw	07Ah
	retlw	07Bh
	retlw	07Ch
	retlw	07Dh
	retlw	07Dh
	retlw	07Eh
	retlw	07Eh
	retlw	07Eh
	retlw	07Fh
	retlw	07Fh
	retlw	07Fh
	retlw	07Fh



sort	movf	volt1,w		;Finding the greatest voltage. Result in delay2.
	subwf	volt2,w
	movf	volt2,w
	btfss	STATUS,C
	movf	volt1,w
	movwf	delay2
	subwf	volt3,w
	movf	volt3,w
	btfsc	STATUS,C
	movwf	delay2
	movf	delay2,w
	subwf	volt1,f		;..calc. DIFFERENCE to next (included voltage(s) are zeroed and excluded in next sort)
	btfsc	STATUS,Z	;Set the PWM bits
	bsf	data2,0
	subwf	volt2,f
	btfsc	STATUS,Z
	bsf	data2,1
	subwf	volt3,f
	btfsc	STATUS,Z
	bsf	data2,2
	retlw	d'0'		
	


init
	clrf	PORTB		;Switch off PWM drivers
	movlw	B'00000000'
	tris	PORTB
        movlw   d'8'            ;increment TMR0 at each program cycle
	option
	clrf	zero
	clrf	angle
	clrf	lsbpos

	clrf	exe_o		; Initial jump. 

	movlw	d'4'
	movwf	speed		; Desired motor frequency. Values above 127 may generate too few sine values?? (<36 a revolution)
	movlw	d'8'
	movwf	gain		; Desired motor voltage. Should follow the frequency (max desired speed -> gain=255)



process movf	angle,w
	movwf	temp		; copy the angle
	btfsc	temp,6		; is angle in the 2nd or 4th quadrant?
	subwf	zero,w		; yes, complement it to reduce to 1st or 3rd
	andlw	07fh		; reduce to 1st quadrant
	call	sinetbl		; get magnitude
	clrf	volt1		; empty the output
	bcf	STATUS,C	; Multiply the gain..
	btfsc	gain,0
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,1
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,2
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,3
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,4
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,5
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,6
	addwf	volt1,f
	rrf	volt1,f
	bcf	STATUS,C
	btfsc	gain,7
	addwf	volt1,f
	rrf	volt1,w
	btfsc	temp,7		; was angle in 3rd or 4th quadrant?
	subwf	zero,w		; yes, complement it
	xorlw	d'128'		; align to center
	movwf	volt1

	movlw	d'85'		; 120 degrees offset for phase 2
	addwf	angle,w
	movwf	temp	
	btfsc	temp,6		; is angle in the 2nd or 4th quadrant?
	subwf	zero,w		; yes, complement it to reduce to 1st or 3rd
	andlw	07fh		; reduce to 1st quadrant
	call	sinetbl		; get magnitude
	clrf	volt2		; empty the output
	bcf	STATUS,C	; Multiply the gain..
	btfsc	gain,0
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,1
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,2
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,3
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,4
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,5
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,6
	addwf	volt2,f
	rrf	volt2,f
	bcf	STATUS,C
	btfsc	gain,7
	addwf	volt2,f
	rrf	volt2,w
	btfsc	temp,7		; was angle in 3rd or 4th quadrant?
	subwf	zero,w		; yes, complement it
	xorlw	d'128'		; align to center
	movwf	volt2

	movlw	d'170'		; 240 degree offset for phase 3
	addwf	angle,w
	movwf	temp	
	btfsc	temp,6		; is angle in the 2nd or 4th quadrant?
	subwf	zero,w		; yes, complement it to reduce to 1st or 3rd
	andlw	07fh		; reduce to 1st quadrant
	call	sinetbl		; get magnitude
	clrf	volt3		; empty the output
	bcf	STATUS,C	; Multiply the gain..
	btfsc	gain,0
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,1
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,2
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,3
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,4
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,5
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,6
	addwf	volt3,f
	rrf	volt3,f
	bcf	STATUS,C
	btfsc	gain,7
	addwf	volt3,f
	rrf	volt3,w
	btfsc	temp,7		; was angle in 3rd or 4th quadrant?
	subwf	zero,w		; yes, complement it
	xorlw	d'128'		; align to center
	movwf	volt3

	
	movf	speed,w		; Lookup table pattern generator..
	addwf	lsbpos,f 	
	btfsc	STATUS,DC	
	incf	angle,f
	swapf	speed,w
	andlw	d'15'
	addwf	angle,f

                                ;-------------This code was used to control speed in test setup

	movlw	d'10'		;BEGIN temporary button control (not included in process time)
	subwf	angle,w
	btfsc	STATUS,C
	goto	skipbut
	movf	PORTA,w
	movwf	temp
	movlw	d'1'	
	btfsc	temp,2
	addwf	gain,f
	btfsc	STATUS,C
	decf	gain,f
	bsf	STATUS,C
	btfsc	temp,3
	subwf	gain,f
	btfss	STATUS,C
	incf	gain,f
	bcf	STATUS,C
	rrf	gain,w
	movwf	speed
skipbut				;END temporary button control (not included in process time)

                                ;-------------This code was used to control speed in test setup



	clrf	data2		;Sorting PWM data
	clrf	delay4
	call	sort		;Find first PWM data and delay. Subtract delay from volt1-3
	movf	data2,w
	movwf	data1		;Store first PWM data
	movf	delay2,w
	movwf	delay1
	subwf	delay4,f
	call	sort		;Find second PWM data and delay
	movf	delay2,w
	btfsc	STATUS,Z
	decf	delay2,f	;Convert 0 to 255
	movf	delay2,w
	subwf	delay4,f
	movlw	d'255'		;Find third delay from data pattern (if all set ->255)		
	btfss	data2,0
	movf	volt1,w
	btfss	data2,1
	movf	volt2,w
	btfss	data2,2
	movf	volt3,w
	movwf	delay3
	subwf	delay4,f	;Fourth delay= 256-Del1-Del2-Del3


        movf    data1,w         ;Format 6 PWM outputs (for bridge) and make the deadtime data (dataX)
	movwf	dataX
	comf	data1,w
	andlw	D'7'
	movwf	temp
	swapf	temp,w
	addwf	data1,f
	comf	data2,w
	andlw	D'7'
	movwf	temp
	swapf	temp,w
	addwf	dataX,f
	addwf	data2,f


	clrf	exeproc
	movlw	d'63'		;Check within what PWM delay the process can be executed (64*4=256 cycles max)
	addwf	delay4,w
	rlf	exeproc,f	;The result is copied from carry bit
	movlw	d'63'
	addwf	delay3,w
	rlf	exeproc,f
	movlw	d'63'
	addwf	delay2,w
	rlf	exeproc,f
	comf	exeproc,f
	movlw	d'63'		;The generator process time to subtract from the PWM loop (63*4)

	btfsc	exe_o,0		;Where to get back to the PWM loop
	goto	E2
	btfsc	exe_o,1
	goto	E3
	btfsc	exe_o,2
	goto	E4
	goto	cycle		;Initial jump. 

E2	addwf	del_o2,f	;add process time and clear execution flag
	clrf	exe_o
	nop
	nop
	nop
	nop
	goto	L2
E3	addwf	del_o3,f
	clrf	exe_o
	nop
	nop
	goto	L3
E4	addwf	del_o4,f
	clrf	exe_o
	goto	L4
	


cycle	clrf	PORTB		;'000'000'
	movf	delay2,w
	movwf	del_o2
	movf	delay3,w
	movwf	del_o3
	movlw	B'01110000'
	movwf	PORTB		;'111'000'
	movf	delay4,w
	movwf	del_o4
	movf	dataX,w
	movwf	pwm_o2
	movf	data2,w
	movwf	pwm_o3
        andlw   B'00000111'     ;'000'111'
	movwf	pwm_o4
	movf	exeproc,w
	movwf	exe_o
	movf	data1,w
L1	andlw	B'01110000'
	incfsz	delay1,f
	goto	L1
	movwf	PORTB		;'110'000'
	movf	data1,w
	nop
	movwf	PORTB		;'110'001' - Data1
	btfsc	exe_o,0
	goto	process
L2	movf	pwm_o2,w
	incfsz	del_o2,f
	goto	L2
	movwf	PORTB		;'100'001' - DataX
	movf	pwm_o3,w
	nop
	movwf	PORTB		;'100'011' - Data2
	btfsc	exe_o,1
	goto	process
L3	movf	pwm_o4,w
	incfsz	del_o3,f
	goto	L3
	movwf	PORTB		;'000'011'	
	movlw	B'00000111'
	nop
	movwf	PORTB		;'000'111'
	btfsc	exe_o,2
	goto	process
L4	nop
	incfsz	del_o4,f
	goto	L4

	goto	cycle	



	END