Code hangs inside interrupt function

Hey sorry for the slightly awkward question, not quite sure how to word it.

Anywho, I have been playing around with i2c and as part of an example project I'm doing to learn arduino, I wanted to do the following:

Board 1: Read in user input from computer Send signal to board 2 to trip and interrupt when its ready Transmit data over i2c

Board 2: Wait for interrupt Ask for information over i2c when it is interrupted

Now everything is working fine if I don't do the interrupt part and just have board 2 polling the main board every second for information, however for the purpose of what I'm doing I really need to only request information when I know it's available.

The code I am using to request information is as follows (first the one that works);

void loop()
{
  /*
  Wire.requestFrom(2, 10);    // request 6 bytes from slave device #2

  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.receive(); // receive a byte as character
    Serial.print(c);         // print the character
  }
  delay(1000);
  */
}

However when I configure an interrupt (I've included some serial prints to see what is happening), it hangs when it runs the Wire.requestFrom line.

  attachInterrupt(0, request, CHANGE);

void request()
{
  Serial.println("interrupted");
  Wire.requestFrom(2, 10);    // request 6 bytes from slave device #2
  Serial.println("post request");
  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.receive(); // receive a byte as character
    Serial.print(c);         // print the character
  }
}

Now as I said originally, the first code works however the second does not. Any ideas why? I thought it might have been the interrupt triggering it, but it's set to change so even if the pin stays high it shouldn't matter, plus it only displays 'interrupted' once on the serial monitor.

I'm sure it's something daft or I'm failing to understand how interrupts work but I've been at this for a while and I'm totally stumped, so any help would be greatly appreciated.

edit As a side question, is there a way to clear the serial input buffer? I'd like to discard user input if it's greater than x characters but I haven't found a nice way to do that yet. I tried serial.flush but it doesn't seem to do what I'm after

I’ll let the software gurus give better analysis of your your problem, but basically I think you are just trying to do too much inside a ISR routine. Generally it’s recommended to do no or as few as possible function calls or library calls while inside a ISR. Another reason is that once the ISR is called all interrupts are disabled which is what is probably hanging your code. Only when the ISR function returns are interrupts re-enabled.

Typical one uses a ISR just to set a global flag that the main loop() function can test and if set, reset the flag and take the appropriate action. ISR need to be lean and mean, short and fast, get in and get out.

That make sense?

Absolutely :) I'll give it a go and report back. Never actually worked with interrupts before so they're quite new to me

Nailed it! Thanks heaps :D

millsy_c: Nailed it! Thanks heaps :D

Wow that was fast, glad to be able to help. Interrupts are very powerful and cool to use, but you do have to be careful in their usage.

Lefty

For anyone that is wondering:

  attachInterrupt(0, request, CHANGE);
...
void request()
{
...
  Wire.requestFrom(2, 10);    // request 6 bytes from slave device #2

The function Wire.requestFrom blocks, waiting for interrupts, until the data arrives. Putting it into an ISR itself means those interrupts will never happen.

I kind of wondered, haven not used I2C, doesn't the I2C library have interrupts all set?

What do you mean "all set"? Inside an ISR interrupts are turned off for the duration, no matter what you might have done elsewhere.

http://gammon.com.au/interrupts

Ahh that makes a lot of sense, I should have thought of that…

Now I just need to tweak my original algorithm as it was a bit off :stuck_out_tongue:

I mean all set as in the code in the library should have those parts.

As in all set to go.