Interrupts causing problems

interrupt_test.bas (888Bytes)

I dislike asking questions - usually it means I didn't RTFM or that my Google skills are sub-par.  Or that I'm missing the obvious.  But here we are.  The following advenure takes place on a Picaxe 28x1 project board (that came with the Solarbotics "Start Here" kit) with a resistor pack replacing the Darlington chip.  The Parallax unit is connected to digital i/o pin 3 (though I see the same behavior on other pins).  Output pin 2 is connected to an LED (but the same behavior holds for pins 4-7 which drive the motor outputs).

Here is some code:

 


 

setint %10000000, %10000000 ; interrupt when pin7 goes high

main:

  ;This area is "before" the sonar code


   low portc 3
   high portc 3
   pause 1
   low portc 3
   let dirsc = %00000000
   pulsin 3,1,w1
   sertxd("Ping))): ",#w1,13,10)
   pause 80

 ; This area is "after" the sonar code

goto main

interrupt:
  high 1 ; LED_1 on
  pause 100
  low 1  ; LED_1 off
  setint %10000000, %10000000 ; re-activate interrupt
return

 


 

The above code works as intended.  Appropriate values are sent to the serial stream, and the LED flashes when the interrupt (a bumper switch) is engaged.

If I add the following LED flash snippet:

   high 2
   pause 1000
   low 2

"after" the sonar code - everything still works like it's suppose too.  However, if I add that snippet "before" the sonar code, the Parallax unit returns "0" every time.  If I comment out the interrupt setting, the behavior is as expected and I get proper sonar readings again.

To further confuse things:  If I remove the sonar code and put it into a subroutine the behavior changes.  Now it doesn't matter whether I put the LED flash code "before" or "after" the gosub call - either way the Parallax returns a "0" reading as long as the interrupt is defined.  Removing the interrupt clears the problem and I get the desired behavior.

What am I doing wrong?  I've tried changing the interrupt and Parralax i/o pins but get similar behaviors.  Where do I go next to troubleshot the problem.  I suspect it is software, but perhaps there is a hardware problem I'm not looking for.  Any advice or direction is appreciated.  If I've left out any critical information, please let me know and I'll answer as best I can.

Thank you.

 

 

I loaded the attached

I loaded the attached program in the Picaxe editor and ran the simulator . You have a return command following the pause 80 command . This causes a ‘Stack error Return without gosub’ in the simulator . You don’t need the return command because you’re not in a subroutine or interrupt service routine . Also I don’t think you need  the dirsc command but I have never used the sonar unit so I could be wrong.

The one difference that stands out to me

between your code and the code from manual 1 is:

your code             modified code from manual

interrupt:              interrupt:

high 1                  high 1

pause 200            pause 200

low 1                    if pinC.7 = 1 then interrupt

…                        …

Also, Rick100 is correct. The code you attached includes a lonely return statement. :slight_smile:

Thanks guys.Yes it is a

Thanks guys.

Yes it is a lonely “return” command - it’s a cut & paste error from testing with and without the subroutine.  I removed that, but it doesn’t appear to be causing my bug.  The code I posted (after removing the offensive return command - or even leaving it in place) should work fine.  The error comes when I try to add the LED flash snippet (high 2 : pause 200) above the sonar portion.  Or when I add the flash snippet before or after the sonar subroutine call when the Parallax measurement is put into a subroutine.

@birdmun - The difference between my interrupt routine and the one you saw in the manual is that I don’t wait for the interrupt to clear before returning from the interrupt - I don’t check the interrupt pin again.  The interrupt routine appears to work even when the Parallax unit is returning 0’s.

Let me know if you have anymore thoughts or observations.

You could try disabling the

You could try disabling the interrupt while your reading the sonar and enabling it afterward . According to the parallax data sheet the sensor waits 750uS after the sig line is toggled before sending the output pulse . If your interrupt occurs at the right time the Picaxe will miss the start of the pulse and time out . After reading the data sheet I understand you need the dirsc command so you can use the same pin for trigger and pulsein . Good luck .

Thanks Rick -The problem

Thanks Rick -

The problem only occurs when I add the “high pin” command - just the sonar routine by itself works fine running along with the interrupt.  And if I trigger the interrupt, the Ping))) waits patiently for the main code to resume.

When the Ping))) returns a “0” I assume that an error occured - that it didn’t register the return pulse in a timely fashion.  But I don’t actually see that anywhere in the documentation.  The high pin command affects the operation of the Ping))) and does so differently depending on the location of the high pin call and whether or not the Ping))) commanding is contained in a subroutine - so I’m still suspecting a software and/or compiler problem.  I don’t have the equipment to diagnose what’s happening at the I/O pin with much temporal resolution.

Thanks again for your continued help.

I would try and remove the

I would try and remove the DIRSC command. When you use the PULSIN the pin is automatically turned into an input and when you use HIGH or LOW it auto configs it back to an output. With the interrupt on a portC pin and messing with the input/output thing it might make for gremlins, I don’t really know. Just something for you to try.

Gotta clear your flags (I think)

