PDA

View Full Version : interrupt with 16F88



tur_bot
- 22nd March 2008, 16:18
hello every body
i m trying to program a small robot which will detect objects and avoid them and will also avoid edges.
i managed to write two separate codes, one for the edges detection and avoidance and the second one for obstacle avoidance.
then i tried to combine the two codes together, it works fine but there is a very large delay on going from obstacle detection to edge detection.
I think that it will work fine if i could use an interrupt to interrupt the obstacle detection when an edge is detected and come back to obstacle detection when it is safe (no edge is detected)

i m very not familiar with interrupt, can you help me on that matter please?

how to activate interrupt?...how to go back to the main program?....?????

Darrel Taylor
- 22nd March 2008, 23:06
There are many ways to do Interrupts. But the easiest to use is ON INTERRUPT GOTO.

To activate a particular interrupt, you'll set the appropriate Enable bit for the interrupt you want to use.

Then in the interrupt handler you clear the Interrupt Flag before RESUME'ing which returns control to the Main program.

With more information, we could probably give more direction as to which Enable bits and flags to use.
<br>

tur_bot
- 23rd March 2008, 02:00
There are many ways to do Interrupts. But the easiest to use is ON INTERRUPT GOTO.

To activate a particular interrupt, you'll set the appropriate Enable bit for the interrupt you want to use.

Then in the interrupt handler you clear the Interrupt Flag before RESUME'ing which returns control to the Main program.

With more information, we could probably give more direction as to which Enable bits and flags to use.
<br>

hello,
this is a peace of my code, the main routine called main is detecting object and avoiding them and the interrupt subroutine is called start.

basically its a robot which detect and avoid obstacle (which works fine ) but should jump to a subroutine if either port.b0 or port.b1 or portb2 or portb3 goes low (meaning that an edge is detected) in order to avoid the edge ;and as soon as the 4 portbs '0 to 3' are high together (meaning that no edge is detected) the program should go back to the main routine.

here is the code:

'-------------------------interrupt set up ----------------------

ON INTERRUPT GOTO start

resume

'------------------------obstacle mode-----------------------------
main:
INTCON = %10010000 'enable interrupt on portb.0
gosub turnhead_extleft 'position head to the left

position[11] = 0 'reset last position of array to 0

for i = 0 to 10 'take 11 distance measurements
gosub sr_sonar 'get sonar readings for each of the 11 dist measuremens
position[i] = dist_inch 'store sonar reading in the array
gosub turnhead_right 'rotate head right by 15 degrees

next i 'do it again

best_pos = 11 ' ?????

for i = 0 to 10 'sorting routine to find location
if position[i] >= position[best_pos] then 'if the distance measured [i] is > than 11 inches
best_pos = i 'then best position will be that distance i

serout lcd,baud,[254,135,#best_pos," "]

endif
next i
most_space = 11 - best_pos 'number of left positions needed to get the bot head
'back to position with the most space

for turn = 1 to most_space 'position the bot head in the direction with the most
gosub turnhead_left 'free space
next turn

for turn = 1 to 15 'walk forward for 15 steps
gosub sr_sonar 'take sonar readings
if dist_inch < 6 then 'if obect is too close,ie <6inches

gosub walk_reverse 'back the bot up for 10 steps
goto main 'go back to start and scan for the most space again

endif
gosub walk_forward
next turn
goto main
end
'--------------------end obstacle mode------------------------------------------

'--------------------edge mode-------------------------------------------------

start:

if portb.0 = 0 && portb.1 = 0 && portb.2 = 0 && portb.3 = 0 then 'if nothing is detected
goto do_nothing
endif
if portb.0 = 0 && portb.1 = 0 && portb.2 = 0 && portb.3 = 1 then 'if left is detected
goto stop_to_move
endif
if portb.0 = 0 && portb.1 = 0 && portb.2 = 1 && portb.3 = 0 then 'if right is detected
goto stop_to_move
endif
if portb.0 = 0 && portb.1 = 0 && portb.2 = 1 && portb.3 = 1 then 'if right and left are detected
goto stop_to_move
endif



if portb.0 = 0 && portb.1 = 1 && portb.2 = 0 && portb.3 = 0 then 'if back is detected
goto back
endif
if portb.0 = 0 && portb.1 = 1 && portb.2 = 0 && portb.3 = 1 then 'if back and left are detected
goto back_headright
endif
if portb.0 = 0 && portb.1 = 1 && portb.2 = 1 && portb.3 = 0 then
goto back_headleft
endif
if portb.0 = 0 && portb.1 = 1 && portb.2 = 1 && portb.3 = 1 then
goto slow_back_headextright
endif



if portb.0 = 1 && portb.1 = 0 && portb.2 = 0 && portb.3 = 0 then
goto front
endif
if portb.0 = 1 && portb.1 = 0 && portb.2 = 0 && portb.3 = 1 then
goto front_left
endif
if portb.0 = 1 && portb.1 = 0 && portb.2 = 1 && portb.3 = 0 then
goto front_right
endif
if portb.0 = 1 && portb.1 = 0 && portb.2 = 1 && portb.3 = 1 then
goto front
endif



if portb.0 = 1 && portb.1 = 1 && portb.2 = 0 && portb.3 = 0 then
goto front
endif
if portb.0 = 1 && portb.1 = 1 && portb.2 = 0 && portb.3 = 1 then
goto front_left
endif
if portb.0 = 1 && portb.1 = 1 && portb.2 = 1 && portb.3 = 0 then
goto front_right
endif
if portb.0 = 1 && portb.1 = 1 && portb.2 = 1 && portb.3 = 1 then
goto front
endif
goto start

skimask
- 23rd March 2008, 05:02
General code flow when using ON_INTERRUPT's...(you mileage may vary, others do it other ways, I do it this way)...

1) resetplaceholder: 'just a placeholder

