PDA

View Full Version : Pic basic RB0 ext interrtupt problem



VE7ZNU
- 26th August 2010, 04:58
The program below runs a DC motor with a turns counter attached. RB0 detects ext interrupt of the turns counter.

Buttons attached to RB6 and RB7 manually drive the motor up and down. The initialization sequence drives the motor down until it stalls which is detected by A/D and sets the cnt =0. When the motor is driven by either RB0 or RB6 the interrupt counts accurately in both the up and down direction.
However, when the motor is driven by the cnt<> bandcnt code the count is off by almost 50 %. For example, if I manually drive the motor "up" from zero and mark the distance travelled and move back to zero, then make bandcnt=100 the motor will drive and count to 100 but the distance travelled is only equal to 60 turns of distance. I'm at my wits end. I have tested this 100's of times. I checked the code an equal number of times. The interrupt is simple. The code is simple and the mechanics are simple. I hate to make the next statement !

I'm at a lose; it seems like its counting faster in the "auto" mode than the manual mode.





'16F877

Include "modedefs.bas" ' Include serial modes

'================================================= ===========================================

Define OSC 20


' Define LCD pins
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
'================================================= ===========================================
' Allocate variables


z var byte

cnt var word
dirflag var byte
freq var word
xband var word
Band var word

flag var byte
top var word
bot var word
zeroflag vAR BYTE
banddone var byte
bandcnt var word
'================================================= ===========================================

freqtrim con 42 'freq correction

cnt=0


bandcnt=0

'================================================= ===========================================


ADCON1 = 4 ' Set PortA 0, 1, 3 to analog inputs

'Interrupt on falling edge of RB0/INT pin
OPTION_REG=%10000000

On Interrupt Goto myint ' Define interrupt handler

INTCON = $90 ' Enable INTE interrupt



Low PORTE.2 ' LCD R/W line low (W)
Pause 100 ' Wait for LCD to start

lcdout $fe,1,"Initializing........"
low portc.1
low portc.2
pause 100





zeroflag=1 'go down to bottom of coil
while zeroflag=1
Dirflag=0 'down
high portc.1
low Portc.2 'go down
gosub getad
gosub getz



if z>50 then 'this on the edge of stall current


low portc.2

low portc.1

Dirflag=1 'go up

zeroflag=0 'stop
cnt=0
endif

wend






mainloop:

'====================================this code is for Motor Down

If portb.6 =0 Then 'this code works for key press
high Portc.1
Dirflag=0
else
low Portc.1

endif


'=====================================this code is for motor up

If portb.7 =0 Then 'this code works for key press

high Portc.2
Dirflag=1
else
low Portc.2
Endif

'================================================= ===========================================



gosub get_freq ' Calc freq

Lcdout $fe, $C0+5 'set location to 17th position of 2nd line
Lcdout " " ' print blanks to clear
Lcdout $fe, $C0+5 'set location to 17th position of 2nd line
Lcdout #cnt
Lcdout $fe, $C0+12 'set location to 17th position of 2nd line
Lcdout " "
Lcdout $fe, $C0+12 'set location to 17th position of 2nd line
Lcdout #bandcnt
Lcdout $fe, $80+15 'set location to 17th position of 2nd line
Lcdout " "
Lcdout $fe, $80+15 'set location to 17th position of 2nd line
Lcdout #Z
'================================================= ===========================================
if cnt=bandcnt then 'done
goto mainloop

endif




if cnt<bandcnt and="" freq="">0 then 'go up
Dirflag=1 'up

while cnt<>bandcnt
low portc.1
high portc.2
wend
endif

if cnt>bandcnt and freq >0 then
Dirflag=0 'down

while cnt<>bandcnt
high portc.1
low Portc.2 'go down
wend
endif

'================================================= ===========================================






Goto mainloop ' Do it forever

Disable ' No interrupts past this point

myint:

if dirflag=1 then
cnt=cnt+1
ENDIF

IF dirflag=0 then
cnt=cnt-1
endif

Lcdout $fe, $C0+5 'set location to 17th position of 2nd line
Lcdout " " ' print blanks to clear
Lcdout $fe, $C0+5 'set location to 17th position of 2nd line
Lcdout #cnt


INTCON.1 = 0 ' Clear interrupt flag


Resume 'mainloop ' Return to main program

Enable
'================================================= ===========================================
' Subroutine to read a/d convertor
getad:
Pauseus 50 ' Wait for channel to setup

ADCON0.2 = 1 ' Start conversion
Pauseus 50 ' Wait for conversion

Return


' Subroutine to get pot z value
getz:
ADCON0 = $59 ' Set A/D to Fosc/8, Channel 3, On
Gosub getad
z = ADRESH
Return
'================================================= ===========================================

get_freq: 'count frequency on portc.7

count portc.0,200,freq
if freq=0 then

return
endif
freq=(freq*10)/2
freq=freq+(freq/freqtrim)
' freq=3780

lookdown2 freq,<[1800,2001,3500,4001,7000,7351,10100,10201,14000,14 351,18068,18169,21000,21145,24890,24991,29701],xband
branchl xband, [get_freq,band160, get_freq, band80, get_freq,band40, get_freq, band30,get_freq, band20,get_freq, band17, get_freq, band15,get_freq, band12,get_freq, band10]


band160:

band=160
bandcnt= 20
goto loop


band80:

band=80
bandcnt=50
goto loop


band40:
band=40
bandcnt=108
goto loop


band30:

goto loop


band20:

goto loop


band17:

goto loop


band15:

goto loop


band12:

goto loop


band10:


loop:

return

</bandcnt>