Need help with MPU6050

I am building a self balancing robot using the arduino nano , mpu6050 , 2 generic dc motors and a L298n motor driver , even though i have seen many youtube videos where people just wire them up , put the code and voila...the robot does its thing , but i have been stuck with the mpu6050 showing erratic readings whenever the battery is connected and the motors are under load ,as one can see when the power is provided only through USB the values shown in the serial monitor are fine , but when the motors are under load , the values are absolute garbage causing my motors to have an epilepsy attack

when connected only with usb


when the motor is under load

i saw a prior post on the same issue , where he fixed it by applying a timeout , so that the I2C bus doesn't go berserk , but that did not help

//Self Balancing Robot
#include <PID_v1.h>
#include <LMotorController.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
 #include "Wire.h"
#endif

#define MIN_ABS_SPEED 30

MPU6050 mpu;


bool dmpReady = false; 
uint8_t mpuIntStatus; 
uint8_t devStatus;
uint16_t packetSize; 
uint16_t fifoCount;
uint8_t fifoBuffer[64];

Quaternion q; 
VectorFloat gravity; 
float ypr[3]; 

//PID
double originalSetpoint = 180.76;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;


double Kp = 60;   
double Kd = 2.2;
double Ki = 270;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

double motorSpeedFactorLeft = 0.9;
double motorSpeedFactorRight = 0.9;

//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 9;
int IN4 = 8;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);

volatile bool mpuInterrupt = false; 
void dmpDataReady()
{
 mpuInterrupt = true;
}


void setup()
{
  Serial.begin(9600);
 
 #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
 Wire.begin();
 Wire.setWireTimeout(3000, true); // add this line
 TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
 #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
 Fastwire::setup(400, true);
 #endif

 mpu.initialize();

 devStatus = mpu.dmpInitialize();

 
 mpu.setXGyroOffset(0);
 mpu.setYGyroOffset(0);
 mpu.setZGyroOffset(0);
 mpu.setZAccelOffset(0);

 if (devStatus == 0)
 {

 mpu.setDMPEnabled(true);


 attachInterrupt(0, dmpDataReady, RISING);
 mpuIntStatus = mpu.getIntStatus();

 dmpReady = true;


 packetSize = mpu.dmpGetFIFOPacketSize();

 pid.SetMode(AUTOMATIC);
 pid.SetSampleTime(10);
 pid.SetOutputLimits(-255, 255); 
 }
 else
 {

 Serial.print(F("DMP Initialization failed (code "));
 Serial.print(devStatus);
 Serial.println(F(")"));
 }
}


void loop()
{

 if (!dmpReady) return;

 while (!mpuInterrupt && fifoCount < packetSize)
 {

 pid.Compute();
 motorController.move(output, MIN_ABS_SPEED);
 
 }


 mpuInterrupt = false;
 mpuIntStatus = mpu.getIntStatus();

 fifoCount = mpu.getFIFOCount();

 if ((mpuIntStatus & 0x10) || fifoCount == 1024)
 {

 mpu.resetFIFO();
 Serial.println(F("FIFO overflow!"));


 }
 else if (mpuIntStatus & 0x02)
 {

 while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();


 mpu.getFIFOBytes(fifoBuffer, packetSize);
 

 fifoCount -= packetSize;

 mpu.dmpGetQuaternion(&q, fifoBuffer);
 mpu.dmpGetGravity(&gravity, &q);
 mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
 input = ypr[2] * 180/M_PI ;
 Serial.println(input);
 }
}



this is the code im using

This seems to be a power supply issue.

Take measures to provide the control elements with stable clean 5 volts at adequate current.

See how it rolls then.

You may want to look into modern motor controllers, there's been some progress since the 20th century.

That might reduce the demand on your battery and extend running time.

But you will always have to have good clean power for the electronics.

a7

Can't compile, the LMotorController.h can't be found.

Since you have a power problem (especially with the ancient L298), showing /telling us about your power will help.

I would like to see an annotated schematic of your project showing all connections power sources etc and links to technical information on the major components including motors (NEMA is mechanical).

Any clues from the five 'Related topics' at bottom of thread?

Probably a power problem as other have said, but your example MPU output shows the chip in an upside down position where it is just on the point of flicking between +180 and -180. What do you see if you have it right way up so it's sitting somewhere near zero? Do you get the same wild swings?

I ran your code and it works fine to get the values from the DMP.

