PDA

View Full Version : Interrupt problem



dj.lambert
- 14th February 2012, 10:34
Hi All

i have a PBP program that is supposed to control an RS485 stepper motor.

without interrupts enabled all is ok but i need to use interrupts as i require an external busy check.
when i add the interrupt code, it works as i expect on 3 positions but the other 8 the interrupt routine keeps being repeated, and the pic no longer detects the opto coupler changes or when it does it runs very slowly.then the hardware serial port outputs continuously either "1"s or "2"s. then only a reset will start it running again.

code is below (in theory)

<code>
'************************************************* ***************'* Name : 742Stepper.BAS *
'* Author : [DJ.Lambert] *
'* Notice : Copyright (c) 2011 *
'* : All Rights Reserved *
'* Date : 18/08/2011 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
'EEPROM
'addr info
' 0 Current/last posn
' 1 Low byte of stepcounter
' 2 High byte of stepcounter
' 3 Adjust performed/valid
'error list
' 1 invalid position
' 2 unit removed during motor move
' 3 220V limit hit
' 4 22mv limit hit


' set config
@ device pic16F876, HS_osc, wdt_on, pwrt_on, protect_off


' set osc speed and serial port
define OSC 16
DEFINE HSER_BAUD 9600 'Hser baud rate
DEFINE HSER_RCSTA 90h 'Hser receive status init
DEFINE HSER_TXSTA 20h


' define Input/outputs
Posn22mV var PortB.2
Posn220mV var PortB.1
Posn700mV Var PortA.5
Posn2V2 var PortA.4
Posn7V var PortA.3
Posn22V Var PortA.2
Posn70V var PortA.1
Posn220V var PortA.0
UnitIdent Var PortB.3
Switch1 var PortB.5
RS485In var PortC.3
RS485InCtl var PortC.2
RS485OutCtl var PortC.1
RS485Out var PortC.0


' Define variables used in prog
'CheckSum var word
'Operator1 var word
'Operator2 var word
'MotAddr var byte
'InstNum var byte
'InstType var byte
'MotorNum var byte
Seek220V var bit 'limit set
Seek22mV var bit
LastPosn var byte 'last recorded posn
DeviceIntLock var byte
ValidAdjust var byte
OPC var byte
t var byte
Steps50 var byte
Steps200 var byte
StepCounter var word
Steps var word
Reply var byte[60]
Query var byte(20)


'start of programme
'port & interupt setup
adcon0 = 0
ADCON1 = 7
intcon= 192
pie1 = 32
pie2=0
TrisA = 255
TrisB = 255
input posn22mv
input posn220v
'wait to settle
pause 500
'check for corrupt eeprom values and load default values
'normally only after programming...
read 0, lastposn
if lastposn > 8 then
lastposn = 8
write 0, lastposn
endif
read 1, stepcounter.byte0
read 2, stepcounter.byte1
if stepcounter > 500 then
validadjust = 0
write 3, validadjust
Stepcounter = 300
write 1, stepcounter.byte0
write 2, stepcounter.byte1
endif
read 3, validadjust
if validadjust > 1 then
validadjust= 0
write 3, validadjust
endif
'Trigger motor check for current posn and set limit flags off
gosub sensortest
gosub motorstepright50
seek22mv = 0
seek220v = 0
'set interupt stuff
enable
on interrupt goto InteruptHandle


Main:
pir1=0
pir2=0
'get rs232input from system
Hserin [str query\10 \13]


'convert all to upper case
for t = 0 to 9
if Query(t) > 96 then
Query(t) = query(t)-32
endif
next


'check query input for commands Format first 3 letters and ? or space
if query(0) = "R" and Query(1) = "A" and query(2) = "N" and query(5) = "?" then
pause 100
gosub sensortest
ELSEIF query(0) = "R" and Query(1) = "A" and query(2) = "N" and query(5) <> "?" then
pause 100
gosub SetRange
ELSEIF Query(0) = "D" and query(1) = "E" and query(2) = "V" and Query(6) = "?" then
pause 100
gosub interlockstatus
ELSEIF Query(0) = "A" and Query(1) = "D" and Query(2) = "J" and query(6) <> "?" then
pause 100
gosub Resetmotor
ELSEIF Query(0) = "A" and Query(1) = "D" and Query(2) = "J" and query(6) = "?" then
pause 100
gosub subvalidadjust
ELSEIF Query(0) = "B" and Query(1) = "U" and Query(2) = "S" then
pause 100
gosub busytest
endif
'Go back for next command
intcon=192
pir1=0
pir2=0
goto Main


