0

Overflow enthusiasts!

I am trying to log accelerometer and gyro data using Serial.print. I have enabled the FIFO_Overflow interrupt. Whenever I log data, the serial port freezes. I am suspecting an interrupt issue while I am using Serial.print. Is there any way to get continuous data for debugging purposes? I know that the Serial library can affect interrupts and wonder whether you guys could help me a little bit ?

#include "Wire.h"    
#include "I2Cdev.h"
#include "MPU9150.h"
#include "helper_3dmath.h"

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU9150 accelGyroMag;    
#define LED_PIN 13
volatile boolean state_fifo_int = false;
uint16_t fifo_count;
uint8_t fifo_buffer[8];
int16_t acc_temp[3];
int16_t gyro_x;

void setup(){
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();    
    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(115200);
    // initialize device
    Serial.println("Initializing I2C devices...");
    accelGyroMag.initialize();
    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(accelGyroMag.testConnection() ? "MPU9150 connection successful" : "MPU9150 connection failed");
    // configure Arduino LED for
    pinMode(LED_PIN, OUTPUT);
    attachInterrupt(0,fifo_int,CHANGE);
}

void fifo_int() {
  state_fifo_int = true; 
}

void loop(){
  while(!state_fifo_int) {
    accelGyroMag.setIntFIFOBufferOverflowEnabled(true);
    // enable fifo_interrupt
    accelGyroMag.setFIFOEnabled(true);
    accelGyroMag.setAccelFIFOEnabled(true);
    accelGyroMag.getXGyroFIFOEnabled();
    accelGyroMag.getAccelFIFOEnabled();
    fifo_count = accelGyroMag.getFIFOCount();
    accelGyroMag.getFIFOBytes(fifo_buffer,8); // fill in fifo bytes
    acc_temp[0] = (((int16_t)fifo_buffer[0]) << 8) | fifo_buffer[1];
    acc_temp[1] = (((int16_t)fifo_buffer[2]) << 8) | fifo_buffer[3];
    acc_temp[2] = (((int16_t)fifo_buffer[4]) << 8) | fifo_buffer[5];
    gyro_x = (((int16_t)fifo_buffer[6]) << 8) | fifo_buffer[7];
    Serial.print((float)acc_temp[0]/16384);
    Serial.print("  ");
    Serial.print((float)acc_temp[1]/16384);
    Serial.print(" ");
    Serial.print((float)acc_temp[2]/16384);
    Serial.print(" ");
    Serial.println(gyro_x);
   }
   accelGyroMag.setIntFIFOBufferOverflowEnabled(false);
   // disable fifo_interrupt
   accelGyroMag.resetFIFO();
   state_fifo_int = false;
}

The library for the MPU9150 is by Jeff Rowberg.

3
  • Do you guys think it will work without the Serial.print library ? I cant approve if i get the right values. Dont want my project to crash. – ozzmanli Aug 8 '15 at 17:03
  • Whenever I log data, the serial port freezes - after how much data? A line? 100 lines? – Nick Gammon Aug 9 '15 at 3:02
  • Arbitrary 50-70 lines – ozzmanli Aug 9 '15 at 11:22
1

