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 Likes
24.3 K Views
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

Good to hear you're making some headway with this ... but man, it sure is a challenge 😞 

I do notice that this function is using getFIFOCount() as well though - I thought (maybe I misunderstood) this function was flawed?


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

The flawed code was the function that read bytes from the FIFO


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

Ah OK - my bad! (I'm bouncing around too many topics and projects) 😉 


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

No responses on this from anyone yet.  Did I find a yet undiscovered major problem with the MPU6050?

I can't believe nobody has come across this issue yet. 

I will keep you posted.  But I am going to put this project on hold for a while. 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

Man that sucks ... I think this could also mean that you ran into an "unsolvable" bug.
As mentioned before: I ran into something like this as well with a cheap networkshield.
A 3rd party developer developed a great library, but even he did not manage to create a fix.

Are there any alternatives for the MPU6050? (for example the MPU-9250 maybe?)
Or are they relying on the same library? (potentially with the same bug)

I totally understand that you'll be putting this project on hold for now ... 😉 

Maybe one of these days I'll try to get a hold of an MPU6050 as well and see what I can figure out.


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

Thats a realy good idea.  I would look for another manufacturer

I will let you know what I find


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

I agree, another manufacturer would be a good idea.
Is there anything Arduino.cc mentions and supports with an official library?
I did see a few listed here - they do not even list the 6050. Maybe a good start.
Or see if AdaFruit has a shield - they are usually very good about support as well.


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

I tried adafruit a while back,  Their library is different and there is a sensors library which is supposed to work with all their sensors,  Problem 1 is it is poorly documented and does not work with everything,   Bigger problem is it does not work on the ESP32


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

You make a good point there ... in general, for their own specific products, they seem to be doing OK.
But I now remember how limited their LED library was (NeoPixel) compared to a more generic LED library (FastLED - which is very well documented and maintained).

I'll wait and see what you find ... in case I run into something that may be helpful, I'll post it here as well 😊 


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

I received a really interesting post on this issue today on github.  Here is the post:
"paynterf commented 5 hours ago

Don't give up on the cheap, ubiquitous MPU6050 IMU modules. I have been using them in my robot projects for years now, and they seem to be completely bullet-proof when used and driven properly. Take a look at this post on my 'Paynters Palace' blog site. You don't need to understand it in detail, but you should come away with the realization that if you use Homer Creutz's GetCurrentFIFOPacket() routine that is embedded in Jeff Rowberg's library, you can rest assured that you will get reliable, valid data from the MPU6050 whether you use the interrupt method or the polling method.

It sounds to me like you have run up against the classic I2C bus 'freeze' problem, and if so, it has nothing at all to do with the MPU6060. I2C bus freezes are a known problem with Arduino, and it has only been recently addressed. See this post for all the gory details. The good news is, if you use the latest Wire library code and add the timeout setting line to your setup() function like this

Wire.setWireTimeout(3000, true); //timeout value in uSec

then the I2C freeze problem should go away. Note that if you aren't using the latest Wire library, the above code line won't compile, so it's easy to tell one way or the other.

Hope this helps,

Frank"

 

I added the line as per his suggestion  and got a compile error that it did not have that function.  I checked my libraries and all were the latest.

I will keep you posted


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

That does sound promising, well, at least someone is tinkering with this as well.

Are you referring to the missing Wire.setWireTimout() function?
If so: you may have to download the latest version of wire.h and maybe even apply the patches mentioned in the Github Pull Request you mentioned?
Considering the age of the Pull Request, I'd imagine the Github to be updated (but looking at it: probably not yet - last change 4 months ago).


   
ReplyQuote
(@michaelzen)
Active Member
Joined: 3 years ago
Posts: 10
 

Hello gents,

 

Thank you so much for digging into this problem, I was trying to get the MPU6050 to work in this configuration but of course failed, and googling I stumbled upon this forum and of course this topic. :)

 

Now I'm a complete newbee to Arduiino, but it's coming to me fast, although I'm lost with the code you both write here, it's a lot, there has been some changes and where at the first pages the whole code was posted now it's fragments of problems that are tackled.

At the risk of being called lazy, which in fact I am with this, I wanted to ask politely if one of you could provide me with the whole code as it is now, to be honest, I get a fault message using any piece of code, something to do with my libraries, but I'm learning!

 

Hoping to have retrieved your both interest, thank you so much

Michael


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

Hi Michael,

Nothing wrong asking for the complete sketch. However, tvr4 is the one working most with this, so maybe he'd be willing to post the code he has so far.
I personally do not even own an MPU6050.