end


'################################################# ############
SensorTest:


'Response to Range? query
if posn22mv=1 then
write 0, 1
Hserout ["22mV", 10, 13]
elseif posn220mv=1 then
write 0, 2
hserout ["220mV", 10, 13]
elseif posn700mv=1 then
write 0, 3
hserout ["700mV", 10, 13]
elseif posn2v2=1 then
write 0, 4
Hserout ["2V2", 10, 13]
elseif posn7v=1 then
write 0, 5
hserout ["7V", 10, 13]
elseif posn22v=1 then
write 0, 6
hserout ["22V", 10, 13]
elseif posn70v=1 then
write 0, 7
hserout ["70V", 10, 13]
elseif posn220v=1 then
write 0, 8
hserout ["220V", 10, 13]
else
hserout ["Error 1", 10, 13]
endif


return
'################################################# ####################
'response to device? query
InterlockStatus:
deviceintlock = 0 'set Device error variable
if switch1 = 1 then
deviceintlock = deviceintlock + 1
endif
if unitident = 0 then
deviceintlock = deviceintlock + 2
endif
'output depends on value of DeviceIntLock
select case deviceintlock
case 0
hserout ["0, OK", 10, 13]
Case 1
hserout ["1, Device fail", 10, 13]
case 2
hserout ["2, Knob fail", 10, 13]
case else
hserout ["3, Both fail", 10, 13]
end select


return


'################################################# #####################


SubValidAdjust:
'response to adjust?
read 3, validadjust
select case validadjust
case 1
hserout ["1", 10, 13]
case else
hserout ["0", 10, 13]
end select

Return
'################################################# #####################


BusyTest:
'response to busy?
select case opc
case 0
hserout ["0", 10, 13]
case 1
hserout ["1", 10, 13]
end select


Return
'################################################# #####################


SetRange:
'set RS485 direction pins
low rs485outctl
high rs485inctl
' check query for range information and call range setting subroutines.
if query(6) ="2" and query(7)="2" and Query(8) ="M" then
opc = 1
pause 100
gosub go2_22mv
opc = 0
ELSEIF query(6) ="2" and query(7)="2" and Query(8) ="0" and query(9) = "M" then
opc = 1
pause 100
gosub go2_220mv
opc = 0
ELSEIF query(6) ="7" and query(7)="0" and Query(8) ="0" and query(9) = "M" then
opc = 1
pause 100
gosub go2_700mv
opc = 0
ELSEIF query(6) ="2" and (query(7)="." or query(7) = ",") and Query(8) ="2" then
opc = 1
pause 100
gosub go2_2v2
opc = 0
ELSEIF query(6) ="7" and query(7)="V" then
Opc = 1
pause 100
gosub go2_7V
opc = 0
ELSEIF query(6) ="2" and query(7)="2" and Query(8) ="V" then
opc = 1
pause 100
gosub go2_22v
opc = 0
ELSEIF query(6) ="7" and query(7)="0" and Query(8) ="V" then
opc = 1
pause 100
gosub go2_70v
opc = 0
ELSEIF query(6) ="2" and query(7)="2" and Query(8) ="0" and query(9) = "V" then
opc = 1
pause 100
gosub go2_220v
opc = 0
endif

return

'#########################################


Go2_22mV:
'retrieve offset count
read 1, stepcounter.byte0
read 2, stepcounter.byte1
seek22mv = 1
seek220v = 0
if posn22mV = 1 then goto done22mV
do until posn22mV = 1 'continue til Posn22mV is reached
gosub rotatemotorright 'move motor
loop
gosub motorstop 'stop motor
do until posn22mv = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineAdjustright
Done22mV:
lastposn = 1
write 0, lastposn 'write current posn to eeprom
return

'########################################


