Code:
' Varidrive "Lite" firmware V2011.00 by DR Electronics
' PIC initialization
DEFINE OSC 40
DEFINE LCD_DREG PORTD
DEFINE LCD_EREG PORTB
DEFINE LCD_RSREG PORTB
DEFINE LCD_EBIT 6
DEFINE LCD_RSBIT 7
DEFINE ADC_BITS 10
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 19200
DEFINE HSER_SPBRG 129
' BAS includes
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
INCLUDE "Sine_table.bas"
' ADC registers configuration
ADCON0=%11101
ADCON1=%10000
ADCON2=%10000110
ADCON3=%10000
ANSEL0=%00001111
ANSEL1=%0
' PCPWM registers configuration
PTCON0=%10
PTCON1=%10000000
PWMCON1=%1
DTCON=%11
' Inverter variables
ustep var BYTE
vstep var BYTE
wstep var BYTE
uduty var WORD
vduty var WORD
wduty var WORD
freq VAR WORD
amp var WORD
copy VAR WORD
rld VAR WORD
stor var word
dum VAR WORD
dum1 VAR WORD
dum2 VAR WORD
bl var BIT
flag var BIT
flag1 VAR BIT
flag2 VAR BIT
flag3 var BIT
flag4 var BIT
flag5 var BIT
flag6 var BIT
flag7 var BIT
flag8 var bit
flag9 var bit
a var BYTE
b var BYTE
c var word
d var word
e var bit
f var bit
run VAR BIT
rot var BIT
menu var BIT
mpos VAR BYTE
isense VAR WORD
usense VAR WORD
tsense VAR WORD
psense var WORD
idisp var BYTE
udisp var WORD
tdisp var BYTE
maxf var WORD
minf var WORD
imax var BYTE
pwmf var BYTE
res var BYTE
flt var BYTE
lastf var BYTE
' Default variables definition
dum1=5600
dum2=100
mpos=1
a=0
b=0
flag=%1
flag3=%1
run=%0
flt=%0
' Reading EEPROM
read 0,rot
read 1,maxf.HIGHBYTE
read 2,maxf.LOWBYTE
read 3,minf.HIGHBYTE
read 4,minf.LOWBYTE
read 5,imax
read 6,pwmf
read 7,bl
read 8,lastf
' Initial GOSUBs
GOSUB pwmsub
GOSUB blsub
' Inverter startup
pause 1000
HIGH PORTD.5
Hserout ["Varidrive V2011.00|19200 8n1|Maxfreq:",DEC4 maxf,"|Minfreq:",dec4 minf,"|Itrip:",dec3 imax,"|PWMfreq:",dec1 pwmf,"|Backlight:",dec1 bl,"|Lastfault:",dec1 lastf]
' Turn LCD on and write custom characters to CGRAM
LCDOUT $fe,$40,$0,$4,$e,$15,$4,$4,$4,$0
LCDOUT $fe,$48,$0,$4,$4,$4,$15,$e,$4,$0
LCDOUT $fe,1
' Create interrupt processors
ASM
INT_LIST MACRO
INT_Handler TMR1_INT,_pwmint,PBP,yes
INT_Handler INT0_INT,_ocint,PBP,yes
INT_Handler INT2_INT,_stopint,PBP,yes
ENDM
INT_CREATE
ENDASM
' Interrupts and timer enable
@ INT_ENABLE TMR1_INT
@ INT_ENABLE INT0_INT
@ INT_ENABLE INT2_INT
T1CON=%10001
' Main program loop
lp:
' Start ADC conversion
ADCON0.1=%1
WHILE ADCON0.1=%1:WEND
' Store ADC results
isense.HIGHBYTE=ADRESH
isense.LOWBYTE=ADRESL
usense.HIGHBYTE=ADRESH
usense.LOWBYTE=ADRESL
tsense.HIGHBYTE=ADRESH
tsense.LOWBYTE=ADRESL
psense.HIGHBYTE=ADRESH
psense.LOWBYTE=ADRESL
' Security fault verifications
IF isense**40000>imax THEN flt=1
IF usense>880 THEN flt=2
IF tsense>880 THEN flt=3
' Security fault tripping
IF flt>0 THEN GOTO fltsub
' Brake/surge resistor control
IF usense>800 then
if run=%1 then high PORTD.7
else
LOW PORTD.7
endif
' Frequency reference control by potentiometer
psense=((psense<<6)**maxf)+10
IF psense<>freq+10 THEN freq=psense:flag=%1
' Frequency limits
IF freq<minf THEN freq=minf
IF freq>maxf THEN freq=maxf
' Recalculations
IF flag=%1 THEN
' Reload timer calculation
dum=dum1*dum2
stor=DIV32 freq
rld=(65535-stor)+8
' U/F calculation
IF freq<=500 THEN
amp=(freq*131)+35
ELSE
amp=65535
ENDIF
flag=%0
ENDIF
' Run
IF run=%1 THEN
IF flag1=%0 THEN PWMCON0.6=%1:HIGH PORTD.6:flag1=%1
ENDIF
' Stop
IF run=%0 THEN
IF flag1=%0 THEN PWMCON0=%0:LOW PORTD.6:flag1=%1
ENDIF
' FWD rotation
IF rot=%1 THEN
IF flag2=%0 THEN ustep=89:vstep=59:wstep=29:write 0,rot:flag2=%1
ENDIF
' RWD rotation
IF rot=%0 THEN
IF flag2=%0 THEN ustep=29:vstep=59:wstep=89:write 0,rot:flag2=%1
ENDIF
' - button
IF PORTE.0=%1 then
if flag8=%0 then
IF menu=%0 THEN mpos=mpos-1:d=1200:E=%0:F=%0
ENDIF
flag8=%1
endif
' + button
IF PORTE.1=%1 then
if flag9=%0 then
IF menu=%0 THEN mpos=mpos+1:d=1200:E=%0:F=%0
endif
flag9=%1
endif
' Run/stop button
IF PORTC.0=%1 THEN
IF run=%0 AND mpos<6 AND flag3=%0 THEN run=%1:flag1=%0:flag3=%1:f=%0
IF run=%1 AND flag3=%0 THEN run=%0:flag1=%0:flag3=%1:f=%0
ENDIF
' FWD/RWD button
IF PORTC.1=%1 THEN
IF rot=%0 AND run=%0 AND flag4=%0 THEN rot=%1:flag2=%0:flag4=%1
IF rot=%1 AND run=%0 AND flag4=%0 THEN rot=%0:flag2=%0:flag4=%1
ENDIF
' Menu/OK button
IF PORTC.2=%1 THEN
IF menu=%0 AND run=%0 AND mpos>5 AND flag5=%0 THEN menu=%1:flag5=%1
IF menu=%1 AND flag5=%0 THEN menu=%0:flag5=%1
ENDIF
' Buttons released state
IF PORTC.0=%0 THEN flag3=%0
IF PORTC.1=%0 THEN flag4=%0
IF PORTC.2=%0 THEN flag5=%0
IF PORTE.0=%0 THEN flag8=%0
IF PORTE.1=%0 THEN flag9=%0
' LCD first line writing
c=c+1
if c>800 then
IF rot=%1 THEN LCDOUT $fe,$2,"+"
IF rot=%0 THEN LCDOUT $fe,$2,"-"
LCDOUT DEC freq DIG 3,DEC freq DIG 2,DEC freq DIG 1,".",DEC freq DIG 0,"Hz"
IF run=%1 THEN LCDOUT REP 32\5,"RUN"
IF run=%0 THEN LCDOUT REP 32\4,"STOP"
c=0
endif
' Inverter menu (LCD second line writing)
SELECT CASE mpos
' Menu limits
IF mpos<1 THEN mpos=1
IF mpos>11 THEN mpos=11
IF run=%1 THEN
IF mpos>5 THEN mpos=5
ENDIF
' Current sensing submenu
CASE 1
d=d+1
if d>1200 then
idisp=isense**40000
lcdout $fe,$c0,$1,$20,"1 ISENS: ",DEC idisp DIG 2,DEC idisp DIG 1,".",DEC idisp DIG 0,"A"
d=0
endif
' Voltage sensing submenu
CASE 2
d=d+1
if d>1200 then
udisp=usense**29600
lcdout $fe,$c0,$1,$0,"2 USENS: ",DEC3 udisp,"V",32
d=0
endif
' Temperature sensing submenu
CASE 3
d=d+1
if d>1200 then
tdisp=(tsense-280)/8
lcdout $fe,$c0,$1,$0,"3 TEMP: ",DEC tdisp DIG 1,DEC tdisp DIG 0,$df,"C",REP $20\2
d=0
endif
' Last fault reading submenu
CASE 4
if e=%0 then
lcdout $fe,$c0,$1,$0,"4 LASTFAULT: ",DEC1 lastf
e=%1
endif
' Firmware version reading submenu
CASE 5
IF f=%0 then
lcdout $fe,$c0,$1,$20,"5 FW: V2011.00"
f=%1
ENDIF
END SELECT
GOTO lp
' PWM update interrupt (timer 1)
pwmint:
' Timer management
T1CON.0=%0
copy.HIGHBYTE=TMR1H
copy.LOWBYTE=TMR1L
copy=copy+rld
TMR1H=copy.HIGHBYTE
TMR1L=copy.LOWBYTE
T1CON.0=%1
' PWM U phase calculation
uduty=sine[ustep]
uduty=(uduty<<res)**amp
' PWM V phase calculation
vduty=sine[vstep]
vduty=(vduty<<res)**amp
' PWM W phase calculation
wduty=sine[wstep]
wduty=(wduty<<res)**amp
' PWM U, V and W update
PDC0H=uduty.HIGHBYTE
PDC0L=uduty.LOWBYTE
PDC1H=vduty.HIGHBYTE
PDC1L=vduty.LOWBYTE
PDC2H=wduty.HIGHBYTE
PDC2L=wduty.LOWBYTE
' Phase angle calculation
@ decf _ustep,1
@ decf _vstep,1
@ decf _wstep,1
' Phase angle reinitialization
IF ustep=0 THEN ustep=89
IF vstep=0 THEN vstep=89
IF wstep=0 THEN wstep=89
@ INT_RETURN
' PWM carrier frequency configuration subroutine
pwmsub:
IF pwmf=1 THEN PTPERH=$f:PTPERL=$ff:res=6
IF pwmf=2 THEN PTPERH=$7:PTPERL=$ff:res=5
IF pwmf=3 THEN PTPERH=$3:PTPERL=$ff:res=4
IF pwmf=4 THEN PTPERH=$1:PTPERL=$ff:res=3
RETURN
' LCD backlight subroutine
blsub:
if BL=%1 then
HIGH PORTD.4
ELSE
low PORTD.4
ENDIF
RETURN
' Over current interrupt
ocint:
flt=4
GOTO fltsub
@ INT_RETURN
' Emergency stop interrupt
stopint:
flt=5
GOTO fltsub
@ INT_RETURN
' Inverter fault subroutine
fltsub:
' Emergency stop of the inverter
PWMCON0=%0
T1CON.0=%0
LOW PORTD.5
LOW PORTD.6
LOW PORTD.7
' Disable interrupts
@ INT_DISABLE TMR1_INT
@ INT_DISABLE INT0_INT
@ INT_DISABLE INT2_INT
' Fault information
lcdout $fe,$1
lcdout $fe,$2,"FAULT!",REP $20\10
lcdout $fe,$c0,"CODE: ",DEC flt,REP $20\9
Hserout ["Fault|Code:",DEC1 flt]
write 8,flt
' Fault LED ON
HIGH PORTE.2
end
This program control a 3-phase AC motor inverter. On my control board I got a HD44780 LCD and buttons, so I can navigate between menus when my motor is running or not. With that I can monitor DC bus current, DC bus voltage, IGBT module temperature, etc. Very useful. All of these things are working right.
Bookmarks