Interrupting for too long causes crash - overflow somewhere?

Hello, I've got a project that is about a drawing machine (hanging plotter type - www.polargraph.co.uk). The hardware consists of an arduino mega with a custom PCB and a ITDB02-2.2 tft touchscreen. This has an interrupt line that I have wired to pin 2 on the arduino (interrupt 0). Using arduino 1.0.1, Henning Karlsen's UTouch and UTFT libraries

I had an issue with the touchscreen not responding, so dug around in the hardware to try and diagnose it. The interrupt pin was at 1.6v to start with, went down to 0v as long as pressure was applied, but then often only came back up to 0.6v when released. (I assume older versions of the tft and the pcb were slightly better, or more tolerant or something, which is why I never had this problem until now.)

I added a pinMode(2, INPUT_PULLUP), and removed a segment of code that caused the pinmode to be toggled unexpecedly, and that seemed to fix the issue... up to a point. At least the pin starts at 3.3v and goes down to 0v and then comes back to 3.3v so I think that's an improvement.

I can now press the touchscreen and get the expected response, but if I hold it down for longer than half a second or so it appears to crash. Doesn't restart, so maybe it's not really a crash, but all my loops that have any output (serial) appear to stop. My question is this - is there a timer or a counter or something that gets filled up while an interrupt is being handled? Something that might be overflowing? A more confusing issue is that my interrupt handler sets a volatile boolean value if it manages to get a coordinate, and then that boolean is polled for and dealt with in the proper program loop. I can print this value out to serial from within the handler, but if I try and access it within the handler then I get the crash. So the code below runs ok (with the proviso that I don't press for too long):

UTouch  touch(11,12,18,19,2);
const int INTERRUPT_TOUCH_PIN = 0;
volatile boolean displayTouched = false;
volatile int touchX = 0;
volatile int touchY = 0;

pinMode(2, INPUT_PULLUP);
attachInterrupt(INTERRUPT_TOUCH_PIN, lcd_touchInput, LOW);

void lcd_touchInput()
{
  Serial.println("touched:");
  Serial.println(displayTouched);
  
  if (true)
  {
    touch.read();
    int firstTouchX = touch.getX();
    int firstTouchY = touch.getY();

    touchX = firstTouchX;
    touchY = firstTouchY;
    displayTouched = true;
  }
}

But if I add a branch based on the value of displayTouched (to let it know not to try and process a new touch if the old one hasn't been cleared yet):

void lcd_touchInput()
{
  Serial.println("touched:");
  Serial.println(displayTouched);
  
  if (!displayTouched)
  {
    touch.read();
    int firstTouchX = touch.getX();
    int firstTouchY = touch.getY();

    touchX = firstTouchX;
    touchY = firstTouchY;
    displayTouched = true;
  }
}

Then that crashes as soon as there's any touch, and doesn't even output the touched: 1 that I expect to see. I guess this is because that serial.println only really gets sent once the handler ends, and something is preventing it from ending. I'm not clear at all if there is a link between the two effects I'm seeing, but it's as far as I've managed to get, and I feel like there is.

The second puzzle is how come this has only just happened, and how come one out of every four shields I build up does not display this behaviour even with unmodified code, but that's another story - I can only think it's a manufacturing tolerances issue. Any ideas, or help around interrupts is very gratefully received. I have only posted a section of the code. It is 98k in multiple files so I didn't want to spam the forum - here it all is: GitHub - euphy/polargraph: Software and hardware designs for Polargraph robot drawing machines.

Cheers!!
sn

  1. Get rid of the Serial.print commands in the ISR, that's what is almost certainly causing the problem. You should only do very quick and simple things in an ISR, such a read a digital port and set a flag to be noticed somewhere else.

  2. You should probably use interrupt mode FALLING instead of LOW.

  1. HA! You know I looked suspiciously at those printlns for a while, but concluded that they'd always been there (so what harm can they be doing?), but now I think I only put them in to diagnose a different issue .. and never took them out. Your solution is absolutely effective - thank you very much!

  2. I had tried FALLING with unreliable results, but it works too now. It triggers on press rather than on release though, so unless LOW gets tricky, I'll stick with that.

Thanks very much dc - so glad to have another pair of eyes look at it. Any ideas why the printlns were ok for short presses but not for long? Filling a buffer or something?

cheers
sn

  1. I had tried FALLING with unreliable results, but it works too now. It triggers on press rather than on release though, so unless LOW gets tricky, I'll stick with that.

So, try RISING.

Oh, well yes that does it too, thanks Paul. I can see why an edge is semantically better than a state to decide when to fire the interrupt. Cheers guys!