LeStef31 Posted July 12, 2014 Report Share Posted July 12, 2014 Hi, my name is Stephane, 44 yo, and I'm a software engineer. I'm working on Segway clone as a hobby.. I'm facing an issue when I make LCD updates via I2C when DMP is activated. The program run a few seconds then hangs. The same code run well in the MPU6050_RAW, that is why I'm concerned about the fact that the DMP is conflicting. I've tried with pullpups resistors, different LCD libraries, delays, without interuption etc .. and now I'm out of ideas. Here is the code, it's 99% the same as MPU6050_DMP6 + LCD parts in bold Any idea ? Thanks Stephane // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files// for both classes must be in the include path of your project#include "I2Cdev.h"#include "MPU6050_6Axis_MotionApps20.h"//#include "MPU6050.h" // not necessary if using MotionApps include file#include <LiquidCrystal_I2C.h>// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation// is used in I2Cdev.h#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE#include "Wire.h"#endif// class default I2C address is 0x68// specific I2C addresses may be passed as a parameter here// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)// AD0 high = 0x69MPU6050 mpu(0x69); // <-- use for AD0 highLiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address#define OUTPUT_READABLE_YAWPITCHROLLlong time10Hz = 0;long currentMillis;#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)bool blinkState = false;// MPU control/status varsbool dmpReady = false; // set true if DMP init was successfuluint8_t mpuIntStatus; // holds actual interrupt status byte from MPUuint8_t devStatus; // return status after each device operation (0 = success, !0 = error)uint16_t packetSize; // expected DMP packet size (default is 42 bytes)uint16_t fifoCount; // count of all bytes currently in FIFOuint8_t fifoBuffer[64]; // FIFO storage buffer// orientation/motion varsQuaternion q; // [w, x, y, z] quaternion containerVectorInt16 aa; // [x, y, z] accel sensor measurementsVectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurementsVectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurementsVectorFloat gravity; // [x, y, z] gravity vectorfloat euler[3]; // [psi, theta, phi] Euler angle containerfloat ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector// ================================================================// === INTERRUPT DETECTION ROUTINE ===// ================================================================volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone highvoid dmpDataReady() { mpuInterrupt = true;}// ================================================================// === INITIAL SETUP ===// ================================================================void setup() { // join I2C bus (I2Cdev library doesn't do this automatically)#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true);#endif // initialize serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) Serial.begin(115200); while (!Serial); // wait for Leonardo enumeration, others continue immediately // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to // the baud timing being too misaligned with processor ticks. You must use // 38400 or slower in these cases, or use some kind of external separate // crystal solution for the UART timer. // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); // verify connection Serial.println(F("Testing device connections...")); Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); // wait for ready Serial.println(F("\nSend any character to begin DMP programming and demo: ")); while (Serial.available() && Serial.read()); // empty buffer while (!Serial.available()); // wait for data while (Serial.available() && Serial.read()); // empty buffer again // load and configure the DMP Serial.println(F("Initializing DMP...")); devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); // 1688 factory default for my test chip // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); } lcd.begin(20, 4); // initialize the lcd lcd.backlight(); lcd.clear(); // configure LED for output pinMode(LED_PIN, OUTPUT);}// ================================================================// === MAIN PROGRAM LOOP ===// ================================================================void loop() { // if programming failed, don't try to do anything if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) { fifoCount = mpu.getFIFOCount(); } // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize;#ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180 / M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180 / M_PI); Serial.print("\t"); Serial.println(ypr[2] * 180 / M_PI);#endif currentMillis = millis(); if (currentMillis - time10Hz >= 100) { loopAt10Hz(); time10Hz = currentMillis; } // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); }}void loopAt10Hz(){ lcd.setCursor(0, 1); lcd.print(currentMillis);} Quote Link to comment Share on other sites More sharing options...
Vulpo Posted July 12, 2014 Report Share Posted July 12, 2014 My guess is that the problem comes from the FIFO used by the DMP code. I have the same problem but with an XBee instead of an LCD screen, and from what I observed is that after a moment the data from the FIFO is corrupted (one chunk of the data is lostlost, leading to a global byte shift) and the program hangs as a consequence. Sometimes I can see some corrupted data being transmitted a few seconds before it stops. I did not resolve the problem, but I am trying to find a way to use DMP without the FIFO. Maybe that's the way to go. Quote Link to comment Share on other sites More sharing options...
LeStef31 Posted July 12, 2014 Author Report Share Posted July 12, 2014 Hi, yes you are probably right about the FIFO. I've played a lot with the code and found that reseting the fifo after each read has an impact. I sometime see corrupted values as well. After many hours struggling with this, I'm about to abandon the DMP and work with raw data.. :-(( Let me know if you find someting without fifo .. Thanks Stephane Quote Link to comment Share on other sites More sharing options...
Vulpo Posted July 13, 2014 Report Share Posted July 13, 2014 I have tried everything I could, with no success. I also looked at the official library (see http://www.i2cdevlib.com/forums/topic/153-official-dmp-documentation-is-released-by-invensense/ ) but it doesn't seem to be a function for that, and don't find any "dmp register value" in the register map. I guess I will stick to the raw values and try to calibrate a Kalman filter or whatever. Quote Link to comment Share on other sites More sharing options...
LeStef31 Posted July 13, 2014 Author Report Share Posted July 13, 2014 Hi Vulpo, I've struggle some more hours this morning ... 2 weeks of my off-time ... :-( I'll go raw values too, they are plenty of kalman/complementary examples for mpu6050 available. Nevertheless, our unusable DMP values will allow us to validate what we will compute with raw values. See you Stéphane Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.