Balancing Robot help jittery

Help!! I can’t seem to balance my robot. I’ve used several codes and several PID’s, but my Bot is still jittering.
Using arduino, mpu6050, drv8833, 6v motor, 6v power supply.
I need a tutor that can help me with my project. botarduinoforum

#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 LOG_INPUT 0
#define MANUAL_TUNING 1
#define LOG_PID_CONSTANTS 0 //MANUAL_TUNING must be 1 to change
#define MOVE_BACK_FORTH 0
#define LOG_BT 0

#include<SoftwareSerial.h>
const int rxpin = 11; // pin used to receive (not used in this version) 
const int txpin = 4; // pin used to send to LCD
SoftwareSerial blue(rxpin, txpin);

// for BT control
String content = "";
float d_speed = 0.1;
float rotate = 0;
float d_rot = 5;

#define MIN_ABS_SPEED 30

#define MIN_P 0
#define MAX_P 100000
#define MIN_I 0
#define MAX_I 50000
#define MIN_D 0
#define MAX_D 5000

//MPU
MPU6050 mpu;
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
#if MANUAL_TUNING
  double kp , ki, kd;
  double prevKp, prevKi, prevKd;
#endif
double originalSetpoint = 180 + 3.00;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.3;
double input, output;
int moveState=0; //0 = balance; 1 = back; 2 = forth

#if MANUAL_TUNING
  PID pid(&input, &output, &setpoint, 0, 0, 0, DIRECT);
#else
  PID pid(&input, &output, &setpoint, 70, 240, 1.9, DIRECT);
#endif

//MOTOR CONTROLLER
#define ENA 10
#define IN1 8
#define IN2 12
#define ENB 9
#define IN3 6
#define IN4 7

LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, 1, 1);

//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()
{   blue.begin(9600);
    blue.setTimeout(10);
   
    // 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
    Serial.begin(250000);
    
    // 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

    // 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);
        motorController.move(output+rotate, output-rotate, MIN_ABS_SPEED); 
        
        unsigned long currentMillis = millis();

        if (currentMillis - time1Hz >= 1000)
        {   loopAt1Hz();
            time1Hz = currentMillis;
        }
        
        if (currentMillis - time5Hz >= 5000)
        {   loopAt5Hz();
            time5Hz = currentMillis;
        }
    }

    // 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(",");
            Serial.println(setpoint - originalSetpoint);
            // Serial.print("\t");
            // Serial.println(ypr[2] * 180/M_PI);
            
        #endif
        input = ypr[1] * 180/M_PI + 180;
   }

      if(blue.available())
    {  content=blue.readString();
       #if LOG_BT
            Serial.print("content: ");Serial.print(content);
            Serial.print(" - setpoint: "); Serial.print(setpoint);
            Serial.print(" - rotation: "); Serial.println(rotate);
       #endif
       
       if(content[0]=='F')
         {setpoint += d_speed; setpoint = constrain(setpoint, originalSetpoint-3, originalSetpoint+3);}  // forward
       else if(content[0]=='B')
         {setpoint -= d_speed; setpoint = constrain(setpoint, originalSetpoint-3, originalSetpoint+3);}  // backward
       else if(content[0]=='L')
         {rotate -= d_rot; rotate = constrain(rotate, -30, 30);}        //left
       else if(content[0]=='R')
         {rotate += d_rot; rotate = constrain(rotate, -30, 30);}        // right
    }
}


void loopAt1Hz()
{ 
#if MANUAL_TUNING
    setPIDTuningValues();
#endif
}


void loopAt5Hz()
{ 
#if MOVE_BACK_FORTH
    moveBackForth();
#endif
}


//move back and forth

void moveBackForth()
{   moveState++;
    if (moveState > 2) moveState = 0;
    
    if (moveState == 0)
      setpoint = originalSetpoint;
    else if (moveState == 1)
      setpoint = originalSetpoint - movingAngleOffset;
    else
      setpoint = originalSetpoint + movingAngleOffset;
}

//PID Tuning (3 potentiometers)

#if MANUAL_TUNING
void setPIDTuningValues()
{  readPIDTuningValues();
   if (kp != prevKp || ki != prevKi || kd != prevKd)
   {
#if LOG_PID_CONSTANTS
      Serial.print(kp);Serial.print(", ");Serial.print(ki);Serial.print(", ");Serial.println(kd);
#endif

      pid.SetTunings(kp, ki, kd);
      prevKp = kp; prevKi = ki; prevKd = kd;
    }
}


void readPIDTuningValues()
{   int potKp = analogRead(A0);
    int potKi = analogRead(A1);
    int potKd = analogRead(A2);
        
    kp = map(potKp, 0, 1023, MIN_P, MAX_P) / 100.0; 
    ki = map(potKi, 0, 1023, MIN_I, MAX_I) / 100.0; 
    kd = map(potKd, 0, 1023, MIN_D, MAX_D) / 100.0; 
}
#endif

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.