Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



problem using MPU-6...
 
Share:
Notifications
Clear all

[Solved] problem using MPU-6050 Accel/Gyro with ESP32

98 Posts
3 Users
3 Reactions
29.8 K Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2864
 
Posted by: @tvr4

I am spending so much time troubleshooting that I do cleanups when I can

Haha, that's how it works for me as well 😉 

As for a delay; at the end of your "loop()" function, you have quoted out a delay statement. I presume there was a good reason for that, but maybe you'd want to to a delay, and if possible do a full reset of the MPU? Not sure if there is a function for that. Maybe "DelayGPS(100);" can be helpful/changed? 


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

@hans

Oh my, I can't believe I forgot about that.  Thanks for the second look

I wondered why someone would put a delay into the code when it seems to work without it.  Now I know why!

I read on other sites that a regular delay(xxx) would not work as the GPS module needs to be polled.  That is why the smart delay was there.  It creates a delay for the duration  called and all it does is poll the GPS.

But I think you are right, it also needs to reset the FIFO buffer or that will overflow during the wait interval

Thanks for the tip.  I will give that a test


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

Ok I did some more testing. (Sample data files from today attached).  Notes in data file are manually entered to track troubleshooting.

 

 

ISSUE1 (Data Logging Interval)
I kept increasing the DelayGPS starting at 100.

There was no consistent change in the data logging interval until 600.  Then I had to add a line to reset the MPU FIFO because it started giving FIFO overflow errors.

At DelayGPS of 800 the data was about 1 per second but it was not consistently 1 second.
At 850 the data started showing dropouts
At 900 the data was 1 per second and consistent

So it looks like that is they setup for further testing

ISSUE2 (Stop in processing and OLED display)
I added a line in the MPU loop to send "In MPU Loop" to the serial monitor

Most of the time this displays a few times but the sketch is working.
At some point the OLED stopped updating.  I looked at the serial monitor and it was stuck in the MPU loop

Here is the loop.  It is around line 266 in my code.  Not sure what needs to be change here.
This chunk of code is straight from the library example

 // wait for MPU extra packet(s) available
while (fifoCount < packetSize) {
if (fifoCount < packetSize) {
// try to get out of the infinite loop
Serial.println("In FIFO Loop");
fifoCount = mpu.getFIFOCount();
}
}

   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

A little more testing

1) Most of the time the fifocount = 0 and the packetsize = 42
Occasionally the FIFO count is a little larger but never more than 8

2) I commented out the above loop and the sketch still works.
Since the loop does not exist the code can not get stuck in an infinite loop.
I need to test further to see what happens

3) With loop commented out I am still getting occasional data dropouts of a couple seconds.
Not sure why.  Need to investigate further


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2864
 
Posted by: @tvr4

Data Logging Interval

It makes me think of one of the cheap China Ethernet-shield. The hardware works, but it somehow gets stuck or trips over "something" (this can be the library, code or the hardware).
With the Ethernet-shield I found that a full reset made it more stable again.
Now in your case, I noticed that quite a bit of work needs to be done if you'd want a full and total reset, so this may not be an option for the MPU.

Could it be some kind of buffer issue with the MPU?
Either an overflow, or maybe the MPU is just too slow ...?

If you'd like to try this little change (it's just a random test) - keep picking up the fifocount until it is not zero.
I'm not sure if getting the fifocount changes anything, but I'd assume the fifo buffer is getting filled as soon as there is a fifoCount>0 ...
Unless we need to wait for the fifocount to be at least packetsize. It would not be uncommon to wait until the buffer is filled with enough data (packetSize).

fifoCount = mpu.getFIFOCount();

// wait for MPU extra packet(s) available
while (fifoCount = 0) {
Serial.println("In FIFO Loop");
fifoCount = mpu.getFIFOCount();
}

Note doing a "while (fifoCount < packetSize)" makes the "if (fifoCount < packetSize)" redundant.
You'd only get to the "if" statement if the "while" statement is true, so we already know that "fifoCount < packetSize".

Your original loop:

// wait for MPU extra packet(s) available
while (fifoCount < packetSize) {
if (fifoCount < packetSize) { // remove this
// try to get out of the infinite loop
Serial.println("In FIFO Loop");
fifoCount = mpu.getFIFOCount();
}
}

Also note: adding Serial output does introduce a super tiny delay, which accidentally may make things work better or worse.


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