When I've gotten into a bind with data being generated faster than I can dump it, or the process cannot tolerate the printing delays, I've made a memory buffer to store as much raw data as I can and print it after the test-run. If you're not using a debugger (which can print memory contents), you'll still need to have serial print code in your sketch but it can execute after the you run the code under test. Store the minimum size raw data (to maximize the amount you can store) and do the formatting on your PC.
If you need to be able see what happened prior to an unusual event your code can detect, use a ring buffer (FIFO) in memory and let it wrap around (don't even bother to detect wrap-around). As soon as your code detects the event, print the ring-buffer contents.
It's not continuous capture but often, it's enough.

1

After reading the datasheet on the PS manual, I found out that the INT1 pulse had a width of 50uS.

So what I simply did was to declare a global integer and check it at the end of the loop.

Whenever I checked the incremented variable at the end, it was 48!.I personally suspected that my loop speed was to slow. Additionally the timeout value 14 ms per loop arbitrary. Clearly a disparity exists in the interrupt routine for the sensor and the microcontroller.

So what I simply did was to reconfigure the sensor output to a latched signal which clearly solved the problem. I am now getting synchronized interrupt with convincing results.

Here is the code:

#include "Wire.h"    
#include "I2Cdev.h"
#include "MPU9150.h"
#include "helper_3dmath.h"

#define LED_BUILTIN 13

MPU9150 accelGyroMag; 

volatile boolean state_fifo_int = false;
int x = 0;

void blink(uint16_t offTime, uint16_t onTime){
digitalWrite(LED_BUILTIN,HIGH);
if(onTime) delay(onTime);
digitalWrite(LED_BUILTIN,LOW);
if(offTime) delay(offTime);
}

void resetSensor(){
  accelGyroMag.reset();
  delay(50);
  accelGyroMag.initialize();
  //Serial.println("Initialize if connection test failed");

  if(accelGyroMag.testConnection()){ //disable interrupts
     accelGyroMag.setIntFIFOBufferOverflowEnabled(false);
     // disable fifo_interrupt
     accelGyroMag.resetFIFO();
        // verify connection

     //Serial.println("Connection tested successfully, Disabling interrupts");
     }
if(!accelGyroMag.testConnection()){ // try to recover sensor
  accelGyroMag.initialize();
    //Serial.println("Initialize if connection test failed");
  }
if(accelGyroMag.testConnection()){  // reconfigure sensor for Fifo and interrupts

   accelGyroMag.setFIFOEnabled(true);
   accelGyroMag.setXGyroFIFOEnabled(true);
   accelGyroMag.setAccelFIFOEnabled(true);
   accelGyroMag.setInterruptMode(false);// Set interrupt logic level mode 0 = active-high
   accelGyroMag.setInterruptLatch(true); //set interrupt 1=latch-until-int-cleared ( latch after INT_STATUS READ)
   accelGyroMag.setIntFIFOBufferOverflowEnabled(true);

   }
else {
 // Serial.println("MPU9150 connection failed");
  //Serial.println("locking UP");
  while(true){
     for(uint8_t i=0;i<3;i++){blink(50,100);} // S
     delay(250);
     for(uint8_t i=0;i<3;i++){blink(50,300);} // O
     delay(250);
     for(uint8_t i=0;i<3;i++){blink(50,100);} // S
     delay(500);
    }
  }
}

void setup(){
  Wire.begin();    
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
// other stuff
  attachInterrupt(0,fifo_int,RISING);
  resetSensor();
}

void fifo_int() {
  x++;
  state_fifo_int = true;

}

static unsigned long timeout = 0; // used to detect dead sensor/connection
uint16_t fifo_count;
uint8_t fifo_buffer[8];
int16_t acc_temp[3];
int16_t gyro_x;

void loop(){

  if(state_fifo_int){ // interrupt has triggered
    blink(0,1);  // really quick blink // really quick blink
    //Serial.println(x);
    state_fifo_int = false;
    accelGyroMag.resetFIFO();
    accelGyroMag.getFIFOBytes(fifo_buffer,8); // fill in fifo bytes
    accelGyroMag.getIntFIFOBufferOverflowStatus(); // read the INT_STATUS reg in order to clear the Latch. 
    acc_temp[0] = (((int16_t)fifo_buffer[0]) << 8) | fifo_buffer[1];
    acc_temp[1] = (((int16_t)fifo_buffer[2]) << 8) | fifo_buffer[3];
    acc_temp[2] = (((int16_t)fifo_buffer[4]) << 8) | fifo_buffer[5];
    gyro_x = (((int16_t)fifo_buffer[7]) << 8) | fifo_buffer[8];

    timeout = millis();

  }

 if((millis()-timeout)>1000){ //last interrupt was over 1 second ago! better reset Sensor!
   blink(100,500);
   blink(100,500);

   resetSensor();
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.