Personally I find the way your code is structured unintuitive and hard to read (not your fault, you're just following the example). I like to have all the mpu.getXXX stuff inside a function that gets called from loop(). In my own self-balancing robot reading the MPU is just one of many tasks and I like to have them all called from loop(). Makes the code more readable.

Also you don't need the interrupt and a rolling average on the MPU output smooths things down a bit.

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"

MPU6050 accelgyro;

int16_t ax, ay, az;
int16_t gx, gy, gz;

bool blinkState = false;
bool toggle = 0;

// MPU control/status vars
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

// orientation/motion vars
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
float rollArray [10] = {0,0,0,0,0,0,0,0,0,0}; // array to hold previous roll values for averaging
int numSamples = 4;                           // number of accelerometer readings over which to form a rolling average
double measuredRoll;                          // current averaged roll in degrees

double readMPU() {                                   // Function to read data and return value in degrees
  accelgyro.resetFIFO();
  fifoCount = accelgyro.getFIFOCount();
  while (fifoCount < packetSize) {                   // wait for correct available data length, should be a VERY short wait
    fifoCount = accelgyro.getFIFOCount();
  } 
  accelgyro.getFIFOBytes(fifoBuffer, packetSize);    // read a packet from FIFO   
  fifoCount -= packetSize;     // track FIFO count here in case there is > 1 packet available (lets us immediately read more without waiting for an interrupt) 
  accelgyro.dmpGetQuaternion(&q, fifoBuffer);        // get all accelerometer data
  accelgyro.dmpGetGravity(&gravity, &q);
  accelgyro.dmpGetYawPitchRoll(ypr, &q, &gravity); 
  double sum = 0;                                     // this section averages out the latest numSamples readings                          
  double avg = 0;                                     // value returned to PID loop is a rolling average updated every time there's new data
  for (int i = numSamples-1; i > 0; i--){             // rollArray [0] holds most recent, rollArray[numSamples] holds oldest
    rollArray[i] = rollArray[i-1];                    // shuffle rollArray[3] into rollArray[4] etc. But not rollArray[0]...see below
    sum = sum + rollArray[i];
  }
  rollArray[0] = ypr[1];                              // load newest position in rollArray[] with current roll value 
  sum = sum + rollArray[0];                           // and accumulate in sum
  avg = sum / numSamples;                             // form the average
  return avg * 180 / M_PI;                            // convert radians to degrees and return to PID control 
} 


void setup() {
  delay(2000);
  Serial.begin(115200);

  Wire.begin();
  Wire.setClock(400000); // 400kHz I2C clock. Comment this line out if having compilation difficulties
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();
  Serial.println(F("Testing device connections..."));
  Serial.println(accelgyro.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  Serial.println(F("Initializing DMP..."));
  devStatus = accelgyro.dmpInitialize();
  if (devStatus == 0) {
    Serial.println(F("Enabling DMP..."));
    accelgyro.setDMPEnabled(true);
    Serial.println(F("DMP ready! Waiting for data..."));
    dmpReady = true;
    packetSize = accelgyro.dmpGetFIFOPacketSize();
  }
  else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }   
}

void loop() {
  measuredRoll = readMPU();
  Serial.println(measuredRoll);
  delay(200); // slow down serial print; remove if full speed is required
}

the power is being provided with 6 AA batteries and the 12v socket of the l298,
also as for the motor drivers , can you suggest any?
best regards

none sadly :(

powering it using 6 AA batteries in series

i built a breadboard diag b4 on fritzing

The Nano should be powered, if you have stable adequate 5 volts, by the 5V pin, not Vin.

And it should probably better come from a separate regulator drawing its power from your battery pack.

You could apply the 9 volts from the pack to the Vin pin and let the Nano regulate it for itself and the things you've attached to Vcc, but there is a limit to the current you can draw and there will be some waste due to the linear regulator on the Nano board.

a7

Don't like fritzing, use your eyes and a pencil in your hand. What we want to know is did you wire it correctly.

You will first need a basic maths course. That will lead you to your power situation.

You will get better results with a modern driver, the L298 is basically a toaster. Try checking on Pololu, they have LOTS!

Edit. .. deleted.

Sorry but a fuzzy diagram is not a schematic!

As @sonofcy indicates the L298 is a toaster, it drops 3 volts because of its bipolar internal structure. Multiply your current by 3 and that will give you the amount of watts lost to heating your toast.

Good Luck!