Created Tue, 05 Sep 2017 00:11:15 +0000 by ricklon
Tue, 05 Sep 2017 00:11:15 +0000
I'm using the Fubarion Mini and the Sparkfun mpu-9250 (https://www.sparkfun.com/products/13762). I'm using there example library and it responds for a while sending data and then stops. Serial data is no longer being sent. I've looked at it with a logic analyzer and the data going back and forth seems OK. The interrupt pin is being toggled. I can't find anywhere in the code this pin is being used.
Any tips on debugging the problem?
I simplified the code and this is what I'm using:
#include "MPU9250.h"
#define SerialDebug true // Set to true to get Serial output for debugging
int myLed = PIN_LED1; // Set up pin 13 led for toggling
boolean state = true;
unsigned int loop_cnt = 0;
MPU9250 myIMU;
void getData() {
// If intPin goes high, all data registers have new data
// On interrupt, check if data ready interrupt
if (myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01)
{
myIMU.readAccelData(myIMU.accelCount); // Read the x/y/z adc values
myIMU.getAres();
// Now we'll calculate the accleration value into actual g's
// This depends on scale being set
myIMU.ax = (float)myIMU.accelCount[0] * myIMU.aRes; // - accelBias[0];
myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes; // - accelBias[1];
myIMU.az = (float)myIMU.accelCount[2] * myIMU.aRes; // - accelBias[2];
myIMU.readGyroData(myIMU.gyroCount); // Read the x/y/z adc values
myIMU.getGres();
// Calculate the gyro value into actual degrees per second
// This depends on scale being set
myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes;
myIMU.gy = (float)myIMU.gyroCount[1] * myIMU.gRes;
myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes;
myIMU.readMagData(myIMU.magCount); // Read the x/y/z adc values
myIMU.getMres();
// User environmental x-axis correction in milliGauss, should be
// automatically calculated
myIMU.magbias[0] = +470.;
// User environmental x-axis correction in milliGauss TODO axis??
myIMU.magbias[1] = +120.;
// User environmental x-axis correction in milliGauss
myIMU.magbias[2] = +125.;
// Calculate the magnetometer values in milliGauss
// Include factory calibration per data sheet and user environmental
// corrections
// Get actual magnetometer value, this depends on scale being set
myIMU.mx = (float)myIMU.magCount[0] * myIMU.mRes * myIMU.magCalibration[0] -
myIMU.magbias[0];
myIMU.my = (float)myIMU.magCount[1] * myIMU.mRes * myIMU.magCalibration[1] -
myIMU.magbias[1];
myIMU.mz = (float)myIMU.magCount[2] * myIMU.mRes * myIMU.magCalibration[2] -
myIMU.magbias[2];
} // if (readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01)
// Must be called before updating quaternions!
myIMU.updateTime();
myIMU.delt_t = millis() - myIMU.count;
if (myIMU.delt_t > 500)
{
Serial.println("My delta is > 500");
if (SerialDebug)
{
// Print acceleration values in milligs!
Serial.print("X-acceleration: "); Serial.print(1000 * myIMU.ax);
Serial.print(" mg ");
Serial.print("Y-acceleration: "); Serial.print(1000 * myIMU.ay);
Serial.print(" mg ");
Serial.print("Z-acceleration: "); Serial.print(1000 * myIMU.az);
Serial.println(" mg ");
// Print gyro values in degree/sec
Serial.print("X-gyro rate: "); Serial.print(myIMU.gx, 3);
Serial.print(" degrees/sec ");
Serial.print("Y-gyro rate: "); Serial.print(myIMU.gy, 3);
Serial.print(" degrees/sec ");
Serial.print("Z-gyro rate: "); Serial.print(myIMU.gz, 3);
Serial.println(" degrees/sec");
// Print mag values in degree/sec
Serial.print("X-mag field: "); Serial.print(myIMU.mx);
Serial.print(" mG ");
Serial.print("Y-mag field: "); Serial.print(myIMU.my);
Serial.print(" mG ");
Serial.print("Z-mag field: "); Serial.print(myIMU.mz);
Serial.println(" mG");
myIMU.tempCount = myIMU.readTempData(); // Read the adc values
// Temperature in degrees Centigrade
myIMU.temperature = ((float) myIMU.tempCount) / 333.87 + 21.0;
// Print temperature in degrees Centigrade
Serial.print("Temperature is "); Serial.print(myIMU.temperature, 1);
Serial.println(" degrees C");
}
myIMU.count = millis();
digitalWrite(myLed, state); // toggle led
state = !state;
delay(10);
}
}
void setupIMU() {
// Read the WHO_AM_I register, this is a good test of communication
byte c = myIMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
Serial.print("MPU9250 "); Serial.print("I AM "); Serial.print(c, HEX);
Serial.print(" I should be "); Serial.println(0x71, HEX);
if (c == 0x71) // WHO_AM_I should always be 0x68
{
Serial.println("MPU9250 is online...");
// Start by performing self test and reporting values
myIMU.MPU9250SelfTest(myIMU.SelfTest);
Serial.print("x-axis self test: acceleration trim within : ");
Serial.print(myIMU.SelfTest[0], 1); Serial.println("% of factory value");
Serial.print("y-axis self test: acceleration trim within : ");
Serial.print(myIMU.SelfTest[1], 1); Serial.println("% of factory value");
Serial.print("z-axis self test: acceleration trim within : ");
Serial.print(myIMU.SelfTest[2], 1); Serial.println("% of factory value");
Serial.print("x-axis self test: gyration trim within : ");
Serial.print(myIMU.SelfTest[3], 1); Serial.println("% of factory value");
Serial.print("y-axis self test: gyration trim within : ");
Serial.print(myIMU.SelfTest[4], 1); Serial.println("% of factory value");
Serial.print("z-axis self test: gyration trim within : ");
Serial.print(myIMU.SelfTest[5], 1); Serial.println("% of factory value");
// Calibrate gyro and accelerometers, load biases in bias registers
myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias);
myIMU.initMPU9250();
// Initialize device for active mode read of acclerometer, gyroscope, and
// temperature
Serial.println("MPU9250 initialized for active data mode....");
// Read the WHO_AM_I register of the magnetometer, this is a good test of
// communication
byte d = myIMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963);
Serial.print("AK8963 "); Serial.print("I AM "); Serial.print(d, HEX);
Serial.print(" I should be "); Serial.println(0x48, HEX);
// Get magnetometer calibration from AK8963 ROM
myIMU.initAK8963(myIMU.magCalibration);
// Initialize device for active mode read of magnetometer
Serial.println("AK8963 initialized for active data mode....");
if (SerialDebug)
{
// Serial.println("Calibration values: ");
Serial.print("X-Axis sensitivity adjustment value ");
Serial.println(myIMU.magCalibration[0], 2);
Serial.print("Y-Axis sensitivity adjustment value ");
Serial.println(myIMU.magCalibration[1], 2);
Serial.print("Z-Axis sensitivity adjustment value ");
Serial.println(myIMU.magCalibration[2], 2);
}
} // if (c == 0x71)
else
{
Serial.print("Could not connect to MPU9250: 0x");
Serial.println(c, HEX);
while (1) ; // Loop forever if communication doesn't happen
}
}
void setup() {
Wire.begin();
Serial.begin(38400);
delay(5000);
pinMode(myLed, OUTPUT);
digitalWrite(myLed, HIGH);
setupIMU();
}
void loop() {
Serial.println(loop_cnt++);
getData();
}
Tue, 05 Sep 2017 17:35:04 +0000
Rick,
Just to be more clear about your situation - you have the IMU connected to the FBMini's I2C bus, correct?
Where are you seeing the interrupt line toggling? At the IMU's INT output? That sounds normal to me - the IMU is simply announcing to the world that it has something to say. I'm assuming you did not connect the IMU's INT output to the FBMini, correct? Your library is probably polling the interrupt register of the IMU and seeing that it has something to say, so there's no reason to care about the INT pin.
When you say "it responds for a while sending data and then stops" do you mean the I2C communications between the FBMini and the IMU stops? Or the serial traffic to the PC? If the I2C traffic stops, I'd be interested in seeing a Logic Analyzer trace of the last I2C transaction before things stop.
*Brian
Tue, 05 Sep 2017 19:21:51 +0000
I'm connect to hardware i2c pins 25, 26. I've attached the INT pin on the board to pin 24. I used the Saleae analyzer and I see 24 toggling and data on pins 25 and 26 the correspond to I2c. I also had the onboard led blinking.
Between 30 - 60 secs in stops blinking and no serial data is being sent. The MPLAB X debugger only gives me the option to pause and when I do it is in the I2C code area.
What's the best way to share the logic analyzer data?
--Rick
Tue, 05 Sep 2017 21:31:36 +0000
If (as I suspect) the library us using the Wire library then it could be suffering from Wire's inability to handle any kind of hiccup even remotely well. It likes to lock up solid waiting for an ACK or something that never arrives.
Wed, 06 Sep 2017 00:41:58 +0000
Rick,
I'd throw the LA trace up on Google Drive or something and share the link here.
I agree with Matt - the Wire library is very weak. You could try using DTWI instead - but that would require digging into the library a bit.
The X debugger won't help you much until you really understand the library code, and can step through the I2C calls that are failing. You can use the stack trace to try and see why the upper layers of the library/program think that there's a problem, or if you're stuck in an infinite loop, etc. Also you can post code snipits here showing where the I2C code is breaking/looping.
*Brian
Wed, 06 Sep 2017 08:33:39 +0000
Here's an example of how I abstract DTWI in my libraries:
It's just as blocking as Wire at the moment, but should be adaptable to allow you to debug what is actually happening and where the lockup is occuring.
Tue, 12 Sep 2017 15:36:23 +0000
I'll give using that library a try.
I have found that I had two sets of wires connected in the middle. As soon as that middle got bumped or loose it stopped working. I did things like unplug scl, and sda and replicated the stop reading and never start again behavior.
I tried short cables and it worked better. But not 100%.
I'll make these changes and test. I'll put the results up on Google Drive.