SETINT with 1 input OR another

John O

Senior Member
Hi,

Are there any tricks to simulate 'SETINT OR input,mask' with an 08M ?

I need a Picaxe which does virtually nothing except loop waiting for one of two interrupts. One interrupt is from an external switch and simply increments a variable and the second is from another Picaxe requesting a serout to send the variable.

The main 'doing nothing' loop is:
Code:
main:
  for b0 = 1 to 60
    pause 60000
  next
  b1 = 0
goto main
so it's not possible to put either the external switch or the request from the second Picaxe inside the main loop.

In 'pseudo' code, the interrupt is simply:
Code:
interrupt:
  setint {input}, {mask}
  if pin1 = 1 then
     inc (b1)
  else
     serout pin0, N2400, (b1)
  endif
  return
Anything bigger than an 08M seems overkill (especially in terms of "managing" unused pins) but I can't see any way of implementing an interrupt from one pin OR another pin with anything less than a 14M2. ??

John.
 
Last edited:

BeanieBots

Moderator
Yes there is, but it's a hardware solution.
Configure the interrupt to trigger on a single input in the normal manner, then diode OR any other inputs that you also want to trigger the interrupt. Within the interrupt you can then test the inputs to see which one caused the interrupt.
 

lbenson

Senior Member
Can't you just poll?

Code:
main:
  if pin1 = 0 then
    bit0 = 0     ' enable check for switch to "on"
  else
    if bit0 = 0 then ' pin1 was off, now it's on
      inc b1
      bit0 = 1   ' disable until pin1 toggles
    endif
  endif
  if pin2 = 1 then ' for instance--2nd "interrupt"
    serout 0, N2400, (b1)
    do while pin2 = 1: loop ' other axe must de-assert
  endif
  goto main
You can run this in the simulator to see if it does what you want.

If your original main loop was to cycle about once an hour (and then do something), you could accomplish this with a "PAUSE 1000", word counter for seconds, and byte counter for minutes--assuming that your pin1 would not go on and off in less than a second.
 
Last edited:

John O

Senior Member
Can't you just poll?
.....

You can run this in the simulator to see if it does what you want.

If your original main loop was to cycle about once an hour (and then do something), you could accomplish this with a "PAUSE 1000", word counter for seconds, and byte counter for minutes--assuming that your pin1 would not go on and off in less than a second.

The signal from the switch (optoswitch) is quite fleeting - I'm not sure how fleeting yet - but I'm guessing it's going to be around 100ms. It's also quite random. It could go for days without switching once (glorious Summer) or be switching 50 or 60 times a minute (pouring with rain!) [Can you tell what it is yet; as Rolf Harris used to say :) ].

I don't know yet how badly the timing of the hour-loop will be affected by the interrupt but it "feels" as though it will be easier to manage and tweak if the two are kept separate. The hour doesn't need to be exact but, as long as I can tweak it, it does need to be consistent, to within, say, 5 seconds.

I'm hoping to get it on the breadboard today to have a play.

John.
 

hippy

Technical Support
Staff member
You can turn the pulse counting into a finite state machine which will be quite responsive and then simply interrupt every hour ...

Code:
Do
  Do : Loop While pin1 = 0
  Inc b1
  Do : Loop While pin1 = 1
Loop
 

geoff07

Senior Member
Why not just send the data regardless of being asked, at intervals or when it changed, and at the receiver get the incoming serial to interrupt the main prog to update a variable and set a 'handle' flag. Then you always have the latest data and the main prog in the receiver doesn't have to even think about asking. It's a doddle to do. My solar controller in the finished section works this way to report temperatures from remote sensors, each with their own 08M.
 

John O

Senior Member
Why not just send the data regardless of being asked, at intervals or when it changed, and at the receiver get the incoming serial to interrupt the main prog to update a variable and set a 'handle' flag. Then you always have the latest data and the main prog in the receiver doesn't have to even think about asking. It's a doddle to do. My solar controller in the finished section works this way to report temperatures from remote sensors, each with their own 08M.
I was thinking of doing it along similar lines but the main program in the receiver has a few commands which I think might be sensitive to being interrupted - count, serout (wireless to the indoor base unit) and I'm not sure about things like readadc10 and readtemp. Something has to "give way" - either the interrupt or the command it happens to be in the middle of. The program currently cycles naturally at about 2 seconds (1 second of that being the count command). I was going to poll the 08M every 30 cycles.

The 08M will actually be on the same board as the main Picaxe. I want it to maintain two variables: The total switch count during the previous hour and the running total (sent at 1 minute intervals) during the current hour. I haven't actually decided/worked out how I'll be using them but they seem the most useful values to monitor and simply pass to the indoor unit via the main outdoor Picaxe!

John.
 

John O

Senior Member
You can turn the pulse counting into a finite state machine which will be quite responsive and then simply interrupt every hour ...

Code:
Do
  Do : Loop While pin1 = 0
  Inc b1
  Do : Loop While pin1 = 1
Loop
Hmm, yes, I like that idea! I'd have to interrupt every 60 seconds because I want a running total during the current hour. The hour loop was basically just to reset the count to zero each hour but, if it also kept count of how many times it had been interrupted, it could reset it on the 60th interrupt!

The only down side is that the main program would have to keep a reasonably accurate track of time.


John.
 
Last edited:

geoff07

Senior Member
Picaxe interrupts aren't 'real' interrupts in the sense that they don't actually interrupt anything - they are polled i.e. the picaxe goes and looks for conditions when it isn't doing anything crucial. Much as you had in mind except much faster. This is true of hardware interrupts as well, though in that case the signal does set a flag (which will be very quick indeed) and you only have to test the flag rather than the input. I think (and certainly hope) that the designers made the mechanisms proof against causing commands to fail. Commands that use timers use different bits of the hardware that work autonomously and intervals aren't affected by what the cpu is up to, generally speaking. There is a lot in a PIC(axe).

That said, you should keep the ISR very short so that the main logic isn't messed with.

If you want a real-time clock pulse to count, to get hours, take the guts out of a cheap alarm clock. You will find a chip with a crystal that pulses a small solenoid that operates the escapement, running off one AA battery. That will be as accurate as you could need and costs very little.
 

John O

Senior Member
This is what I've ended up with and it seems to work, although I haven't checked how close to an hour the delay is:

Code:
#picaxe 08M

setint %00010000, %00010000
main:
 for w0 = 1 to 60000
   pause 60
 next
 b2 = 0
 goto main
 
interrupt:
 setint %00010000, %00010000       ; Main interrupt on pin4
 
 if pin3 = 1 then
   serout 2, N2400, ("r", b2)         ; Diode ORed interrupt from pin3
   do : loop while pin3 = 1           
  else
   inc b2
   do : loop while pin4 = 1
 endif
 toggle 1                              ; LED to check it's working
 return

The code at the "master" end is just:
Code:
   high B.5                                  ; To 08M Pin3
   serin [500], C.0, N2400, ("r"), b18       ; From 08M Pin 5
   low B.5
I made the hour-loop the other way round - ie 60000 small delays - because the interrupt routine cancels a pause that is currently in progress. So, if an interrupt occurred 1000 ms into the 60,000 pause, the delay would be lost. This way, less than 60ms is lost.

I put the external switch input inside the for.. next loop but it was being missed so the pulse must be shorter than I expected.

I couldn't put the serout inside the loop (even if it would have been sensible with a 60ms cycle time) because serout disables interrupts (according to manual 2, Appendix 4)

John.
 
Last edited:
Top