Go2_220mV:
'retrieve offset count
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0
if posn220mV = 1 then goto done220mV
' check last entered posn for motor direction
if lastposn < 2 then
do until posn220mv = 1 'continue til Posn220mV is reached
gosub rotatemotorleft 'move motor
loop
gosub motorstop
do until posn220mv = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 2 then
do until posn220mv =1 'as above but opposite direction
gosub rotatemotorright
loop
gosub motorstop
do until posn220mv = 0 'step out until opto changes
gosub motorstepleft
loop
Gosub fineadjustright
endif
Done220mV:
lastposn = 2
write 0, lastposn 'write current posn to eeprom
return

'########################################


Go2_700mV:
if posn700mV = 1 then goto done700mV
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0
if lastposn < 3 then 'as previous steps
do until posn700mv = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn700mv = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 3 then
do until posn700mv =1
gosub rotatemotorright
loop
gosub motorstop
do until posn700mv = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineadjustright
endif
Done700mV:
lastposn = 3
write 0, lastposn
return

'########################################


Go2_2V2:
pir1=0
pir2=0
if posn2V2 = 1 then goto done2V2
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0
if lastposn < 4 then 'as previous steps
do until posn2V2 = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn2v2 = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 4 then
do until posn2v2 =1
gosub rotatemotorright
loop
gosub motorstop
do until posn2v2 = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineadjustright
endif
Done2v2:
lastposn = 4
write 0, lastposn
return

'########################################

Go2_7V:
if posn7V = 1 then goto done7V
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0
if lastposn < 5 then 'as previous steps
do until posn7v = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn7v = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 5 then
do until posn7v =1
gosub rotatemotorright
loop
gosub motorstop
do until posn7v = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineadjustright
endif
Done7V:
lastposn = 5
write 0, lastposn
return

'########################################

Go2_22V:
if posn22V = 1 then goto done22V
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0

if lastposn < 6 then 'as previous steps
do until posn22v = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn22v = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 6 then
do until posn22v =1
gosub rotatemotorright
loop
gosub motorstop
do until posn22v = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineadjustright
endif
Done22V:
lastposn = 6
write 0, lastposn
return

'########################################

Go2_70V:
if posn70V = 1 then goto done70V
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 0
if lastposn < 7 then 'as previous steps
do until posn70v = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn70v = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
ELSEIF lastposn > 7 then
do until posn70v =1
gosub rotatemotorright
loop
gosub motorstop
do until posn70v = 0 'step out until opto changes
gosub motorstepleft
loop
gosub fineadjustright
endif
Done70V:
lastposn = 7
write 0, lastposn
return

'########################################

Go2_220V:
opc=1
if posn220V = 1 then goto done220V
read 1, stepcounter.byte0
read 2, stepcounter.byte1
read 0, lastposn
seek22mv = 0
seek220v = 1
do until posn220v = 1
gosub rotatemotorleft
loop
gosub motorstop
do until posn220v = 0 'step out until opto changes
gosub motorstepright
loop
gosub fineadjustleft
Done220V:
lastposn = 8
write 0, lastposn
opc = 0
return

'########################################

ResetMotor:
opc=1
validadjust = 0
write 3, validadjust
read 0, lastposn
if lastposn < 4 then
do until posn2v2 = 1
gosub rotatemotorleft
loop
gosub Resetfromhi
ELSEIF lastposn > 4 then
do until posn2V2 =1
gosub rotatemotorright
loop
gosub resetfromhi
endif
gosub motorstop
lastposn = 4
validadjust = 1
write 0, lastposn
write 3, validadjust
return


ResetFromHi:
stepcounter = 0 'zero counter
do until posn2v2 =0 ' move till sensor switches
gosub motorstepleft
loop
do until posn2V2 = 1 'move to first edge of sensor
gosub motorstepright
loop
'step thru to far end.
do until posn2V2 = 0 'move to end of sensor
gosub motorstepright
stepcounter = stepcounter + 1 'count steps
loop
'calculate halfway steps and store to eeprom
stepcounter = (stepcounter / 2)
write 1, stepcounter.byte0
write 2, stepcounter.byte1
'step back half of step counter
do until stepcounter = 0
gosub motorstepleft
stepcounter = stepcounter - 1
loop
opc=0
return

'#######################################

FineAdjustRight:
steps = stepcounter
steps200 = steps/200 ' calculate number of 200step steps
for t = 1 to (steps200 * 10)
gosub MotorStepright200 ' move motor
next

steps = stepcounter -( steps200 * 200)

steps50 = steps/50 'calculate number of 50step steps
for t = 1 to (steps50 *10)
gosub MotorStepright50
next
steps = stepcounter -(( steps200 * 200)+(steps50 * 50))
' remainder are normal 10step steps
do until steps = 0
gosub motorstepright
steps = steps -1
loop
return

'#######################################

FineAdjustLeft:
steps = stepcounter
steps200 = steps/200 ' calculate number of 200step steps
for t = 1 to (steps200 * 10)
gosub MotorStepleft200 ' move motor
next

steps = stepcounter -( steps200 * 200)

steps50 = steps/50 'calculate number of 50step steps
for t = 1 to (steps50 *10)
gosub MotorStepLeft50
next
steps = stepcounter -(( steps200 * 200)+(steps50 * 50))
do until steps = 0
gosub motorstepLeft
steps = steps -1
loop
return


'#######################################

RotateMotorRight:
'sub to move motor
gosub checkunit
gosub endlimit1
high rs485outctl
pauseus 100
gosub endlimit1
serout2 rs485out, 84,[ %00000001, %00000001, %00000000, %00000000, %00000000, %00000000, %00000001, %11110100, %11110111]
gosub endlimit1
pause 50
gosub endlimit1
low rs485outctl

return

'########################################

RotateMotorLeft:
'sub to move motor
gosub checkunit
gosub endlimit2
high rs485outctl
pauseus 100
gosub endlimit2
serout2 rs485out, 84,[ %00000001, %00000010, %00000000, %00000000, %00000000, %00000000, %00000001, %11110100, %11111000]
gosub endlimit2
pause 50
gosub endlimit2
low rs485outctl
return

'########################################

MotorStop:
'sub to stop motor
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000011, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000,%00000100]
low rs485outctl

return


'#########################################

MotorStepRight:
'sub to step motor 10 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %00000000, %00000000, %00000000, %00001010, %00010000]
pause 40
low rs485outctl

return

'######################################

MotorStepLeft:
'sub to step motor 10 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %11111111, %11111111, %11111111, %11110110, %11111001]
pause 40
low rs485outctl
return

'#########################################

MotorStepRight50:
'sub to step motor 50 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %00000000, %00000000, %00000000, %00110010, %00111000]
pause 40
low rs485outctl

return

'######################################

MotorStepLeft50:
'sub to step motor 50 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %11111111, %11111111, %11111111, %11001110, %11010001]
pause 40
low rs485outctl

return


'#########################################

MotorStepRight200:
'sub to step motor 200 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %00000000, %00000000, %00000000, %11001000, %11001110]
pause 40
low rs485outctl

return

'######################################

MotorStepLeft200:
'sub to step motor 200 steps
gosub checkunit
high rs485outctl
pauseus 100
serout2 rs485out, 84,[ %00000001, %00000100, %00000001, %00000000, %11111111, %11111111, %11111111, %00111000, %00111011]
pause 40
low rs485outctl
return

'#######################################
CheckUnit:

if switch1 = 1 or unitident = 0 then 'check for unit fitted.
gosub motorstop
hserout ["ERROR 2" , 10, 13]
gosub InterlockStatus
goto main
endif
return

'#######################################
EndLimit1:

if posn22mv = 1 and seek22mv = 0 then
gosub motorstop
hserout ["ERROR 4", 10, 13]
lastposn = 1
write 0, lastposn
goto main
endif
return
'##########################################
EndLimit2:

if posn220v = 1 and seek220V = 0 then
gosub motorstop
hserout ["ERROR 3", 10, 13]
lastposn = 8
write 0, lastposn
goto main
endif

return
end

'#######################################
disable
InteruptHandle:
intcon=192
pir1=0
pir2=0
hserout["1", dec intcon," ", dec pie1," ",dec pir1, " ", bin portb, 10, 13]


if query(0) = "B" or query(0) = "b" then


select case opc
case 0
hserout ["0", 10, 13]
case 1
hserout ["1", 10, 13]
end select
endif
intcon=192
pir1=0
pir2=0


hserout["2", dec intcon," ", dec pie1," ",dec pir1, " ", bin portb, 10, 13]


resume
enable



<\code>

i have added various resets for the interrupt flags and a few serial outputs for current status of intcon and other registers.
if anyone out there can see what i have done wrong or missed i would be very grateful..this is my first real attempt at using on interrupt etc.

thanks in advance