2) ------DEFINEs needed thru the program

3) DISABLE 'need to disable interrupts while actually processing an interrupt

4) CLEAR

5) ------any eeprom data, variable definitions, etc.

6) ------macro's you might be using

7) startupholder: goto skipsubs 'skip over all the commonly used subroutines

8) ON INTERRUPT GOTO INTHANDLER

9) INTHANDLER: 'process your interrupts.

10) 'check the interrupt bits, if the interrupt you want is active, reset the bit and process it

11) INTFINISH: 'I usually recheck the interrupt sources. If one of them tripped while I was processing a previous interrupt, I go back and re-process the interrupt

12) INTRESUME: RESUME 'resume AFTER you've processed the interrupt

13) 'commonly used subroutines start below here

14) commonly_used_sub_1: 'do something here and return from it

15) ..........

16) 'end of commonly used subroutines, skipsubs block for setting up registers, lcd, whatever

17) skipsubs: 'set up the PIC as required

18) mainloop: 'the main program runs here waiting to get interrupted

19) ------------more program stuffed in here.........

20) goto mainloop

21) END

mister_e
- 23rd March 2008, 21:40
Here's some of my advices. Assumming your INTCON an all interrupts settings are nice, i prefer to read the whole PORTB and keep only the revealant bits in one shot.

INTSOURCE = PORTB & $0F ' this will keep PORTB<3:0> only

and then you use a Select Case INTSOURCE or BRANCH.

You forgot the DISABLE/ENABLE RESUME stuff.



ON INTERRUPT GOTO start

resume
MIIIIIIIIIIP! that resume will act as a RETURN... and will cause you something like a stack underflow. remove it.

Read the manual once again.

tur_bot
- 27th March 2008, 16:54
General code flow when using ON_INTERRUPT's...(you mileage may vary, others do it other ways, I do it this way)...

1) resetplaceholder: 'just a placeholder

2) ------DEFINEs needed thru the program

3) DISABLE 'need to disable interrupts while actually processing an interrupt

4) CLEAR

5) ------any eeprom data, variable definitions, etc.

6) ------macro's you might be using

7) startupholder: goto skipsubs 'skip over all the commonly used subroutines

8) ON INTERRUPT GOTO INTHANDLER

9) INTHANDLER: 'process your interrupts.

10) 'check the interrupt bits, if the interrupt you want is active, reset the bit and process it

11) INTFINISH: 'I usually recheck the interrupt sources. If one of them tripped while I was processing a previous interrupt, I go back and re-process the interrupt

12) INTRESUME: RESUME 'resume AFTER you've processed the interrupt

13) 'commonly used subroutines start below here

14) commonly_used_sub_1: 'do something here and return from it

15) ..........

16) 'end of commonly used subroutines, skipsubs block for setting up registers, lcd, whatever

17) skipsubs: 'set up the PIC as required

18) mainloop: 'the main program runs here waiting to get interrupted

19) ------------more program stuffed in here.........

20) goto mainloop

21) END


hello,
i wanted to test an interrupt in a simple small code , i found a code on the internet and modified it and got this:
@ DEVICE INTRC_OSC, LVP_OFF, WDT_OFF, MCLR_OFF

DEFINE OSC 4

OSCCON=%01101000 ' INTRC = 8MHz
ANSEL=%00000000
CMCON=%00000111


OPTION_REG.6=1 'Trigger on rising edge
INTCON = %10010000 'Enable INTE
INTCON.1 = 0 'Clear RB0/INT External Interrupt Flag bit

On Interrupt Goto UpdateCounter

PORTB=0 ' PORTBs are outputs
Pause 500 ' Wait for startup
'LOW PORTB.6

loop:
low portb.6
HIGH PORTB.5
Pause 2000 ' Wait 2 second

low portb.6
LOW PORTB.5
Pause 2000 ' Wait 2 second
Goto loop ' Do it forever

Disable
UpdateCounter:
LOW PORTB.5
HIGH PORTB.6
pause 500
low portb.5
LOW PORTB.6
pause 500

INTCON.1=0 're-enable interrupts

resume
ENABLE
GOTO loop

END


the code works, but the interrupt routine doesn't work, doesn t light the led connected to pin portb.6.
I mean when the portb.0 is connected to ground the led connected to portb.5 blinks as soon as i connect the portb.0 to +5v the portb.5 stops to blink and nothing happens to portb.6 led.
can you help me on that please???
how can I use a digital signal to activate the interrupt for example, with an if statement??

if portb.0 = 1 , the interrupt is activated and the program jumps to the int subroutine and if portb.0 = 0 the program comes back to the main loop???????

thank you

skimask
- 27th March 2008, 19:45
And yet again, one very important step is missing and one not so important step is also not present...
No, your code doesn't follow my example exactly, and no, it doesn't have to follow it exactly. Mine is only an example, one of many ways to accomplish the same thing.
However, I believe in this case, if you follow the example provided, and write your code following said example, you will solve your problem.
And no, I'm not playing games with you...