As for the error message:
It would be good to see you code and see the exact error message so one of us can chime in and help fix the error. 😉 


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

@michaelzenI do apologize for not posting the code.  I was tinkering with it so much I forgot.

Great to have another on the case.  Together hopefully we can solve it. 
I have not tinkered with the sketch for some time since we were stalled at a solution to the data freeze in the I2C bus

Here is the complete sketch

//
// ESP32-GPS-Accel_to_SD
//
// TONY
// MPU6050 Init, Calibrate, Read Data
// Display Max-G X,Y,Z on OLED
// Display GPS, Vmax, Hmax, Sats on OLED
// Write GPS and Accel to SD
// DOES NOT USE INTERRUPT
//

#define BUFFER_LENGTH 32

#include "heltec.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"

#include <TinyGPS++.h>
#include <mySD.h>

const int cs_sd=26;

int LoopCounter = 0;

int16_t rawTemp;
float tempC;
float tempF;

//GPS RX Pin-17 GREEN WIRE
//GPS TX Pin-23 YELLOW WIRE

TinyGPSPlus gps;

int maxspeed = 0, speed1 = 0;
int maxhigh = 0, high1 = 0;
int maxsatelite = 0, satelite1 = 0;

SSD1306AsciiWire oled;

MPU6050 mpu;

bool dmpReady = false; // set true if DMP init was successful
uint8_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 FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
float MaxGx = 0, MaxGy = 0, MaxGz = 0;

// orientation motion variables
Quaternion q; // [w, x, y, z] quaternion container
//VectorInt16 aa; // [x, y, z] accel sensor measurements
//VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
//VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
//VectorFloat gravity; // [x, y, z] gravity vector
//float euler[3]; // [psi, theta, phi] Euler angle container
//float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector

// ================================================================
// === SETUP ===
// ================================================================

void setup() {
Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Enable*/, true /*Serial Enable*/);
oled.begin(&Adafruit128x64, 0x3C, 16);
oled.setFont(System5x7);
oled.clear();
oled.setCursor(25,3);
oled.println("GPS and G-force");
oled.setCursor(30,4);
oled.println("Logger to SD");
delay(2000);
oled.clear();

Wire.begin(); //pin 21 and 22 for ESP32
Wire.setClock(400000); // 400kHz I2C clock

//gives error Wire.setWireTimeout(3000, true); //timeout value in uSec

// GPS RX=17, GPS TX=23
Serial1.begin(9600, SERIAL_8N1, 23, 17);

if (!SD.begin(26, 14, 13, 27))
{
oled.clear();
oled.print(" NO SD Card");
delay(2000);
oled.clear();
}
else
{oled.print(" SD Card OK");
delay(2000);
}

oled.clear();

//SD for GPS Data
File data = SD.open("GPS-data.txt",FILE_WRITE); //Open the file "GPS-data.txt"
data.println("");
data.println("Start Recording"); // Write to file
data.close();

//SD for Accel Data
File data2 = SD.open("ACC-data.txt",FILE_WRITE); //Open the file "ACC-data.txt"
data2.println("");
data2.println("Start Recording"); // Write to file
data2.close();

// initialize serial monitor
Serial.begin(115200);

// initialize I2C devices
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();

// verify I2C device connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

// load and configure the DMP
Serial.println(F("Initializing DMP..."));
oled.setCursor(0,0);
oled.println("Calibrate Acc/Gyro");
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);

// returns 0 if MPU6050 working
if (devStatus == 0)
{
// Generate offsets and calibrate MPU6050
mpu.CalibrateAccel(6);
mpu.CalibrateGyro(6);
mpu.PrintActiveOffsets();
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
oled.print("Accel/Gyro Ready");
delay(1000);
oled.clear();
mpu.setDMPEnabled(true);

// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready!"));
dmpReady = true;

// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
// get FIFO count
fifoCount = mpu.getFIFOCount();

}
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(")"));
}
}

// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop() {

//*CODE FOR GPS*
satelite1 = (abs(gps.satellites.value()));

oled.setCursor(0,0);
oled.print("Vmax ");
oled.print("Hmax ");
oled.print("SAT ");

speed1 = (gps.speed.mph());
if ( speed1 > maxspeed)
{
maxspeed = speed1;
}

oled.setCursor(0 , 1);
oled.clearToEOL();
oled.setCursor(10 , 1);
oled.print(maxspeed);

high1 = (gps.altitude.feet());
if ( high1 > maxhigh)
{
maxhigh = high1;
}

oled.setCursor(60 , 1);
oled.print(maxhigh);

