Strange interrupt problem.

JanJor

Member
Dear forum, it’s not my habit to bother the forum, unless all other sources are gone. The program below sends three short text fragments in text boxes to a Digole Touchscreen, after the first hit. The program does that in the interrupt-mode. That works OK. After a second hit, the program checks if one of the short tekst boxes is touched through the interrupt procedure. This also works OK and sends back the coordinates where the pen hits the screen. However, the strange fact is that, although in my view, after the interrupt the program should return to the main program and then decide which loop to go to (gra or lev) on the basis of the received screen coordinates, it immediately goes to loop “lev” and stays there. I spent days, modifying each and every part of the program, but without result. Could someone more capable of working with interrupts please tell me where I make a mistake?
Thanks very much in advance.
Janjor
 

Attachments

JanJor

Member
Apparently, attached file can be downloaded after all.

Hoping that anyone can solve this interrupt-problem.

Thanks,

Janjor.
 

mushroom

New Member
Your interrupt sub starts with an 'if' statement without an 'endif'. Also I believe this if line asks for an interrupt if a condition is met. I don't think an interrupt can be called from within an interrupt sub. (anyway the program will no longer be set for interrupt once an interrupt is called from the main program).
 

AllyCat

Senior Member
Hi,
in my view, after the interrupt the program should return to the main program and then decide which loop to go to (gra or lev) on the basis of the received screen coordinates, it immediately goes to loop “lev” and stays there.
Code:
lev:
w12=w12+5
BINTOASCII w12 , b10 , b11 , b12 , b13 , b14
serout a.0,T9600_8,("ETP",45,60)
pause 50
serout a.0,T9600_8,("TT",b10,b11,b12,b13,b14,0)'These four lines print an increasing number on the screen
'The increase of the printed number = 5
pause 50
sertxd("w12 = ",#w12,"  b4 = ",#b4,13,10)
goto lev

It looks to me as if "lev" (and "gra") is a closed program loop - how is the program flow suppose to return to the "main" part? A RETURN is what it says it is, it Returns to the point in the program where the interrupt occurred.

With all those PAUSES and SEROUTS you're not really using the Interrupt in the "intended" manner. But possibly you just need to change the GOTO lev to GOTO main , or maybe provide an alternative method to "escape" from the loops (after returning from an interrupt) ?

Cheers, Alan.

PS: I don't think you need ENDIFs because you're using the IF .. THEN {GOTO} label structure.
 
Last edited:

inglewoodpete

Senior Member
I have had a quick look at your code. There appears to only be two inputs to the program: pinc.0 and serin. Also, you don't mention which PICAXE your are using. It must be one of the larger ones, since it has ports a, b and c.

While an interrupt can be used (or abused) in any way the programmer likes, its purpose is to "capture" brief events, record them in a variable and exit. That way, 1 or more brief events can be captured and acted on. Your main loop would act on the flag or variable values set/recorded in the Interrupt routine.

Your interrupt code does all of the action inside the same routine. In this case, with all the pause and serout statements, there will be an extensive delay (up to a second?) after C.0 returns to the low state. The serial data stream could be over and gone before execution gets to the serin statement. This is not an efficient use of the interrupt function. Perhaps you could explain to us what all of the serout statements currently inside the interrupt routine are do to the receiving device.

My suggestion would be to record the fact the C.0 has gone high and then exit the interrupt routine immediately without resetting the interrupts. Your main loop would then sense the flag and then act on the condition - with the code's priority to capture the incoming serial stream before it has passed.
 

JanJor

Member
@ Mushroom, thanks for your reply. The 'if' statements without an 'endif' do not seem to be the problem. And with reference to "anyway the program will no longer be set for interrupt once an interrupt is called from the main program", that's why at the end of the interrupt routine I programmed a new setint command (line 122).

@ Alan, thanks for your reply. Indeed the pauses are not very efficient, but they are necessary to send data to the Digole touchscreen. May be the problem is as you suggested "A RETURN is what it says it is, it Returns to the point in the program where the interrupt occurred". I hoped it would go back to the main program from which it started in the first place, but apparently that is not the case. And in that case it wouldn't matter that gra and lev are closed loops: after another hit of the screen the system would go to the interrupt, and the second hit, now on new coordinates would tell the main program where to go this time. But apparently my thoughts about this were a bit too simple: it did not work.


@ InglewoodPete, thanks for your reply. The picaxe I use is the 28X2 on a shield-base. Indeed the pauses are not very efficient, but they are necessary to send data to the Digole touchscreen.

Basically the idea was as follows: the first hit on the screen starts the interrupt mode. Then the program waits (serin line 137) for the second hit and loads the coordinates of the hit in W0 and W1. It then returns but indeed the question now is: to which line does it return ?? I expected it to return to the main menu, but apparently that is not the case.
If it would return to the main menu, the main menu would subsequently go to either lev or graph on the basis of the information in W0 and W1. But since apparently it does not seem to return to the main menu, this approach fails.
The question now remains how to solve this problem.

Inglewoodpete, could you please explain your suggestion "My suggestion would be to record the fact the C.0 has gone high and then exit the interrupt routine immediately without resetting the interrupts. Your main loop would then sense the flag and then act on the condition - with the code's priority to capture the incoming serial stream before it has passed. " in a bit more detail? Which setint commants should in your opinion be removed and which ones kept?
Thanks in advance,
Janjor
 

AllyCat

Senior Member
Hi,
... starts the interrupt mode. Then the program waits (serin line 137) for the second hit
That rather suggests that you don't need to use an interrupt at all. The "main" program can just poll the serin line and then there's no problem in jumping to any desired part of the program. Of course you might well use subroutines to partition the program into more manageable blocks.

Cheers, Alan.
 

inglewoodpete

Senior Member
A few thoughts.

I avoid using the pause statement. It makes the chip "do nothing" (apart from detect interrupts if these are enabled). During a pause, the PICAXE is effectively disabled - it can't perform calculations or other data manipulations. There are better ways to use delays between outputs and keep the PICAXE working for you.

I also avoid using the GoTo command - it makes programs difficult to structure clearly and to understand.

Avoid using b0 to b3 (w0 and w1) - they are best used for bit variables bit0 to bit31.

Since you are using a 28X2, use background serial data reception instead of serin. The SerIn statement stops everything from happening until enough serial characters have been received. Also, using hSerOut is for more efficient for outputting serial data. The serout command locks up the PICAXE until all the characters are sent.

Your program has a lot of 50mS delays. You should consider using a 50mS timer interrupt that increments a byte register. Your main loop can then respond to that byte register value by sending the data sequences you require.

I have not used a Digole touch screen, so I can't help you much there.

Below, I have taken part of your code (the serout commands from your interrupt routine) and rewritten it to avoid using any Pause commands. (Untested!) The structure should give you an idea of what can be done in your system.
Code:
Symbol mskTmrAndSer    = %10100000
Symbol flgTmrAndSer    = %10100000
Symbol False           = 0
Symbol True            = 1
Symbol tmrIntOn1stTick = 65535   'Interrupt to be caused by roll over on first major tick
Symbol tmr50mS_8       = 63974   'SetTimer value for 50mS second ticks @8MHz
Symbol tmr50mS_16      = 62411   'SetTimer value for 50mS second ticks @16MHz
Symbol tmr50mS_32      = 59286   'SetTimer value for 50mS second ticks @32MHz
'
'TaskID Values
Symbol tsk1_CL         = 1
Symbol tsk1_ETP1       = 2
Symbol tsk1_TT1        = 3
Symbol tsk1_SF1        = 4
Symbol tsk1_DR1        = 5
Symbol tsk1_DR2        = 6
Symbol tsk1_DR3        = 7
Symbol tsk1_SF2        = 8
Symbol tsk1_ETP2       = 9
Symbol tsk1_TT_Graph   = 10
Symbol tsk1_ETP3       = 11
Symbol tsk1_TTV2       = 12
Symbol tsk1_ETP4       = 13
Symbol tsk1_TTV3       = 14
Symbol tsk1_RPNXYC     = 15
'
'Symbol tsk2_???       = 20
'
'Variables
Symbol tTaskTimerOn    = bit0
Symbol tDoTask         = bit1
Symbol bTaskID         = b4
Symbol bSerialRec      = b5      'Received serial byte/character
'
'ScratchPad
Symbol sSerInBuffStart = 0
Symbol mskSerInRange   = %00111111 'Bytes 0-63 in Scratchpad
'
'Compilation Directives
#PICAXE 28X2
#No_Data
#No_Table
'
'Executable Code: Initialisation
SetFreq m8
'
'Initialise serial link for
hSerSetup B9600_8, %00001     '9600 baud @ 32MHz, Background, no invertion
'                  %abcde where, for X2 chips:
'                  Bit e (bit 0): Foregrd/Backgrd mode e=0 foreground; e=1*background
'                  Bit d (bit 1): Transmit mode -      d=0*No invert;  d=1 Invert transmit polarity
'                  Bit c (bit 2): Receive  mode -      c=0*No invert;  c=1 Invert receive polarity
'                  Bit b (bit 3): disable hserout      b=0 enable;     b=1 disable
'                  Bit a (bit 4): disable hserin       a=0 enable;     a=1 disable
'
Ptr = sSerInBuffStart         'Ptr     is used for reading received background serial data
hSerPtr = sSerInBuffStart     'hSerPtr is updated by the background serial firmware
'
'Start the background timer (runs continuously)
Timer = tmrIntOn1stTick
SetTimer tmr50mS_8            'Expires after 50mS at 8 MHz
Flags = 0                     'Reset serial reception flag
SetIntFlags Or flgTmrAndSer, mskTmrAndSer 'Set timer 0 or hSerial to interrupt
bTaskID = 0                   'Initialise for seqence previously in Interrupt routine
tTaskTimerOn = False
Do
   If tTaskTimerOn = True Then
      Select Case bTaskID
      Case tsk1_CL
         hSerOut 0, ("CL")
         tDoTask = False
      Case tsk1_ETP1
         hSerOut 0, ("ETP", 25, 200)
         tDoTask = False
      Case tsk1_TT1
         hSerOut 0, ("TT", "Menu", 0)
         tDoTask = False
      Case tsk1_SF1
         hSerOut 0, ("SF", 51)
         tDoTask = False
      Case tsk1_DR1
         hSerOut 0, ("DR", 10, 2, 90, 40)
         tDoTask = False
      Case tsk1_DR2
         hSerOut 0, ("DR", 120, 2, 200, 40)
         tDoTask = False
      Case tsk1_DR3
         hSerOut 0, ("DR", 230, 2, 255, 55, 40)
         tDoTask = False
      Case tsk1_SF2
         hSerOut 0, ("SF", 18)
         tDoTask = False
      Case tsk1_ETP2
         hSerOut 0, ("ETP", 25, 30)
         tDoTask = False
      Case tsk1_TT_Graph
         hSerOut 0, ("TT", "Graph", 0)
         tDoTask = False
      Case tsk1_ETP3
         hSerOut 0, ("ETP", 135, 30)
         tDoTask = False
      Case tsk1_TTV2
         hSerOut 0, ("TT", "Vak 2", 0)
         tDoTask = False
      Case tsk1_ETP4
         hSerOut 0, ("ETP", 245, 30)
         tDoTask = False
      Case tsk1_TTV3
         hSerOut 0, ("TT", "Vak 3", 0)
         tDoTask = False
      Case tsk1_RPNXYC                    'Last action for Task sequence 1 "tsk1_???"
         hSerOut 0, ("RPNXYC")
         tDoTask = False
         tTaskTimerOn = False             'Disable task stepping in the interrupt routine
      End Select
   End If
   If pinc.0 = 1 then
      tTaskTimerOn = True
   EndIf
   If Ptr <> hSerPtr Then
     ' bSerialRec = @PtrInc And mskSerInRange 'Fetch character/byte from Scratchpad  -Edited-
      bSerialRec = @PtrInc                    'Fetch character/byte from Scratchpad  -Edited-
      Ptr = Ptr And mskSerInRange             'Manage the Scratchpad pointer         -Edited-
      SerTxd (bSerialRec)                     'Send it to the PE terminal
   EndIf
Loop
'
'
' ************************************************************
'  Interrupt handler
' ************************************************************
' 
Interrupt:If hSerInFlag = True then                   'Restrict pointer to 0-63 (Must appear
            hSerInPtr = hSerInPtr And mskSerInRange   '        first in the interrupt routine)
            hSerInFlag = False
          EndIf
          If TOFlag = True then                       'All timer ticks
            TOFlag = False                            'Reset (clear) the flag first
            If tTaskTimerOn = True Then
               Inc bTaskID
               tDoTask = True
            EndIf
            Timer = tmrIntOn1stTick                   'Then reset the timer
          EndIf    'Timer has ticked
          SetIntFlags Or flgTmrAndSer, mskTmrAndSer   'Set timer 0 or hSerial to interrupt
          Return
' ************************************************************
 
Last edited:

JanJor

Member
Wow, InglewoodPete, this must have taken you hours! Thanks very much. This is high-end programming. As you may have noticed from my program, I still use the same simple commands as I did when I bought my first Picaxe. I'll print your program and study it thoroughly, if only for the fact that this will bring my programming skills to a higher level. In the meantime I have temporarily "solved" the problem by replacing the "goto gra" and "goto lev" loops by "goto main" in both gra and lev. In that case, the interrupt works OK. This however slows down the program bit, which is a pity since "gra" is in the final version supposed to print lines on the screen like an oscilloscope. No need for very high speed, but the faster the better. I'll try to implement your program to see if that speeds up the whole process. Once again, thanks for your time and help.
Ronald
 

inglewoodpete

Senior Member
You're welcome. It only took about 45 minutes because I snipped most of the code from other PICAXE programs I have written.

Although I was/am a professional programmer, about 15 years ago I started out with the PICAXE. Programming Editor V4 was all that we had back then and everyone was locked into writing pretty rudimentary code. With the introduction of PE5, and later PE6, I was able to use programming structures used in commercial work. For me at least, it makes revisiting a program written months or years earlier much easier to understand.

Long-time Rev-Ed staffer and PICAXE guru @hippy was also an inspiration on how to do clever things with a PICAXE.
 
Top