It has been a very long time since I last worked with the interrupt routine on a Picaxe. I did however, go back and check my old code. It seems that I used the setintflags command instead of the setint command. I have no idea why I did --but I did and it works.

I wish I could be of more help but as I skim through my own code, I just get more confused.

Give the setintflags thing a shot.

Be sure to include hintflag=0 as the last thing in your interrupt subroutine. (to clear the flag)

Also include the setintflags = %0000???  %00000??? thing in there as well --just like you have now

 

 

SETINTFLAGS = X2?

I also went the way of tracking flags for my interrupts but they’re tied to the hardware interrupts, an X2 feature.

Thanks for the response Jax

Thanks for the response Jax & CTC.

It seems I need the DIRSC command - otherwise it doesn’t work.  I went looking for the posting where I obtained the code for the Parallax, and it suggests the following for troubleshooting:


6. Try a Low-high only instead of a low-high-low…

 LOW PORTC 0
 HIGH PORTC 0
 PAUSE 1
 LOW PORTC 0
 LET DIRSC = %00000000
 PULSIN 0, 1, W0


When I comment out the second “low portc 3” in my code, I get the expected behavior - joy!.  I haven’t checked everything yet, but it’s a step in the right direction (maybe).  It does seem that the readings from the Ping))) unit are a little less “stable” / consistent than before, but I won’t know until I do some more bench testing.

@CTC: Thanks for scanning your old code.  I’ll take a closer look at the other interrupt settings and really try to understand what’s going on and how to get a solid implementation of the interrupts.  (Someday maybe I’ll even graduate to parallel processing and do away with polled interrupts altogether.)

Thanks for all the help everyone.  I’m glad the code seems to be working, but I really wish I understood my problem and why the code is affected the way it is - I don’t like fixes that I don’t understand.  Of course I like magic fixes better than broken code, but still…

Okay, I’m not a Picaxe guy
Okay, I’m not a Picaxe guy but, I do know Pause statements in other languages cause problems for interrupts unless the interrupt routine is done in assembler. I mostly use Picbasic Pro and a pause routine actually stops code execution until it is complete so your interrupt routine might not get executed. As a test, take out the pause routines and setup a for…next loop as a substitute.

The interrupt gets

The interrupt gets constantly polled during a “pause” command, so the pauses never seem to be a problem.

I’m still confused why the bug exists, but since I have a work-around, I guess I just need to let it go.

Does the interrupt led ever flash for no reason?

Without pulldown resistors on my int pins they would drift high and trigger the obstacle avoidance routine. Yours would exhibit such a thing in the form of a blinking light at odd times, which could interrupt the correct reading of your sonar pulse.

I hate work arounds. Want… to… solve… prob… lem…

A big mystery to me is why

A big mystery to me is why changing state on one of the output pins (beit LED, motor, etc) affects the sonar routine differently depending on whether the routine is written directly in main: or if it’s put into a subroutine.  And if the routine is directly coded in main:, it still depends on whether the state change occurs before or after the sonar code.  And none of this (directly) should be affecting the state of the I/O pins on portc.

If I had a scope maybe I could see what was happening on the I/O pins when I re-arrange the code, but for now I’ll live with it.

 

Thanks.

And to finally answer your

And to finally answer your question - no, the interrupt never appears to trigger accidentally.

My bad

Sorry that was a pointless comment. I failed to refresh the page so I could see your replies. Glad to see it worked out, well, at least the functioning sonar part.

One last word lol

I put your code in the editor and instead of, for instance, LOW 1 I put in LOW B.1 or LOW PORTC 1 and it passed syntax. Maybe better pin definition can help? If you have time and the inclination, let me know what it does :slight_smile:

OK. Here’s the final

OK.  Here’s the final answer - for tonight.  It’s a timing problem.  I guess that the one millisecond pause between the “high portc 3” and “low portc 3” isn’t quite long enough - depending on what else is going on with the processor.  That might explain why the behavior changes when other pin change states and whether or not the sonar routine is hardcoded in main: or put into a subroutine.  It also explains why getting rid of the second “low portc 3” worked as a fix.  I also changed the “high 2” command to light an LED to “high b.2” - it fixed some of the problems, but not all of the error conditions.

I’ve changed the “pause 1” in the sonar routine to “pause 2” and now the code seems to work regardless of what the pins on portb are doing, and whether or not the sonar code is written directly in main: or in a subroutine.  I’m a little happier with this fix - if it’s a problem with timing, then there’s not much I can do to see that with the equipment at hand.

Thanks for all the help guys - especially JAX and CtC.  I’ll test this fix further and see if it holds up.

-Cactus

Have you tried stepping

Have you tried stepping through your code with the emulator? You may find something that way.

I hadn’t tried that before

I hadn’t tried that before (hadn’t even looked at it).  I’ve been playing with it and while it doesn’t show me the problem, I did learn a bit about the emulator.  So thanks for pointing it out to me and giving me another tool to work with!

ps: I was able to fix the problem in my test code by increasing the pause length, but it didn’t fix the problem when I made that fix in the navigation code.  So I’m back to getting rid of the second “low portc 3” and looking for more incriminating code lines.  At least I have a fix.  I think a scope would help me see the problem, but that’s not available.