I was thinking the same thing about the if inside the while loop.  That code was part of the library example.
I submitted an issue on the github page for the library but have not had a reply yet as to why the developer put it there in the first place.  I have removed the entire loop and the sketch still works.

I have also removed some of the serial monitor output that I used for testing.  Now that I know most of the code works the only thing I send to the serial monitor is the x,y,x live values.  his way if something gets stuck I will see that stop outputting on the serial monitor.

Onward to testing. 


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

Still getting stuck in the while loop.  

It seems to be random and I can't figure out why.

It should not be getting stuck.  The serial output shows fifocount=0 and packetsize=42

This should satisfy the condition itvshpuld exit the loop.  However at times it does not exit and i have no idea why. 

while (fifoCount < packetSize)

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2864
 

Interesting, so in that first loop (fifocount<packetsize), for some odd reason it occasionally will never reach "packetsize" for the fifocount.  
What if we try something like this ... we reset the FIFO, wait 100 ms, and see if there is data. If there is data, then execute "the usual" data processing.
If not, then skip that an do the loop again.

  //added 8-29-2020
  mpu.resetFIFO();

  DelayGPS(100); // let the MPU breath for 100 ms so the buffer can get filled - you may need more time here
  fifoCount = mpu.getFIFOCount(); // new 
  
  // only execute this if packet(s) are available
  if (fifoCount >= packetSize) {

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();
    if (fifoCount < packetSize) {}
    // check for FIFO overflow
    else if (fifoCount >= 1024) {
      // reset so we can continue cleanly
      mpu.resetFIFO();
      //  fifoCount = mpu.getFIFOCount();  // will be zero after reset
      Serial.println(F("FIFO overflow!"));
    }

    // read a packet from FIFO
    while (fifoCount >= packetSize) {
      mpu.getFIFOBytes(fifoBuffer, packetSize);
      // track FIFO count in case there is > 1 packet available
      fifoCount -= packetSize;
    }

    // display quaternion values in easy matrix form: w x y z
    mpu.dmpGetQuaternion( & q, fifoBuffer);

    //USE THIS FOR LIVE ACCEL DATA DISPLAY
    //Serial.print("ACCEL\t");
    Serial.print("G-MAX\t");
    Serial.print(q.x);
    Serial.print("\t");
    Serial.print(q.y);
    Serial.print("\t");
    Serial.println(q.z);

    //calculate Max Accel X,Y,Z
    if (abs(q.x) > abs(MaxGx)) {
      MaxGx = q.x;
    } else {
      MaxGx = MaxGx;
    }

    if (abs(q.y) > abs(MaxGy)) {
      MaxGy = q.y;
    } else {
      MaxGy = MaxGy;
    }

    if (abs(q.z) > abs(MaxGz)) {
      MaxGz = q.z;
    } else {
      MaxGz = MaxGz;
    }

    oled.setCursor(0, 5);
    oled.println("MaxG   X     Y     Z");
    oled.setCursor(0, 6);
    oled.clearToEOL();
    oled.setCursor(20, 6);
    oled.print(MaxGx);
    oled.setCursor(60, 6);
    oled.print(MaxGy);
    oled.setCursor(95, 6);
    oled.println(MaxGz);
    oled.setCursor(0, 7);
    oled.println("TEMP = " + String(tempF, 1) + " F");

    //Added for stable MPU data
    mpu.resetFIFO();
  } // new
  //delay(333);
}

 

p.s. in case you're familiar with Stepper Motors (I have no experience with it), would you mind looking at this post (not a requirement)?


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

@hansVery interesting idea.  I will give that a try.

I also noticed a return; in the MPU6050 code.  The original example the code came from was a single loop dedicated to the MPU only.  So a return would not be a problem.  However, my code uses the GPS and the MPU6050.  If the MPU causes a return condition it will stop processing things that I may want it to so.
Look at this section of code. 

//If MPU6050 programming failed, don't do anything
//if (!dmpReady) return;
if (!dmpReady)
{
oled.setCursor(0,7);
oled.clearToEOL();
oled.println("DMP Not Ready !");
return; //COULD BE CAUSING A PROBLEM
}

   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

Oh and I looked at the stepper motor post.  Wondering if the issue is because he is attempting to use SPI pins for output.
From what I could gather, you can't reassign those pins.  They are hardwired in the Uno.

 


   
Hans reacted
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

Ok I did a little tinkering today.  I still do not know why the MPU causes the code to get stuck in the loop.