oled.setCursor(100 , 1);
oled.print(satelite1);

oled.println(" ");
oled.println(" ");

//Display Lat & Long on OLED
oled.setCursor(0 , 2);
oled.print("LAT ");
oled.println(gps.location.lat(),6);
oled.print("LNG ");
oled.println(gps.location.lng(),6);

//-4 is offset for eastern time zone
String Temps=String(gps.time.hour()-4)+(":")+(gps.time.minute())+(":")+(gps.time.second());
String Date=String(gps.date.month())+("/")+(gps.date.day())+("/")+(gps.date.year());

// Writing GPS data to text file
//if (satelite1 > 1) {
File data=SD.open("GPS-data.txt",FILE_WRITE);
data.println(Date + "," + Temps + "," + String(gps.location.lat(), 6) + "," + String(gps.location.lng(), 6) + "," + String(gps.altitude.feet(),0) + "," + String(gps.speed.mph(),0) + "," + String(satelite1));
data.close();
//}

//Get temperature from MPU6050
rawTemp = mpu.getTemperature();
tempC=(rawTemp/340)+36.53;
tempF=(tempC * 9/5) + 32;

// Write ACCEL G-Force data to text file
//if (satelite1 > 1) {
File data2=SD.open("ACC-data.txt",FILE_WRITE); //Temps is string hour, minute, second
data2.println(Date + "," + Temps + "," + String(q.x, 2) + "," + String(q.y, 2) + "," + String(q.z,2) + "," + String(tempF,1));
data2.close();
//}

//ORIG Code DelayGPS(500);
//Delay of 900 gives 1 second logging interval
DelayGPS(500);

//END GPS CODE

//*BEGIN MPU6050 Code*
//mpu.resetFIFO();
//fifoCount = packetSize;

if(GetCurrentFIFOPacket(fifoBuffer, packetSize) )
{
// gets the latest packet if available and runs your code else this will skip your code because there is
// nothing new to process.
}

// display quaternion values x y z
mpu.dmpGetQuaternion(&q, fifoBuffer);
//USE THIS FOR LIVE ACCEL DATA DISPLAY
Serial.print("G-Force\t");
//Serial.print(q.w);
//Serial.print("\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;
}

//Display LIVE ACCEL G data on OLED
//oled.setCursor(0,5);
//oled.clearToEOL();
//oled.println("ACCEL X Y Z");
//oled.setCursor(0,6);
//oled.clearToEOL();
//oled.setCursor(20,6);
//oled.print(q.x,2);
//oled.setCursor(60,6);
//oled.print(q.y,2);
//oled.setCursor(95,6);
//oled.println(q.z,2);

//DISPLAY MAX G on OLED
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
//REMOVED 9/19 mpu.resetFIFO();
}

//Delay function but continue to receive date from GPS
static void DelayGPS(unsigned long ms)
{
unsigned long start = millis();
do
{
while (Serial1.available())
gps.encode(Serial1.read());
//REMOVED 9/19 mpu.resetFIFO();
} while (millis() - start < ms);
}

//BEGIN FUNCTION GetCurrentFIFOPacket
// Get the latest byte from FIFO buffer no matter how much time has passed.
// === GetCurrentFIFOPacket ===
// ================================================================
// Returns 1) when nothing special was done
// 2) when recovering from overflow
// 0) when no valid data is available
// ======================
//
int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof
LoopCounter++;

int16_t fifoC;
// This section of code is for when we allowed more than 1 packet to be acquired
uint32_t BreakTimer = micros();

Serial.println("Function Loops=" + String(LoopCounter));

do {
if ((fifoC = mpu.getFIFOCount()) > length) {

if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive
mpu.resetFIFO(); // Fixes any overflow corruption
fifoC = 0;
while (!(fifoC = mpu.getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet
} else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer
uint8_t Trash[BUFFER_LENGTH];
while ((fifoC = mpu.getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer
fifoC = fifoC - length; // Save the last packet
uint16_t RemoveBytes;
while (fifoC) { // fifo count will reach zero so this is safe
RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer
mpu.getFIFOBytes(Trash, (uint8_t)RemoveBytes);
fifoC -= RemoveBytes;
}
}
}
}
if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset
// We have 1 packet
if ((micros() - BreakTimer) > (11000)) return 0;
} while (fifoC != length);
//ORIG LINE mpu.getFIFOBytes(data, length); //Get 1 packet
mpu.getFIFOBytes(fifoBuffer, packetSize);
return 1;
}


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2678
 

Awesome trv4! Thanks for posting it! 👍 


   
ReplyQuote
Page 5 / 7
Share: