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