Let's Make Robots!

Using Interrupts in PICAXE 08M to change led lighting routines

I was in the process of completing this carzy project of mine, where i had a single picaxe 08m chip driving four leds (green, red and amber). Its intended to give my four year old daughter something fun to look at. However I am a bit stuck as in teh code I can only get the interrupt to fire once via teh simulator. 

Any help will be appreciated.

 

symbol green_led = 0

symbol yellow_led = 1

symbol red_led = 2

symbol wait_green = 3000

symbol wait_yellow = 500

symbol wait_red = 3000

let b13 = 1

setint %00000000,%00001000

main: 

select case b13

case 1

gosub traffic

case 2

gosub cycling

case 3

gosub eyes

else

b13 =1

endselect

 

 

goto main

traffic: 

 

high green_led

low red_led

low yellow_led

pause wait_green

low green_led

for b0 =1 to 6

high yellow_led

pause wait_yellow

low yellow_led

pause wait_yellow

next b0

high red_led

low yellow_led

pause wait_red

Return

 

cycling:

 

low green_led

low red_led

low yellow_led

pause wait_yellow

high green_led

low red_led

low yellow_led

pause wait_yellow

low green_led

high red_led

low yellow_led

pause wait_yellow

low green_led

low red_led

high yellow_led

pause wait_yellow

 

Return

eyes:

 

high green_led

low red_led

high yellow_led

 

pause wait_yellow

 

low green_led

high red_led

low yellow_led

Return

interrupt:

 

let b13 = b13 +1

if pin3 = 0 then interrupt

pause 2000

setint %00001000,%00000000

Return

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I have modified your interrupt routine so it can be used to cycle through your subroutines .

interrupt:

inc b13
if b13 > 3 then
    b13 = 1
endif
stayhere:
if pin3 = 0 then stayhere    'wait for interrupt condition to clear

pause 2000

setint %00000000,%00001000    'reenable interrupt

Return

In your original code b13 would be incremented   continuously while pin 3 was low . It would also get out of the range 1 - 3 . Interrupts always return to the next line from where they occurred so you can't simply use a goto to return to your main label . This code will go to the next mode after your subroutine returns and the select case executes . This might seem sluggish if your in your traffic subroutine when the button is pushed . You can take out the pause 2000 in the interrupt routine to make it a little faster .  If you want the program to more quickley go to the next mode when the button is pushed you will have to change the way your program is structured . Like birdmun suggested . Since it's for a child to play with they might not care . Hope this helps and good luck .

 

 

I am sorry that I forgot you had already suggested the if then change to the interrupt routine. I did not mean to minimize your suggestion.

No problem . I liked your solution of setting a flag in the interrupt and using it to jump over all the delays .

would be to do away with the interrupt and just make a call to the subroutine that is interrupt at the end of each individual subroutine call and get rid of the setint in your program completely. For example:

eyes:
   high green_led
   low red_led
   high yellow_led
   pause wait_yellow
   low green_led
   high red_led
   low yellow_led
   gosub interrupt
return

interrupt:
   let b13 = b13 +1
   if pin3 = 0 then interrupt
   pause 2000
return

what i am trying to do is have multiple light flashing routines within the single picaxe 08M chip. There is a button on my circuit board that when pressed regardless of which routine the code is in at that point in time it should based on an internal variable exit and go to the next routine in the line up. Or more simply put I wanted a way to change operational modes. 

Mind u this is stepping stone project to add sumo mode and roaming mode to a robot i am building. wanted to get a full grash of teh interrupts

symbol green_led = 0
symbol yellow_led = 1
symbol red_led = 2
symbol wait_green = 3000
symbol wait_yellow = 500
symbol wait_red = 3000
symbol flag = b1
let b1 = 0
let b13 = 1
setint %00000000,%00001000
 
main: 
flag = 0
select case b13
case 1
gosub traffic
case 2
gosub cycling
case 3
gosub eyes
else
b13 =1
endselect
goto main
 
traffic: 
 
gosub green
if flag !=1 then pause wait_green
endif
low green_led
 
b0=1
do while b0<7 and flag !=1
high yellow_led
if flag !=1 then pause wait_yellow
endif
low yellow_led
if flag !=1 then pause wait_yellow
endif
b0 = b0 + 1
loop
 
gosub red
if flag !=1 then pause wait_red
endif
return
 
cycling:
 
gosub ledoff
if flag !=1 then pause wait_yellow
endif
gosub green
if flag !=1 then pause wait_yellow
endif
gosub red
if flag !=1 then pause wait_yellow
endif
gosub yellow
if flag !=1 then pause wait_yellow
endif
return
 
eyes:
 
high green_led
low red_led
high yellow_led
if flag !=1 then pause wait_yellow
endif
gosub red
if flag !=1 then pause wait_red
endif
return
 
green:
 
if flag != 1 then
high green_led
low red_led
low yellow_led
endif
return
 
red:
 
if flag != 1 then
low green_led
high red_led
low yellow_led
endif
return
 
yellow:
 
if flag != 1 then
low green_led
low red_led
high yellow_led
endif
return
 
ledoff:
 
if flag != 1 then
low green_led
low red_led
low yellow_led
endif
return
 
interrupt:
 
let b13 = b13 +1
if b13 > 3 then b13 = 1
endif
if pin3 = 0 then interrupt
pause 2000
flag = 1
setint %00000000,%00001000
return

Say thank you DanM :) He found a missing pause in the eyes routine and suggested the if b13 > 3 then b13 = 1 to make sure b13 is a random number versus always defaulting to 1 all the time. He went so far as to breadboard the circuit for testing.

this looks great gonna try it on the chi[p now. I started an alternative code that was gonna use variables to control the following

LED ligthing sequence

LED flash delay

whether or not an LED was apart of the sequence.

The interrupt routine would change the values of these variables based on b13 (device mode). the idea came to me after watching Green Lantern and coming home not being able to sleep. Needless to say I needed as you would put it a more elegant design because pretty soon I ran out of space on the 08M. 

Will put some more thought into it but now I know the key is how often I check to determine if the mode has been changed.

Once again thanks for all the help given so far from all

 

 

 

While I had it breadboarded, I tried a few changes that would fall in the personal preference category.

1) I removed the pause 2000 from the interrupt subroutine.

2) changed out the yellow LED for blue

3) I changed the preset timings to be a bit faster  [to wit: wait_blue = 300 wait_green = 500 & wait_red = 1000]

The code could be compacted and made more efficient, but this works. An example of what I mean, would be to use the led on/off subroutines, and then rather than repeat each in the different main routines, just set up lists of instructions (which I've renamed R, G, & B) to be called in a given order. [i.e. using 'lookup' command  / lookup b2, ("GRBBBBGR"), b3 ; puts ascii character into b2 / followed by the "select case" command in a for-next or do-while loop]

Anyway, once you have it in front of you flashing, you may decide to try different timings and/or different sequences.  Play around with it so it's pleasing to you (and to the youngster in question).

What you describe sounds like  a drum sequencer and it should be more effecient than all that inline code . Here is a link to good article about implementing one by Jon Williams in his Basic Stamp column .

http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/vol5/col/nv110.pdf

 

I don't know how typical it is to want to use an interrupt to break out of a subroutine, but, rather than removing interrupts how about breaking down your subroutines into much smaller parts and rewritting your for loop as a do/while or do/until. Once you have your subroutines broken out encapsulate each one with a check to make sure that the interrupt has not occurred. Do the same with the Do/While or Do/Until loop that you replace your for loop with. It won't be an instataneous switch, but it will be faster than it is currently.