Self Balancing Robot

Hello everyone

I am doing a self balancing robot as my graduation project but I am having some issues with it. I am using everything from as well as the code this link below

but I am using either Arduino Micro (Original) or Arduino UNO R3 (Clone) or Arduino Pro Mini (that is probably a clone as well).

I tired testing the Arduino micro with the MPU6050 to check if it reads the code but I get stuck on "initializing I2C devices..." for a long time. I switched to Arduino UNO and Pro mini and both work.

My issue is my robot is working but only the first seconds it works when it is tilted to the back but not with a frontal tilt. after some time it doesn't recognize that I am tilting for some reason but also kind of does as the motors give me different sound when I tilt forward but but the wheels don't rotate.

I've been working on this project for over a year now, I built another one before this one and it didn't work so I had to abandon it for this design and still not working. I still have to add Ultra Sonic Sensor and a GPS or something for it to rotate in a square and to detect a body or an object that comes in front of it.

This is supposed to be my graduating project and it's just been killing me and I have to deliver it by the end of this year. I would appreciate it if you could help me with this project.

It really sounds like you have not developed and tested in a modular way, where you can fully understand and test sub systems independently. Probably, you now have a huge sketch with thousands of lines and you don't know where to start troubleshooting. Am I right? Have you tested the hardware with simple sketches to verify the correct operation of the accellerometer, motors, etc.?

The problem with that is, we will have the same problem. But we don't even have your hardware (most of us anyway). Also it's a senior project. Senior means you are supposed to have been learning the approaches to tackling this kind of project. The ability to troubleshoot is a huge part of engineering. It makes it possibly unethical to help very much.

Your problems with the importance, difficulty and urgency are really not our problem, they are your problems.

But if you post some details of your hardware such as schematics, diagrams, images and so on, someone might spot an obvious problem. It does sound like maybe a motor control issue.

I already have been troubleshooting this many times and still don't know the reason why it's always not working properly.
I found out that my last MPU-6050 was broken so I bought new ones to test if it was the issue, and it was.

Now, when I used my Arduino Micro for some reason I get stuck on "Initializing I2C devices..." I tried scanning it and also the get stuck "Scanning devices..." so I switched to Arduino UNO R3 (Clone) to see if it would work, and it did.

But, for now my motors work and then after some seconds now they only move but a tiny bit clockwise and counterclockwise like a mm. I tried with a different UNO clone and still the exact same issue.

I Checked if the MPU was broken but when I checked it it was working as it didn't give me any errors about DMP unable to initialize it but when I tried processing it to the 3D sample view and it wasn't moving whenever I move the MPU around.

This is A schematic of my board

This is the code

#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 20

MPU6050 mpu;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
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
VectorFloat gravity;    // [x, y, z]            gravity vector
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

//PID
double originalSetpoint = 165; 
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;
int moveState=0; //0 = balance; 1 = back; 2 = forth
double Kp = 50; // First adjustment
double Kd = 0; // Second adjustment
double Ki = 0; // Third adjustment
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT); // kp = 55,kd=0.9

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

//timers
long time1Hz = 0;
long time5Hz = 0;

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
    mpuInterrupt = true;
}


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

    // 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"));

    // 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();
        
        //setup PID
        
        pid.SetMode(AUTOMATIC);
        pid.SetSampleTime(10);
        pid.SetOutputLimits(-255, 255);  
    }
    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(")"));
    }
}


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)
    {
        //no mpu data - performing PID calculations and output to motors
        
        pid.Compute();
        motorController.move(output, MIN_ABS_SPEED);
        
    }

    // 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;

        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
        #if LOG_INPUT
            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
        input = ypr[1] * 180/M_PI + 180;
   }
}

I am planning to try 9-DOF Gyro board Like Adafruit's or Sparkfun's if I find them available in my area, but I am not sure if it is advisable with Self-Balancing Robot.

One of the problems of using someone else’s code is debugging and understanding what is happening - you are effectively building a kit and not developing anything and then struggling when it doesn’t work .
I would start with a simple sketch to see if I can drive the motors from say a pot , then write something simple to see if you are getting the signals correctly from the 6050 when you tilt it about .
Have a good look at debugging techniques , using print statements , leds etc. Then how the Pid loop works ( maybe make a simple closed loop control - eg a heater , or bulb brightness).
Then go back to your sketch , or better still build something yourself - At some point you will have to explain your work to whoever marks it .If you haven’t developed any of it, and only copied what someone else made, the marks will be low !

Good luck