HB-operamail-885

Name: Mr. Helge B
Company:
Web Site:

Code:

Helge B shares this code:


 
; PIC 3-Phase generator - buen-AT-operamail-com

; I borrowed and altered the table lookup and it's driver code. It is Copyright 1995 Eric Smith


; Fixed PWM frequency 3-phase sine generator for electric motors etc.. The output
; frequency are generated by jumps in the sine lookup table. For example the lowest
; frequency will repeat each value 16 times (4096 values). The highest will do 15 and
16
; jumps (only 16.5 values - maybe too few, not tested). All others generated by
; combinations of repeat/jump. The code is not tested in practice.
; Electric motors needs the voltage to follow the frequency. Therefore each sine value is
; multiplied by a factor (gain). The frequency (speed) and the gain variables are
; INDEPENDENT in the code. The simplest and most suitable would be to right rotate the
; gain into the speed variable. At a gain of 255 the controller would output 36 values a
; revolution at full voltage. If one want some voltage boost (motor torque) at particular
; conditions that is easy to implement too. Of course it would be interesting to monitor
; the speed of the motor and REDUCE voltage to save power on battry apps.
; This code generates 3 values ranging from 2 - 128 and 128-254. 128 is 0 volt and
; corresponds to the 50% PWM ratio (bridge). A separate PWM controller is required as
; it have to output some thousand pulses a second at 255 resolution The PWM controller
; should have fixed instruction number, master the time and clock the sine generator
; (handshake). It is an good idea to centre the PWM pulses to avoid simultaneously
; switching (noise) No speed ramping (frequency increment) is implemented, it should
; correspond the mecanical application. Hovever increasing the speed variable by one
; each revolution would be no problem. It is possible to alter the speed/gain at each
; PWM pulse, be aware! The 3 motor voltages should be output simultaneosly at the end.
 
; 08.09.01: PWM data preparation:

; Convertion of the voltage values into 4 delays and 2 data bytes. The purpose is to do
; as much processing as possible in the generator controller. At the same time not too
; much data should be created because of the transfer time to the PWM. The delays
; represent time between changes and the data is what to be output. The sum of all
; delays always is 256. Note: they are complements to 256 and 0 must be treated as
; zero delay. Usual method: before counting them up (incfsz), initially subtract 1 from all.
; Before counting down, add 1 to all. (Use decf/incf instead of movf at data transfer)

; Now, simply load 4 'counter' and 2 'data' registers in the PWM. Count first UP to
; zero, output data one, count next and so on. The third data output is given to be all
; set. This method introduce small errors, but i believe they are unessential to this
; application. Remember to compensate (at the other end) for the data transfer dead time.

; To implement centered pulses the 4 delays must initially be loaded twice, and second copy
; count DOWN at the 'mirror part'. The data must be inverted (comf). This also requires twice
; as fast controller. A 20MHz controller is beginning to reach the limit here if you want
; reasonable switching frequency (>3KHz). Another idea i had was to do the first PWM half in
; the generator, and the second in the PWM as the generator carry out processing.

; Note that there is only 3 outputs, but 6 are necessary for 3 phase output bridges. The
; additinal 3 signals are kind of inverted versions, but cross over delay must be insterted. That
; is a very short period where none of the transistor pairs are on, to protect them. I have no idea
; how long this period should be, but a very long period would decrease the dynamic range of the
; PWM. If someone has any experience about this, please let me know! Also ideas about fast
; paralell data transfers PIC to PIC wanted. The cross over delay and inverted signals could either
;
be made in the PWM controller or in the transistor driver stage (depending on delay value). I think
; the PIC would do it most nice but, again, it's pretty busy.
; Outputs are delay1-4 and data 1-2.
; 04.19.03: Edited the text to make it more readable. The project have rested for a while,
; but I am now working on it again. Some things i found out:
 
; The 'third data' to be all PWM's set is unnecessary. Guess what, no current would flow in the
; output bridge! Also the first and last delay can be added as one. So there's 3 or 4 delays, and TWO
; data bytes required to control each 3 phase PWM period.
 
; The 'whole inverter' can be implemented into a 20MHz PIC16C5X!! The idea is that no matter the
; distribution of delay values at output, one of them is always greater than 63. (256/4). So at 20MHz,
; there's room
to do the processing during the longest delay, maintaining approx. 4KHz PWM frequency.

 

list p=16c55a

; 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'
delay0 EQU H'0011'
delay1 EQU H'0012'
delay2 EQU H'0013'
delay3 EQU H'0014'
delay4 EQU H'0015'
data0 EQU H'001A'
data1 EQU H'001B'
data2 EQU H'001C'


; Start at the reset vector
org 0x000

GOTO start

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 clrf data0 ;Subroutine to sort PWM data. (see driver comments)
movf volt1,w
movwf delay0 ;Presume volt1 is greatest
bsf data0,0 ;And set it's output
movf volt2,w
subwf delay0,w ;Test volt2 against volt1
btfsc STATUS,Z ;Equal?
bsf data0,1 ;Yes, just set that bit too (They share delay)
btfsc STATUS,C ;Volt2 greater?
goto test3 ;No, go testing volt3
rlf data0,f ;Yes, change output (Carry known to be zero)
movf volt2,w
movwf delay0 ;And correct delay
test3 movf volt3,w
subwf delay0,w ;Test volt3 against the greatest
btfsc STATUS,Z ;Equal?
bsf data0,2 ;Yes, just set that bit too (They share delay)
btfsc STATUS,C ;Volt3 greater?
goto diff ;No, go calculate difference
clrf data0
bsf data0,2 ;Yes, set that output
movf volt3,w
movwf delay0 ;And correct delay

diff movf delay0,w ;Get result
subwf zero,w ;Complement and..
addwf volt1,f ;..calc. DIFFERENCE to next (included voltage(s) are zeroed and excluded in next sort)
addwf volt2,f
addwf volt3,f
retlw d'0'



start:

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


frame 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



call sort ;Format voltages to PWM delays and data to disengage PWM controller.
movf delay0,w
movwf delay1 ;Store first delay
movf data0,w
movwf data1 ;Store first data
call sort
movf delay0,w
movwf delay2 ;Store second delay
movf data0,w
iorwf data1,w ;Include first and..
movwf data2 ;..store second data (Third data is given to be simply all switched on)
clrw ;Find the third delay by checking data. If all set -> zero. (Shared with another)
btfss data2,0
movf volt1,w
btfss data2,1
movf volt2,w
btfss data2,2
movf volt3,w
movwf delay3
addwf delay1,w ;Calculate the fourth delay (sum of previous and this delay -> 256)
addwf delay2,w
subwf zero,w ;Complement
movwf delay4

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

goto frame

END




See also Pages:

Code:

Questions: