self balancing Robot with Arduino

Arduino Self balancing robot

A self-balancing robot is interesting to make with the Arduino. it is eye-catchy to see the robot balance by itself. the robot having only two tires and only on these two tires the robot balance its own weight. there are three types of self-balancing robot

1. Self-balancing robot having PID controller.

2. self-balancing robot having an encoder motor

3. the bot they have both above feature.

the most stable is the 3rd one. because it has both mechanisms. so it balances quite good.

It is work on the accelerometer principle. there is an accelerometer uses in the self-balancing robot on the top of the bot. so, if there is any til noted in the robot the accelerometer changes its value to according to the axis. there is 3 axis inside the sensor which can note the tilt in any direction or angle.for example when the bot tilt in the forward direction the change comes in any direction which can be sent to the Arduino.  and now Arduino will decide the step to run. and the same process will be for the condition of tilting backward.

Component Required for a self-balancing robot

  • Arduino Uno
  • Accelerometer
  • dc motor
  • motor driver
  • wires
  1. Accelerometer


  1. Arduino Uno


  1. DC Motor


4. Motor Driver



circuit diagram for a self-balancing robot



code for a self-balancing robot


// <PID_v1.h>

#include <LMotorController.h>

#include “I2Cdev.h”

#include “MPU6050_6Axis_MotionApps20.h”


#include “Wire.h”


#define MIN_ABS_SPEED 20MPU6050 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 containerVectorFloat gravity; // [x, y, z] gravity vector

float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector


double originalSetpoint = 173;

double setpoint = originalSetpoint;

double movingAngleOffset = 0.1;

double input, output;

//adjust these values to fit your own design

double Kp = 60;

double Kd = 1.4 ;

double Ki = 70;

PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

double motorSpeedFactorLeft = 0.6;

double motorSpeedFactorRight = 0.6;


int ENA = 5;

int IN1 = 6;

int IN2 = 7;

int IN3 = 8;

int IN4 = 9;

int ENB = 10;

LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft,


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)



TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)


Fastwire::setup(400, true);



devStatus = mpu.dmpInitialize();

// supply your own gyro offsets here, scaled for min sensitivity




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


// enable Arduino interrupt detection

attachInterrupt(0, dmpDataReady, RISING);

mpuIntStatus = mpu.getIntStatus();

// set our DMP Ready flag so the main loop() function knows it’s okay to use it

dmpReady = true;

// get expected DMP packet size for later comparison

packetSize = mpu.dmpGetFIFOPacketSize();

//setup PID



pid.SetOutputLimits(-255, 255);





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





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


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


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

input = ypr[1] * 180/M_PI + 180;



Upload the given code into the arduino uno;

What do you think?

3 points
Upvote Downvote

Written by shahid

Leave a Reply

Your email address will not be published. Required fields are marked *

How to make a Robotic arm with multiple servos

Wifi Surveillance Rover