Pages: [1]   Go Down
Author Topic: Reading from Wire inside an ISR  (Read 510 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to read data from a Wire (connected to a gyroscope) from inside a function called from an interrupt service routine. I am using the FlexiTimer2 library from http://playground.arduino.cc/Main/FlexiTimer2.

The problem I am having is that whenever this function (my function I'm attaching to the interrupt) is called, the code locks up. I beleive this is due to my Wire.something() function calls, since removing them and just using some Serial.print()s allows it to work properly.

My code:

Code:
void timerTask() {
  Serial.print("Gyro X: ");
 
  int buff[10];
  Wire.beginTransmission(ADDRESS_GYRO); //start transmission to ACC
  Wire.write(0x1B);        //sends address to read from
  Wire.endTransmission(); //end transmission
 
  Wire.beginTransmission(ADDRESS_GYRO); //start transmission to ACC
  Wire.requestFrom(ADDRESS_GYRO, G_TO_READ);    // request 6 bytes from ACC
 
  int i = 0;
  while(Wire.available())    //ACC may send less than requested (abnormal)
  {
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
   
   
  Serial.print(buff[0]);
  Serial.print("\r\n");
}

And I assign my fuction to the interrupt handler here:

Code:
FlexiTimer2::set(500, timerTask);
    FlexiTimer2::start();

Is there a way for me to use Wire functions from within an interrupt, or is this not possible?

My ultimate goal is to query the gyro every so many milliseconds to get an accurate picture of how far I've rotated since I started.

Thanks for taking the time to read this...
Logged

Global Moderator
Online Online
Brattain Member
*****
Karma: 502
Posts: 19080
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Wire.beginTransmission(ADDRESS_GYRO); //start transmission to ACC
  Wire.requestFrom(ADDRESS_GYRO, G_TO_READ);    // request 6 bytes from ACC
 
  int i = 0;
  while(Wire.available())    //ACC may send less than requested (abnormal)
  {
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission

You don't need  Wire.beginTransmission and Wire.endTransmission around Wire.requestFrom.

Wire.requestFrom returns the number of bytes read.

You shouldn't be doing Serial.print inside an ISR, and the Wire library uses interrupts which is why it doesn't work.

Better is to set a flag, check that flag in the loop function, and do your stuff there.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I see... I was starting to suspect the Wire lib using interrupts was the problem.

Thanks!
Logged

0
Offline Offline
Shannon Member
****
Karma: 215
Posts: 12467
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Rather than guess about how the Wire library works remember you have the source code for it - just have a look
at it's description and comments and code!

Actually for the Wire library you'd need to look at <install>/libraries/Wire/utility/twi.c to discover the use of interrupts,
so perhaps not the most straightforward example.

Built in libraries are either at <install>/libraries/... or a few (including HardwareSerial) are at <install>/hardware/arduino/cores/arduino/...

Even if the code means nothing the big comments at the top of a library file can be very informative.
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
or is this not possible?

It is generally not possible / advisable.

The issue is with re-entrancy: you have no way of knowing that before an isr is fired, if that very (wire) function is being called.

There are solutions around it but they fundamentally don't alter the picture:

1) don't call a function from within the isr;
2) if you have to, make sure that that function isn't called anywhere else.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, I didn't think to look at the included source for the libs...

I have an alternative solution that involves not using the interrupt to handle my Wire calls (keeping track of time in my main loop with if/else and doing what I need to there)..

Thanks for the responses.
Logged

Pages: [1]   Go Up
Jump to: