PDA

View Full Version : LCD freezing problem with interrupts



pxidr84
- 29th November 2011, 18:34
Hi everyone,

I've a very weird problem with my program. Here is the source 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.

But sometimes when I navigate into this menu (when the AC motor is either on or off), and very randomly, the LCD is "freezing" and after 2 seconds the display is reseted. The 3-phase PWM outputs are not affected at all.

Now, if I remove only the interrupts (TMR1_INT, INT0, INT2) of my program, this problem doesn't occur.

So what's the problem? :blue:

pxidr84
- 29th November 2011, 20:15
EDIT

Corrected program part:


' Menu limits
IF mpos<1 THEN mpos=1
IF mpos>5 THEN mpos=5

Still doesn't works.

pxidr84
- 5th December 2011, 12:35
Nothing? I've also tried to remove serial commands and CGRAM custom-made characters, same problem.

Jerson
- 6th December 2011, 03:58
But sometimes when I navigate into this menu (when the AC motor is either on or off), and very randomly, the LCD is "freezing" and after 2 seconds the display is reseted. The 3-phase PWM outputs are not affected at all.

Now, if I remove only the interrupts (TMR1_INT, INT0, INT2) of my program, this problem doesn't occur.
Do you get the fault indication? I suspect, you are getting into the FltSub when you say the LCD is frozen.

You can possibly disable the ocint and the stopint for checking this possibility. Does the LCD still freeze?

sayzer
- 6th December 2011, 05:30
OSC is defined as 40Mhz, where is the config settings?
which pic is this?

HenrikOlsson
- 6th December 2011, 06:21
Completely unrelated to your problem, or perhaps not but anyway.....
Does these constructs really work? Do they even compile:


' 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

I think you need an ENDIF for each of those IF statements.

pxidr84
- 6th December 2011, 21:13
Do you get the fault indication? I suspect, you are getting into the FltSub when you say the LCD is frozen.

You can possibly disable the ocint and the stopint for checking this possibility. Does the LCD still freeze?

Actually I'm not at home so I will try to remove ocint and stopint next friday.

And no, I'm not getting into Fltsub when my LCD is frozen: in reality, the menu is reseted to the very first position (1: ISENS).

pxidr84
- 6th December 2011, 21:19
Completely unrelated to your problem, or perhaps not but anyway.....
Does these constructs really work? Do they even compile:


' 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

I think you need an ENDIF for each of those IF statements.

I've no problems with that (but I've modified this part to something like that):

if rot=%0 then
if run=%0 then
if flag4=%0 then
rot=%1
flag2=%0
flag4=%1
endif
endif
endif

Yeah, not very readable but take less program space than AND operator. And it works good.

pxidr84
- 6th December 2011, 21:23
OSC is defined as 40Mhz, where is the config settings?
which pic is this?
A special PIC for motor control, it's the PIC18F4431, 10MHz quartz with PLL enabled (so 4*10=40MHz).

sayzer
- 6th December 2011, 22:34
So, while LCDOUT command is being executed, an interrupt is occuring.

To "test" this, you can disable all interrupts before lcdout command and enable them right after.
This is just to see.
But this will definitely effect your motor. It can give you a point anyway.