Let's Make Robots!

Interrupts causing problems

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


  ;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

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



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.



interrupt_test.bas888 bytes

Comment viewing options

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

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.

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. :)

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 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 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 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.

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...

 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...

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



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

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.