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