Hi,
I'm trying to log yaw, pitch and roll data from an IMU (MPU6050, using the Sparkfun breakout board (https://www.sparkfun.com/products/11028)) to a microSD card (using the Sparkfun microSD Shield (SparkFun microSD Shield - DEV-12761 - SparkFun Electronics)). I'm using an Arduino Uno R3, Arduino 1.0.5, and some Sparkfun logic level converters between the Arduino and the sensor.
My sketch uses Jeff Rowberg's I2Cdevlib (i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub) to communicate with the MPU6050. For some reason, my sketch just halts after around half a minute, sometimes more, sometimes less.
The example sketch in the library (at https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino) seems to be able to run indefinitely. My sketch is essentially the same as this example, but with uneeded output formats removed, and logging to an SD card instead of outputting sensor readings to Serial. My sketch also closes and reopens the log file on the card every 10 seconds, to ensure that data is actually written onto the card, and writes a timestamp to the log.
Suspecting a problem with either the microSD shield or the card itself, I tried just writing data continuously to the card - nothing went wrong with this.
Suspecting a shortage of RAM, I've tried monitoring memory usage using MemoryFree.h (Arduino Playground - AvailableMemory). There is a constant 746 bytes available on the Arduino, right up to when it crashes, so memory is probably not the problem.
I've also tried using the Fastwire I2C implementation in I2Cdevlib (as opposed to the default Wire.h), but even the example sketch doesn't work with it - it just stops after announcing its intention to initialise the processor on the sensor. After enabling debugging output in I2Cdevlib, it just ends up repeatedly printing I2C (0x68) reading 2 bytes from 0x72.... Done (-1 read).
When I tried running my sketch using the Wire.h I2C implementation and with debugging output enabled, to see if there were any abnormalities in the communication between the Arduino and sensor, it ran for a record 245 seconds, with no apparent abnormalities prior to halting. There were over 1000 FIFO overflows, which aren't supposed to happen at all, but because they don't occur without debugging output enabled, I think they were just caused by the delay in writing the debugging output via Serial.
My sketch:
#include <SD.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050_6Axis_MotionApps20.h>
#include <MemoryFree.h>
const int CS = 8;
File logFile;
MPU6050 mpu;
char filename[] = "000";
uint8_t deviceStatus; // 0 indicates success
uint8_t mpuIntStatus; // interrupt status byte
uint16_t packetSize; // expected DMP packet size
uint16_t fifoCount; // number of bytes in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
unsigned long startTime = 0;
unsigned long previousTime = 0;
unsigned long currentTime = 0;
Quaternion q; // [w, x, y, z] quaternion container
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
void error()
{
while (true);
}
volatile bool mpuInterrupt = false;
void dmpDataReady()
{
mpuInterrupt = true;
}
void setup()
{
Serial.begin(115200);
// -------------------------------------------------SD
Serial.print(F("Initialising SD card... "));
pinMode(10, OUTPUT);
pinMode(CS, OUTPUT);
if (!SD.begin(CS))
{
Serial.println(F("failed"));
error();
}
Serial.println(F("succeeded"));
// -------------------------------------------------MPU
Serial.print(F("Initialising IMU... "));
Wire.begin();
TWBR = 24;
mpu.initialize();
Serial.println(F("done"));
// test connection
Serial.print(F("Testing IMU connection... "));
Serial.println(mpu.testConnection() ? F("succeeded") : F("failed"));
// -------------------------------------------------DMP
Serial.print(F("Initialising DMP... "));
deviceStatus = mpu.dmpInitialize();
if (deviceStatus == 0)
{
// turn DMP on
mpu.setDMPEnabled(true);
// set interrupt
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// get expected DMP packet size
packetSize = mpu.dmpGetFIFOPacketSize();
Serial.println(F("succeeded"));
}
else
{
Serial.println(F("failed"));
error();
}
// -------------------------------------------------LOG
// look for unused filename
Serial.print(F("Opening log... "));
logFile = SD.open(filename, FILE_WRITE);
Serial.print(F("succeeded opening "));
Serial.println(filename);
startTime = millis();
previousTime = startTime;
logFile.print(F("T"));
logFile.println(startTime);
Serial.print(F("S"));
Serial.println(previousTime);
}
void loop()
{
// wait until MPU is ready
while (!mpuInterrupt && fifoCount < packetSize);
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow
if ((mpuIntStatus & 0x10) || fifoCount == 1024)
{
mpu.resetFIFO();
Serial.println(F("ERROR: FIFO overflow"));
}
else if (mpuIntStatus & 0x02) // check for data ready interrupt
{
// wait for correct data length
while (fifoCount < packetSize)
fifoCount = mpu.getFIFOCount();
// read packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count in case more than 1 packet is available
// (allows us to read more without waiting for interrupt)
fifoCount -= packetSize;
// get data
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
// log data
logFile.println(ypr[0] * 180/M_PI);
logFile.println(ypr[1] * 180/M_PI);
logFile.println(ypr[2] * 180/M_PI);
}
currentTime = millis();
Serial.print(F("M: "));
Serial.print(freeMemory());
Serial.print(F(" P: "));
Serial.print(previousTime);
Serial.print(F(" C: "));
Serial.println(currentTime);
if (currentTime >= (previousTime + 10000))
{
Serial.println(F("CYCLE"));
// close log to ensure changes are written
logFile.close();
// open log again
logFile = SD.open(filename, FILE_WRITE);
logFile.print(F("T"));
logFile.println(currentTime);
previousTime = currentTime;
}
}
Would anyone have any ideas about what could be causing the Arduino to halt? Thanks.