But I added some code to only allow the FIFO loop to occur 10 times.  Then it would force an exit of the loop.
This would guarantee that it does not get stuck in an infinite loop.

Upon exiting the loop the counter would be 10 and I set fifoCount = packetSize; to cause it to read a packet from the MPU

Here is the basic code

LoopCounter = 0;

while (fifoCount < packetSize && LoopCounter < 10)
{
     fifoCount = mpu.getFIFOCount();
     LoopCounter++;
}

if (LoopCounter = 10)
{
     fifoCount = packetSize;
}


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

I forgot to mention that I believe I found the cause of the data dropouts.  Occasionally the number of GPS satellites drops to 0 since I am running this indoors.

It was only writing to the data file if the number of satellites was > 1
In these conditions it would not write to the data file and it would appear a missing data entry.
The delayGPS may not be as critical as I thought.  But I will leave it as is for now

The reason I added this code is to prevent the numerous entries of junk until the GPS starts receiving valid data. 
In these cases the date and time are constant until actual GPS data begins.

I can check for the date condition instead.  I need to work on this later

Will keep you posted


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2864
 

Thanks for chiming in with the Stepper motor question - maybe this way we will get more like-minded people here discussing their Arduino projects 😊 

All this still makes me wonder if it is the library or the code in the MPU that is not working 100% OK ...? (like the example with the cheap Ethernet shield I had mentioned)

I do like your "count 10 times" approach! To expand on that one, you could also try something like this: instead of waiting for fifoCount to reach at least packetSize, maybe wait for fifoCount > 0, and after that do your "usual" loop?

 

I did see that the variable "satelite1" (goes for speed1 and high1 as well) was not defined as a specific type - line 33 just says:

satelite1 = 0;

This should probably be something like (this can be byte or int, unless the function "gps.satellites.value" requires a specific type):

byte satelite1 = 0;

And since that variable is only used in the loop() function, you can probably remove the line all together and change this line:
(you defined it as a global variable, where it only needs to be a local variable)

satelite1 = (abs(gps.satellites.value()));

to:

byte satelite1 = (abs(gps.satellites.value()));

(same for speed1 and high1)

 

Also note: I tend to break my code up in functions, so the main loop() functions becomes more manageable.
I do this typically by moving stuff that goes together and works correctly, into a specific function.
This way you can read the code easier and it becomes easier to debug (disable/modify pieces of code).
(just a thought, not a requirement)

 


   
ReplyQuote
 tvr4
(@tvr4)
Estimable Member
Joined: 5 years ago
Posts: 122
Topic starter  

Great ideas.  I was wondering the same thing about the library.  Unfortunately the developer, Electronic Cats, has not replied.

The page states that it is Based in the work of jrowberg/i2cdevlib
I think I need to go to the source since he developed the initial lib and code

I like the function idea.  I was thinking about that but got sidetracked with all the troubleshooting.
It is basically two functions now, GPS Stuff and MPU Stuff.  I just need to move the code into functions.

I think the FIFO count idea you had is a good idea.
Looking over the serial monitor output and studying the MPU6050 datasheet it seems that the fofocount of 0 means that it does not have any valid bytes ready to read.  The datasheet specifically warns against reading bytes in this case.

But the questions are:
1) why isn't there any valid data
2) why does'n the FIFO load as the code is running

The packetsize is 42 and when the ficicount = 42 it exits the loop like it should.
But what is keeping theFIFO from populating?  (reading cycle too fast? too many resetFIFO?)

I need to look at this stuff later when I have more time


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2864
 

Going through the library would be a way to go, but I can imagine it to be a challenge. 😞 
Too bad the developer is not responding (yet). Do they have a github page where you can submit an issue?

Splitting things in smaller functions makes things much more readable and maintainable. But I'll admit; when I'm tinkering with code I pretty much work the same way you do 😉 
Cleaning up in the code and putting things in specific functions is something I typically start doing when the concept code works 😊 

Do you think this forum post could be useful for the issue?

The writer suggest the pgm_read_byte() definition in 'MPU6050.cpp' from a ported I2CDev library was incorrect and resulted in the wrong data being written to the MPU's memory.
For reference, the correct definition is:

#define pgm_read_byte(addr) (*(const unsigned char *)(addr))

I don't have the library handy so I cannot check.


   
ReplyQuote
Page 3 / 7
Share: