Balancing Bot Proje...
Clear all

Balancing Bot Project

6 Posts
3 Users
New Member
Joined: 3 years ago
Posts: 4
Topic starter  

Hello all, and thanks for any help in advance.

I am currently working on a balancing bot. At this point i have managed to build a working bot and so in lies the problem, it's a boring bot. I would like to add user control via IR communication. Now the fun part is that I would like to use a joystick to control the bot, my issue is that im not sure how to implement the joystick value's across IR.

My second issue is how to account for the movement with the P.I.D. that controls the bots balance.


for the sake of curiosity, i have chosen to use IR because it's the only parts i have to make a controller cordless.

Balancing bot code used by my bot slightly modified for my use.

i have video of my bot, the first bot video is horrible but worked, the second V2 is much better, but still issues (since Fixed in code below) just search my channel  Eric Collyer on YouTube.

/*Arduino Self Balancing Robot
* Code by: B.Aswinth Raj
* Build on top of Lib:
* Website:

#include "I2Cdev.h"
#include <PID_v1.h> //From
#include "MPU6050_6Axis_MotionApps20.h" /

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

/******Tune these 4 values for your BOT***/
double setpoint= 183.14; //set the value when the bot is perpendicular to ground using serial monitor.
//Read the project documentation on to learn how to set these values
double Kp = 17; //Set this first
double Kd = 0.5; //Set this second
double Ki = 25; //Finally set this
End of values setting******/

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

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

void setup() {
TCCR1B = TCCR1B & B11111000 | B00000001; // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000001; // set timer 2 divisor to 1 for PWM frequency of 31372.55 Hz

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

// 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
devStatus = mpu.dmpInitialize();

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

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

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

//Initialise the Motor outpu pins
pinMode (3, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
pinMode (11, OUTPUT);

//By default turn off both the motors

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

//Print the value of Input and Output on serial monitor to check how it is working.
Serial.print(input); Serial.print(" =>"); Serial.println(output);

if (input>150 && input<200){//If the Bot is falling

if (output>0) //Falling towards front
Forward(); //Rotate the wheels forward
else if (output<0) //Falling towards back
Reverse(); //Rotate the wheels backward
else //If Bot not falling
Stop(); //Hold the wheels still


// 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); //get value for q
mpu.dmpGetGravity(&gravity, &q); //get value for gravity
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); //get value for ypr

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


void Forward() //Code to rotate the wheel forward
Serial.print("F"); //Debugging information

void Reverse() //Code to rotate the wheel Backward

void Stop() //Code to stop both the wheels

New Member
Joined: 3 years ago
Posts: 4
Topic starter  
Posted by: @tinkerinman

Now the fun part is that I would like to use a joystick to control the bot, my issue is that im not sure how to implement the joystick value's across IR.

ok, so upon further learning, i have managed to figure out the joystick control, for the most part, but i am still left with the issue of adding the control to the bot.

New Member
Joined: 3 years ago
Posts: 4
Topic starter  

Wow, well it has been some time since i have posted on this bot project. Anyway i have kinda given up on the bot simply due to my lack of knowledge using the arduino.

Noble Member Admin
Joined: 3 years ago
Posts: 1165


But that is how you learn about the Arduino, by digging into something, trying to assemble it, making mistakes, and learning from those mistakes.  And when you're stumped, coming to the forum for help and advice.

We've all been there and done that!  We weren't born with the knowledge!


Noble Member Admin
Joined: 3 years ago
Posts: 1165


And instead of using IR, which is limited in its movement capabilities, how about using RF?

Looking into using the nRF24L01.  One on the Bot and one on the joystick control.


Noble Member
Joined: 8 months ago
Posts: 959

Although this is an old thread, I got here as part of a search and I think others will also and thought I'd give two options.  

  1. If you really want a physical joy-stick type control, here is a great paper on the subject of a balancing robot that has a physical controller.  However, it uses WiFi instead of your desired IR.  Benefit is longer range and line-of-sight is not required.   I used this paper (but not the controller) in my robot build extensively.
  2. I use just WiFi, a web server on the robot and serve client pages to any browser and have a virtual joystick.  Downside - it doesn't have tactile feedback.  Upside - It's free.  It's available on any device and it is very easy to automate computer control through coding on higher-end CPUs. It only has to be implemented only once and will work on future robot projects in the future.



3 lines of code = InqPortal = Complete IoT, App, Web Server w/ GUI Admin Client, Access Point Manager, Drag & Drop File Manager, OTA, Performance Metrics, Web Socket Comms, Easy App API, All running on ESP8266...
Even usable on ESP-01S - Quickest Start Guide